nrf52: fix loop-task stack overflow causing reset on BLE pairing/first-sync (#10944)
The Arduino loop task runs Meshtastic's entire cooperative OSThread scheduler on the Adafruit core's stock 4 KB (1024-word) stack. The 2.8 first-sync path - AdminModule::handleSetConfig -> saveChanges -> configChanged -> RadioInterface::reloadConfig -> LR11x0 reconfigure -> SPI Lock::lock, with vsnprintf/USB-CDC logging frames stacked on top - overflows it. SWD fault capture on a T1000-E (pyocd vector_catch=h) proved it: the loop task's SP was driven 40 bytes BELOW its own pxStack base, the stack paint was consumed to the floor, and the crash was a BusFault in xQueueSemaphoreTake dereferencing a semaphore handle that adjacent-heap corruption had overwritten with log text (0x3f3f207c = "| ??"). The core's HardFault handler is a bare NVIC_SystemReset, so in the field this presents as a silent reboot ~seconds after a phone pairs (or a 30 s zombie hang -> supervision timeout 0x8 when the corruption lands on task TCBs instead). Also explains the set_time_only -> immediate-NodeInfo crash variant reported on empty-DB nodes: same task, different deep chain. 2.7.26 is unaffected because the deep frames (XEdDSA, satellite map conversion, replay engine) did not exist. Fix: set -DLOOP_STACK_SZ=2048 (words = 8 KB) for all nrf52840 targets. Requires the #ifndef guard from meshtastic/Adafruit_nRF52_Arduino#7; until that merges the flag is a harmless redefinition warning. Validated on hardware: pairing + full sync completes, stack paint shows healthy margin under load. Also fix the boot-time reset-reason log: the core's init() caches RESETREAS and W1C-clears the register before setup() runs, so the raw read here has always printed 0. Use readResetReason() instead. (preFSBegin's RESETREAS==0 gate is intentionally left as-is - its degenerate GPREGRET-only behavior is what makes lfs recovery work.)
This commit is contained in:
@@ -378,7 +378,11 @@ void nrf52Setup()
|
|||||||
pinMode(ADC_V, INPUT);
|
pinMode(ADC_V, INPUT);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint32_t why = NRF_POWER->RESETREAS;
|
// The Adafruit core's init() (cores/nRF5/wiring.c) caches RESETREAS into a static and then
|
||||||
|
// W1C-clears the hardware register before setup() ever runs, so a raw NRF_POWER->RESETREAS
|
||||||
|
// read here is ALWAYS 0. Use the core's cached copy so this log line is actually meaningful
|
||||||
|
// (0x1 pin reset, 0x2 watchdog, 0x4 soft reset/SREQ, 0x8 CPU lockup, 0x10000 System OFF wake).
|
||||||
|
uint32_t why = readResetReason();
|
||||||
// per
|
// per
|
||||||
// https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.nrf52832.ps.v1.1%2Fpower.html
|
// https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.nrf52832.ps.v1.1%2Fpower.html
|
||||||
LOG_DEBUG("Reset reason: 0x%x", why);
|
LOG_DEBUG("Reset reason: 0x%x", why);
|
||||||
|
|||||||
@@ -23,6 +23,13 @@ build_flags =
|
|||||||
${arduino_base.build_flags}
|
${arduino_base.build_flags}
|
||||||
-Wno-unused-variable
|
-Wno-unused-variable
|
||||||
-Isrc/platform/nrf52
|
-Isrc/platform/nrf52
|
||||||
|
; The Arduino loop task runs the entire cooperative OSThread scheduler; the core's stock
|
||||||
|
; 4 KB (1024-word) stack overflows during BLE first-sync (admin config-apply -> radio
|
||||||
|
; reconfigure with XEdDSA/satmap/log frames stacked) - SWD-proven on T1000-E: SP driven
|
||||||
|
; 40 B below pxStack, corrupting adjacent heap -> silent HardFault reset on phone pairing.
|
||||||
|
; 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
|
||||||
-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
|
||||||
|
|||||||
Reference in New Issue
Block a user