From becfb770c1c0354667d5dc1e4fdd6e80f7248eb3 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Fri, 24 Jul 2026 06:38:46 -0500 Subject: [PATCH] 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. --- variants/nrf52840/nrf52.ini | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/variants/nrf52840/nrf52.ini b/variants/nrf52840/nrf52.ini index d4249bb78..471db3c8d 100644 --- a/variants/nrf52840/nrf52.ini +++ b/variants/nrf52840/nrf52.ini @@ -30,6 +30,13 @@ build_flags = ; 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). -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 -DMESHTASTIC_EXCLUDE_AUDIO=1 -DMESHTASTIC_EXCLUDE_PAXCOUNTER=1