nrf52: fix BLE-task stack overflow crashing pairing and wiping LittleFS (#11190)

Since #10967 made Router::sendLocal handle self-addressed packets
synchronously, the entire phone-API chain for a BLE client runs inline in
the Bluefruit characteristic write callback: toRadioWriteCb ->
PhoneAPI::handleToRadio -> admin set-config -> radio reconfigure ->
NodeDB::saveToDisk. That callback executes on the Bluefruit BLE FreeRTOS
task, whose stock stack is 5 KB (CFG_BLE_TASK_STACKSIZE = 256*5 words) -
not the Arduino loop task that #10944 already raised to 8 KB. The loop-task
fix therefore protects the wrong task for BLE-originated writes.

On a Seeed Wio Tracker L1 the 5 KB stack overflows during pairing
first-sync, resetting the device mid-LittleFS-write, every single time.
Repeated mid-write resets tear the LittleFS metadata, lfs_assert fires on
the next boot, and the corruption handler formats the whole filesystem:
region, channels, module config, and the node's keypair are all lost
(critical fault #13, new node identity on next region set). Reproduced
end-to-end tonight on stock develop 6908d27; with this change the same
device pairs, serves config screens, and survives back-to-back
config.proto saves over BLE.

Raise the BLE task to the same 2048 words (8 KB) as LOOP_STACK_SZ, for the
same reason. bluefruit.cpp's #ifndef guard makes the -D take effect with no
framework patch. Costs 3 KB of RAM on nrf52840 targets only.

Credit where due: Ixitxachitl independently established in #11155 testing
that the save-path crash persists after #11185 and that re-queueing
sendLocal (moving the pipeline back to the Router thread) makes it go away
- which corroborates this diagnosis from the other direction. This commit
is the minimal capacity-side fix; #11155's relocation of the pipeline off
the BLE task remains the right architectural follow-up, and this guard
stays correct even after it lands.

Likely also explains #10905 (L1 display-thread crash when a client
requests full configuration) and the 2.8 field reports of idle nodes
losing region and keys after a BLE session.
This commit is contained in:
Ben Meadors
2026-07-24 06:38:46 -05:00
committed by GitHub
co-authored by GitHub
parent 01d1873bfc
commit becfb770c1
+7
View File
@@ -30,6 +30,13 @@ build_flags =
; 2048 words = 8 KB, validated on hardware. Value is in WORDS; requires the #ifndef guard ; 2048 words = 8 KB, validated on hardware. Value is in WORDS; requires the #ifndef guard
; from meshtastic/Adafruit_nRF52_Arduino#7 (harmless redefinition warning until it merges). ; from meshtastic/Adafruit_nRF52_Arduino#7 (harmless redefinition warning until it merges).
-DLOOP_STACK_SZ=2048 -DLOOP_STACK_SZ=2048
; The Bluefruit BLE task runs the ENTIRE phone-API chain inline (toRadioWriteCb ->
; handleToRadio -> admin set-config -> radio reconfigure -> LittleFS save): its stock
; 5 KB (1280-word) stack overflows during pairing/first-sync, resetting mid-flash-write
; and tearing LittleFS (auto-format -> total config/key wipe, critical fault #13).
; Reproduced on Wio Tracker L1 @ develop 6908d27. Same rationale as LOOP_STACK_SZ above;
; bluefruit.cpp's #ifndef guard makes the -D take effect without a framework patch.
-DCFG_BLE_TASK_STACKSIZE=2048
-DLFS_NO_ASSERT ; Disable LFS assertions , see https://github.com/meshtastic/firmware/pull/3818 -DLFS_NO_ASSERT ; Disable LFS assertions , see https://github.com/meshtastic/firmware/pull/3818
-DMESHTASTIC_EXCLUDE_AUDIO=1 -DMESHTASTIC_EXCLUDE_AUDIO=1
-DMESHTASTIC_EXCLUDE_PAXCOUNTER=1 -DMESHTASTIC_EXCLUDE_PAXCOUNTER=1