fix: don't boot-loop on a corrupted coredump

setup() prints the stored coredump summary on every boot and trusted its
backtrace depth. A half-written dump reads back as the 0xa5 stack fill, so
depth was 0xa5a5a5a5: the loop read past bt[16], snprintf ran past its
256-byte buffer once the size went negative, and the interrupt watchdog
reset the board. The dump stays in flash, so every boot hit it again
(seen 2026-10-21: 162 TG1WDT resets in a row, each stopping after "Cause:").

formatBacktrace() in Utils reads at most bt[]'s 16 frames and stops when the
buffer is full, and the line notes IDF's corrupted flag. The task name is
printed at most 16 chars, since exc_task isn't always terminated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
cjkas 2026-10-21 12:07:53 +02:00
parent b74f382650
commit 54641af039
4 changed files with 53 additions and 7 deletions

View file

@ -147,6 +147,18 @@ void RssiBroadcast::sent(bool broadcast, int rssi, int channel, uint32_t now) {
bool worthRoaming(bool connected, int currentRssi, int apRssi, int minGain) {
return !connected || apRssi >= currentRssi + minGain;
}
void formatBacktrace(char *buf, size_t size, const uint32_t *bt, size_t maxFrames, uint32_t depth) {
// depth comes from flash. A half-written dump reads back as 0xa5a5a5a5,
// so never trust it past bt[] or the buffer.
buf[0] = '\0';
size_t pos = 0;
size_t frames = depth < maxFrames ? depth : maxFrames;
for (size_t i = 0; i < frames && pos < size - 1; i++) {
int n = snprintf(buf + pos, size - pos, " 0x%08x", (unsigned int)bt[i]);
if (n < 0) break;
pos += (size_t)n;
}
}
const char *wifiAuthModeName(uint8_t authMode) {
switch(authMode) {
case 0: return "OPEN";