fix(mem): reclaim internal DRAM — PSRAM LAN RX buffer, PSRAM-only WiFi/tinfl - #140
Merged
Merged
Conversation
…i/tinfl
ESP32-S3 was panicking repeatedly (six identical PANIC resets, same Saved PC,
each following a BLE pipe-write). Cause is internal-DRAM exhaustion, not a
pointer fault: ESP.getMinFreeHeap() is MALLOC_CAP_INTERNAL only, and on every
wake cycle that ran a BLE pipe-write it bottomed out at 48-264 bytes. Wake boots
stack NimBLE (~65 KB) plus WiFi/LWIP/mDNS and the FastEPD cold bring-up (~49 KB)
against the ~98 KB left after the mbedTLS record slots are reserved at boot.
Two changes, one theme: the DRAM-expensive features are now built only for parts
that have the DRAM.
1. tcpReceiveBuffer moves to PSRAM. It was a 16 KB permanently-resident .bss
array and the largest app-owned static buffer, yet the link-owner rule leaves
it idle during every BLE transfer. odLanReserveRxBuffer() reserves it once at
boot, PSRAM first, internal DRAM as a fallback (a board with dead PSRAM boots
silently under CONFIG_SPIRAM_IGNORE_NOTFOUND=1, so the fallback logs a
warning). Never freed. If reservation fails, startLanServer() refuses to
listen rather than accepting a socket the parser cannot serve.
The declaration moves to wifi_service.h with OD_LAN_RX_BUFFER_SIZE. It was
defined in main.h and re-declared `extern uint8_t[16384]` in wifi_service.cpp
with the size literal duplicated: C++ does not mangle namespace-scope variable
names, so converting one side to a pointer and not the other would have linked
cleanly and then read the buffer's first bytes as a pointer. Both
sizeof(tcpReceiveBuffer) sites become the constant in the same change --
sizeof on a pointer yields 8 and would have collapsed LAN reads to a few bytes
per tick, reading as a network fault rather than a code bug.
2. -DOPENDISPLAY_ENABLE_WIFI is removed from esp32-c3-N4, esp32-c6-N4 and
esp32-c3-N16. That flag has exactly two consumers -- OPENDISPLAY_HAS_WIFI
(wifi_service.h) and OPENDISPLAY_USE_TINFL (od_inflate_tinfl.h) -- so one edit
per env drops both the LAN transport and tinfl's tables on the parts with no
PSRAM to relocate anything into. Neither gate derivation changes; the flag is
the single control point, and the invariant "set it only on -DBOARD_HAS_PSRAM
envs" is documented in wifi_service.h and per-env in platformio.ini. Nothing
in code enforces it.
BREAKING for those three targets: they become BLE-only (no LAN push, mDNS or
TLS-PSK) and fall back to uzlib for inflate on every compressed path,
including BLE. The uzlib path already ships on esp32-N4 and nrf52840custom.
Measured, .dram0 static:
esp32-s3-N16R8 .bss 111,960 -> 95,592 (-16,368 B)
esp32-c3-N4 .bss 89,120 -> 60,712,
.data 15,641 -> 11,505 (-32,544 B total)
nrf52840custom ELF byte-identical to before
All 12 targets in .github/firmware-targets.json build.
Not yet verified on hardware: the min-heap figure on a wake cycle with a BLE
pipe-write (expect ~16 KB where it was 48-264 B), and uzlib throughput on C3/C6.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
ESP.getMinFreeHeap()which isMALLOC_CAP_INTERNAL-only).tcpReceiveBuffer(the 16 KB LAN RX reassembly buffer) moves from a static.bssarray to a runtime allocation that prefers PSRAM viaodLanReserveRxBuffer(), falling back to internal DRAM with a logged warning if PSRAM is absent/dead.startLanServer()now refuses to listen if reservation failed rather than accepting a socket the parser can't serve.-DOPENDISPLAY_ENABLE_WIFIis removed fromesp32-c3-N4,esp32-c6-N4, andesp32-c3-N16(no PSRAM to relocate anything into) — this also dropsOPENDISPLAY_USE_TINFL's ~15 KB of tables on those parts, since both gates share the same flag. Those three targets become BLE-only (no LAN push, mDNS, or TLS-PSK) and fall back to uzlib for inflate, same asesp32-N4/nrf52840customalready do.Measured
.dram0static:esp32-s3-N16R8:.bss111,960 → 95,592 (−16,368 B)esp32-c3-N4:.bss89,120 → 60,712,.data15,641 → 11,505 (−32,544 B total)nrf52840custom: ELF byte-identicalAll 12 targets in
.github/firmware-targets.jsonbuild; verified all 16 platformio.ini envs (including both debug variants andesp32-wrover-e-N4R8) build clean.Test plan
pio runacross all 16 environments — all SUCCESS