mirror of
https://github.com/rstrouse/ESPSomfy-RTS.git
synced 2026-10-31 13:52:15 +01:00
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:
commit
2c1085ee9b
4 changed files with 53 additions and 7 deletions
|
|
@ -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)
|
#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 ***");
|
if(newCrash) ESP_LOGW(TAG, "*** Crash coredump from the last boot ***");
|
||||||
else ESP_LOGI(TAG, "Stored coredump from an earlier crash");
|
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);
|
CRASH_LOG(" PC: 0x%08x", summary.exc_pc);
|
||||||
#ifdef CONFIG_IDF_TARGET_ARCH_XTENSA
|
#ifdef CONFIG_IDF_TARGET_ARCH_XTENSA
|
||||||
CRASH_LOG(" Cause: %d", summary.ex_info.exc_cause);
|
CRASH_LOG(" Cause: %d", summary.ex_info.exc_cause);
|
||||||
char bt_buf[256] = {0};
|
char bt_buf[256];
|
||||||
int pos = 0;
|
formatBacktrace(bt_buf, sizeof(bt_buf), summary.exc_bt_info.bt,
|
||||||
for (int i = 0; i < summary.exc_bt_info.depth; i++) {
|
sizeof(summary.exc_bt_info.bt) / sizeof(summary.exc_bt_info.bt[0]), summary.exc_bt_info.depth);
|
||||||
pos += snprintf(bt_buf + pos, sizeof(bt_buf) - pos, " 0x%08x", summary.exc_bt_info.bt[i]);
|
CRASH_LOG(" Backtrace:%s%s", bt_buf, summary.exc_bt_info.corrupted ? " (corrupted)" : "");
|
||||||
}
|
|
||||||
CRASH_LOG(" Backtrace:%s", bt_buf);
|
|
||||||
#elif CONFIG_IDF_TARGET_ARCH_RISCV
|
#elif CONFIG_IDF_TARGET_ARCH_RISCV
|
||||||
CRASH_LOG(" Cause: %d", summary.ex_info.mcause);
|
CRASH_LOG(" Cause: %d", summary.ex_info.mcause);
|
||||||
CRASH_LOG(" MTVAL: 0x%08x RA: 0x%08x SP: 0x%08x",
|
CRASH_LOG(" MTVAL: 0x%08x RA: 0x%08x SP: 0x%08x",
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
void releaseAssetName(char *buf, size_t size, const char *kind, const char *chipModel) {
|
||||||
snprintf(buf, size, "SomfyController.%s.esp32%s.bin", kind, 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) {
|
const char *wifiAuthModeName(uint8_t authMode) {
|
||||||
switch(authMode) {
|
switch(authMode) {
|
||||||
case 0: return "OPEN";
|
case 0: return "OPEN";
|
||||||
|
|
|
||||||
|
|
@ -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
|
// "ino" for the firmware or "littlefs" for the web UI image, chipModel as in
|
||||||
// ConfigSettings ("" for the ESP32, "s3", "c3", "c6").
|
// ConfigSettings ("" for the ESP32, "s3", "c3", "c6").
|
||||||
void releaseAssetName(char *buf, size_t size, const char *kind, const char *chipModel);
|
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
|
// 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
|
// pass, over the window since the last memStatus broadcast. Only the loop
|
||||||
// task calls record(), rate(), maxUs() and publish(). publish() closes the
|
// task calls record(), rate(), maxUs() and publish(). publish() closes the
|
||||||
|
|
|
||||||
|
|
@ -292,6 +292,35 @@ static void test_releaseAssetName_keeps_c3() {
|
||||||
TEST_ASSERT_EQUAL_STRING("SomfyController.ino.esp32c3.bin", buf);
|
TEST_ASSERT_EQUAL_STRING("SomfyController.ino.esp32c3.bin", buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
* formatBacktrace
|
||||||
|
********************************************************************/
|
||||||
|
static void test_formatBacktrace_frames_the_dump_holds() {
|
||||||
|
const uint32_t bt[16] = {0x40083c19, 0x4008e42d, 0x00000011};
|
||||||
|
char buf[256];
|
||||||
|
formatBacktrace(buf, sizeof(buf), bt, 16, 3);
|
||||||
|
TEST_ASSERT_EQUAL_STRING(" 0x40083c19 0x4008e42d 0x00000011", buf);
|
||||||
|
}
|
||||||
|
static void test_formatBacktrace_garbage_depth_stays_in_bounds() {
|
||||||
|
// A half-written dump reads back as the 0xa5 stack fill: depth 0xa5a5a5a5.
|
||||||
|
// setup() looped that many times and overran bt[] and its buffer.
|
||||||
|
struct { uint32_t bt[16]; uint32_t depth; } summary;
|
||||||
|
memset(&summary, 0xa5, sizeof(summary));
|
||||||
|
struct { char buf[256]; char guard[16]; } out;
|
||||||
|
memset(out.guard, 'G', sizeof(out.guard));
|
||||||
|
formatBacktrace(out.buf, sizeof(out.buf), summary.bt, 16, summary.depth);
|
||||||
|
TEST_ASSERT_EQUAL(16 * 11, strlen(out.buf));
|
||||||
|
for (size_t i = 0; i < sizeof(out.guard); i++) TEST_ASSERT_EQUAL_CHAR('G', out.guard[i]);
|
||||||
|
}
|
||||||
|
static void test_formatBacktrace_stops_when_the_buffer_is_full() {
|
||||||
|
const uint32_t bt[16] = {0};
|
||||||
|
struct { char buf[30]; char guard[16]; } out;
|
||||||
|
memset(out.guard, 'G', sizeof(out.guard));
|
||||||
|
formatBacktrace(out.buf, sizeof(out.buf), bt, 16, 16);
|
||||||
|
TEST_ASSERT_EQUAL(sizeof(out.buf) - 1, strlen(out.buf));
|
||||||
|
for (size_t i = 0; i < sizeof(out.guard); i++) TEST_ASSERT_EQUAL_CHAR('G', out.guard[i]);
|
||||||
|
}
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
* wifiAuthModeName
|
* wifiAuthModeName
|
||||||
********************************************************************/
|
********************************************************************/
|
||||||
|
|
@ -424,6 +453,9 @@ int main(int argc, char **argv) {
|
||||||
RUN_TEST(test_otaProven_not_without_network);
|
RUN_TEST(test_otaProven_not_without_network);
|
||||||
RUN_TEST(test_releaseAssetName_matches_the_release_workflow);
|
RUN_TEST(test_releaseAssetName_matches_the_release_workflow);
|
||||||
RUN_TEST(test_releaseAssetName_keeps_c3);
|
RUN_TEST(test_releaseAssetName_keeps_c3);
|
||||||
|
RUN_TEST(test_formatBacktrace_frames_the_dump_holds);
|
||||||
|
RUN_TEST(test_formatBacktrace_garbage_depth_stays_in_bounds);
|
||||||
|
RUN_TEST(test_formatBacktrace_stops_when_the_buffer_is_full);
|
||||||
RUN_TEST(test_wifiAuthModeName_matches_the_idf_enum);
|
RUN_TEST(test_wifiAuthModeName_matches_the_idf_enum);
|
||||||
RUN_TEST(test_wifiAuthModeName_unknown_past_the_shared_values);
|
RUN_TEST(test_wifiAuthModeName_unknown_past_the_shared_values);
|
||||||
RUN_TEST(test_heapEmitTarget_one_client_always_gets_it);
|
RUN_TEST(test_heapEmitTarget_one_client_always_gets_it);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue