Move OTA_HEAP_CONTEXT from two hand-edited envs to a pre-script gated on
build.mcu == "esp32", so every classic ESP32 image gets it and none can drift.
S2/S3/C-series and nRF52 keep the .bss singleton: they have no equivalent
static-DRAM ceiling, so there a guaranteed-present workspace is the better
trade for what is ultimately a recovery path. It has to be a build flag rather
than a header default, because OTA_HEAP_CONTEXT must hold the same value in
every translation unit that sees OtaContext.h - OtaContext.cpp included - and a
header test on CONFIG_IDF_TARGET_ESP32 would depend on include order relative
to sdkconfig.h. The script defers to OTA_SHARED_COMPANION_QUEUE where a Full
Companion recipe already owns the storage.
Fix a gap this exposes in the roles that now use it. Only CLI entry points
acquire the context, so once it was released, a repeater with the temporary
radio profile up would no longer serve or announce its own firmware - LoRa OTA
would look enabled and silently do nothing. ota_service_temp_radio_context()
holds the workspace for exactly the temp-radio window and hands it back
outside it, which is where the saving was coming from anyway. Wired into the
repeater, room server and sensor loops; the Companion keeps its own
acquire-on-host-demand policy, since its context is borrowed from the offline
message queue and must not be taken speculatively.
Static DRAM, classic ESP32 (bytes occupied of a 124,580 region):
Heltec_v2_repeater 108,332 -> 70,732
Heltec_v2_room_server 83,716 -> 68,300
Heltec_v2_companion_radio_ble 123,236 -> 107,772 (was failing on main)
Tbeam_SX1262_repeater 86,932 -> 71,468
Tbeam_SX1262_repeater_observer_mqtt 121,132 -> 83,532 (was failing)
Classic ESP32 links into a dram0_0_seg of only 124,580 bytes: memory.ld
carves the BT controller's 0xdb5c (56,156) reservation off the 0x2c200
window before the application gets any. Three large objects dominated what
was left, and Tbeam_SX1262_repeater_observer_mqtt overran the build's 8 KiB
static reserve by 4,744 bytes.
Heap-allocate them instead, each with a defined behaviour when the
allocation fails:
- OtaContext: generalize the Companion's borrowed-storage path behind
OTA_DYNAMIC_CONTEXT and add OTA_HEAP_CONTEXT, which allocates the context
on first use and frees it once no transfer, apply or folder link needs it.
A repeater is idle nearly all the time, so the workspace is usually absent.
Exhaustion is reported to the caller and the operation declines.
- ClientACL: the client table becomes a pointer with a live capacity;
capacity 0 refuses new clients rather than writing through a null table.
- MyMesh flood packet filters: likewise, with flood_packet_filter_slots as
the live bound for every rule loop. At capacity 0 the node forwards
unfiltered, and both save paths refuse to write so a stored ruleset is
never replaced by an empty file.
Also override the Arduino SDK's weak btInUse() in simple_repeater so
initArduino() releases the BT controller memory to the heap. That grows the
runtime heap these tables now come from; it cannot recover the same
reservation from the linker's static window.
Static DRAM, classic ESP32:
Heltec_v2_repeater 108,332 -> 70,732
Tbeam_SX1262_repeater_observer_mqtt 121,132 -> 83,532 (was failing)
Keep stealth separate from custom, saved-random and rotating MAC policies without migrating the development MAC mode. Persist authenticated peer state, guard advertising transitions and recovery, and expose the setting through the CLI and WebConfig.
Add regression and CI checks and record exact XIAO BLE pairing, reconnect, reboot and address-rotation hardware results.
Bind Companion replies to request transports, make dual-CDC USB sessions nonblocking and reconnect-safe, and harden nRF52 watchdog/OTA storage paths. Fix T096 button debounce, display wake, sleep races, and the compact message layout; add exact WisBlock OTA profiles plus expanded native/static/HIL documentation.