Merge branch 'main' into feat/eth-framework-independent

Brings in the coredump bounds fix (#74). Utils.h, Utils.cpp and
test_utils.cpp conflicted only because both sides added helpers in the
same spot; kept otaProven/releaseAssetName and formatBacktrace.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
cjkas 2026-10-21 13:09:16 +02:00
commit 2c1085ee9b
4 changed files with 53 additions and 7 deletions

View file

@ -80,16 +80,15 @@ void setup() {
#define CRASH_LOG(fmt, ...) do { if(newCrash) ESP_LOGW(TAG, fmt, ##__VA_ARGS__); else ESP_LOGI(TAG, fmt, ##__VA_ARGS__); } while(0)
if(newCrash) ESP_LOGW(TAG, "*** Crash coredump from the last boot ***");
else ESP_LOGI(TAG, "Stored coredump from an earlier crash");
CRASH_LOG(" Task: %s", summary.exc_task);
// exc_task isn't always terminated.
CRASH_LOG(" Task: %.*s", (int)sizeof(summary.exc_task), summary.exc_task);
CRASH_LOG(" PC: 0x%08x", summary.exc_pc);
#ifdef CONFIG_IDF_TARGET_ARCH_XTENSA
CRASH_LOG(" Cause: %d", summary.ex_info.exc_cause);
char bt_buf[256] = {0};
int pos = 0;
for (int i = 0; i < summary.exc_bt_info.depth; i++) {
pos += snprintf(bt_buf + pos, sizeof(bt_buf) - pos, " 0x%08x", summary.exc_bt_info.bt[i]);
}
CRASH_LOG(" Backtrace:%s", bt_buf);
char bt_buf[256];
formatBacktrace(bt_buf, sizeof(bt_buf), summary.exc_bt_info.bt,
sizeof(summary.exc_bt_info.bt) / sizeof(summary.exc_bt_info.bt[0]), summary.exc_bt_info.depth);
CRASH_LOG(" Backtrace:%s%s", bt_buf, summary.exc_bt_info.corrupted ? " (corrupted)" : "");
#elif CONFIG_IDF_TARGET_ARCH_RISCV
CRASH_LOG(" Cause: %d", summary.ex_info.mcause);
CRASH_LOG(" MTVAL: 0x%08x RA: 0x%08x SP: 0x%08x",

View file

@ -153,6 +153,18 @@ bool otaProven(bool networkUp, unsigned long uptimeMs, unsigned long minUptimeMs
void releaseAssetName(char *buf, size_t size, const char *kind, const char *chipModel) {
snprintf(buf, size, "SomfyController.%s.esp32%s.bin", kind, chipModel);
}
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";

View file

@ -90,6 +90,9 @@ bool otaProven(bool networkUp, unsigned long uptimeMs, unsigned long minUptimeMs
// "ino" for the firmware or "littlefs" for the web UI image, chipModel as in
// ConfigSettings ("" for the ESP32, "s3", "c3", "c6").
void releaseAssetName(char *buf, size_t size, const char *kind, const char *chipModel);
// A coredump backtrace as " 0x%08x" per frame. bt holds maxFrames entries and
// depth is how many the dump claims are valid.
void formatBacktrace(char *buf, size_t size, const uint32_t *bt, size_t maxFrames, uint32_t depth);
// How well loop() keeps up: the passes it made per second and its longest
// pass, over the window since the last memStatus broadcast. Only the loop
// task calls record(), rate(), maxUs() and publish(). publish() closes the