BLE lifecycle memory: true BLE-off on nRF52, NimBLE host pools to PSRAM on S3 - #10902
BLE lifecycle memory: true BLE-off on nRF52, NimBLE host pools to PSRAM on S3#10902thebentern wants to merge 3 commits into
Conversation
…AM on S3 nRF52: when config.bluetooth.enabled is false, leave the SoftDevice entirely off instead of fully initializing SoftDevice + Bluefruit and then muting advertising (the #4055-era workaround). Being "off" was costing ~3.5 KB of Bluefruit heap plus ~6 KB of BLE/SOC task stacks on a ~115 KB arena. With the SD disabled the BSP flash driver stays on its synchronous path (the same path every boot already uses before Bluefruit.begin()), checkSDEvents() keys off useSoftDevice, and the deep-sleep GPREGRET writes now mirror lfs_assert()'s direct-register fallback. clearBonds() still lazily brings the stack up for explicit bond maintenance; re-enabling bluetooth applies via reboot, so no runtime re-init path is needed. NRF52Bluetooth::startDisabled() is removed. ESP32-S3 with PSRAM: new esp32s3_psram_base sets CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL=y so NimBLE host pools (MSYS mbufs, GATT/CCCD tables, bond storage) allocate from PSRAM, freeing ~5-8 KB of internal DRAM on the WiFi+BLE coexistence path. Controller memory (CONFIG_BT_CTRL_*) stays internal. All PSRAM S3 envs re-parent to the new base; non-PSRAM envs are unchanged (verified by resolving the merged custom_sdkconfig per env). Native suite 535/535; rak4631 builds green. Hardware validation (pairing matrix, BT-off soak for the #4055 ghost) tracked in the PR.
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Comment |
⚡ Try this PR in the Web FlasherWarning This is an automated, unreviewed CI test build. Back up your device configuration Supported boards built by this PR (26)
Build artifacts expire on 2026-08-05. Updated for |
Firmware Size Report22 targets | vs
Show 17 more target(s)
Updated for 8a8d4f4 |
|
Hardware validation on rak4631 (integration build with the full heap PR stack, 120-node NodeDB):
Updated checklist state — still open: multi-day BT-off soak (the #4055 ghost; the test rig can run it), phone pairing matrix (needs a phone), and the ESP32-S3 PSRAM half (needs an S3+PSRAM board). |
The first sweep only caught envs whose platformio.ini declares BOARD_HAS_PSRAM; another 23 variant dirs (42 envs) get the flag from their board JSON instead (EoRa-S3/Hub, t-beam-1w, t-watch-s3, tbeam-s3-core, unphone, vision-masters, mesh-tab, sensecap-indicator, t-deck-pro, wismesh-tap-v2, and friends). Re-parent them all to esp32s3_psram_base; inheritance verified by statically resolving the merged custom_sdkconfig per env (all 42 gain CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL=y; non-PSRAM controls heltec-v3 / heltec-wsl-v3 stay clean). Hardware-validated on a CDEBYTE EoRa-S3 (embedded 2 MB quad PSRAM): NimBLE initializes and advertises normally with host pools in PSRAM, and free internal DRAM in the client-attached steady state rises from 161,608 B to 179,296/178,828 B across boots - about 17.5 KB reclaimed, comfortably above the 5-8 KB estimate.
|
ESP32-S3 PSRAM half validated on hardware (CDEBYTE EoRa-S3, ESP32-S3 with embedded 2 MB quad PSRAM
Coverage fix pushed (3d0b7cc): the original sweep only re-parented envs whose platformio.ini declares Still open before undraft: nRF52 BT-off multi-day soak, and a phone pairing/bond matrix on both platforms. |
nRF52: being "off" should be free
When
config.bluetooth.enabled == false, the firmware previously fully initialized SoftDevice + Bluefruit and then muted advertising — the #4055-era workaround ("device hangs several days after boot", root cause never found). Being off cost ~3.5 KB of Bluefruit heap plus ~6 KB of BLE/SOC FreeRTOS task stacks, out of a ~115 KB arena.This PR leaves the SoftDevice entirely off in that case:
setBluetoothEnable()short-circuits and clearsuseSoftDevice, socheckSDEvents()stops polling.GPREGRETwrites (DFU_MAGIC_SKIP) now mirrorlfs_assert()'s existing pattern: trysd_power_gpregret_*, fall back to a directNRF_POWER->GPREGRETwrite when the SD isn't enabled.NRF52Bluetooth::startDisabled()is removed.clearBonds()keeps its lazy bring-up for explicit bond maintenance, and re-enabling bluetooth applies via reboot, so no runtime re-init state machine is needed.Why this is safe: with the SD disabled, the Adafruit BSP flash driver checks
sd_softdevice_is_enabled()per operation and takes its synchronous path — the exact path every boot already uses for all filesystem work beforeBluefruit.begin()runs.HardwareRNGuses the CC310, not the SD.sd_*calls with the SD disabled return an error code rather than faulting (thelfs_assertfallback has relied on this for years). The failure mode this deliberately revisits is the un-root-caused #4055 hang — hence draft + soak test below, and the change is a one-branch revert if the ghost reappears.(Note: the nrf54l15 platform carries its own copy of the
startDisabled()workaround — left untouched here, flagged as follow-up.)ESP32-S3 + PSRAM: NimBLE host pools out of internal DRAM
New
esp32s3_psram_base(variants/esp32s3/esp32s3.ini) addsCONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL=y; all PSRAM S3 envs re-parent to it. NimBLE host allocations (MSYS mbufs, GATT/CCCD tables, bond storage) move to PSRAM, freeing ~5–8 KB of internal DRAM where WiFi+BLE coexistence hurts most. Controller memory (CONFIG_BT_CTRL_*) intentionally stays internal. Bond record formats are unchanged, sopurgeIncompatibleBleBonds()(#10741) does not trigger.Non-PSRAM envs are untouched — verified by statically resolving the merged
custom_sdkconfigper env (t-deck/station-g2/thinknode-g3 gain the flag; heltec-v3 does not).Verification so far
Hardware checklist before undrafting
ESP.getFreeHeap()delta and nopurgeIncompatibleBleBondson same-version reboot