diff --git a/mongoose.c b/mongoose.c index 8ce1ed15..55d017de 100644 --- a/mongoose.c +++ b/mongoose.c @@ -7032,11 +7032,31 @@ static void mg_mdash_fn(struct mg_connection *c, int ev, void *ev_data) { } static void mg_mdash_rpc_get_info(struct mg_rpc_req *r) { - mg_rpc_ok(r, "{%m:%m,%m:%llu,%m:%m,%m:\"mws.%d\"}", MG_ESC("fw_version"), - MG_ESC(MG_MDASH_FIRMWARE_VERSION), MG_ESC("uptime"), - (uint64_t) (mg_millis() / 1000), MG_ESC("reboot_reason"), - MG_ESC(mg_health_reason_str(mg_health_reason())), MG_ESC("arch"), - MG_ARCH); + if (mg_health_valid()) { + uint32_t *data = mg_health_record.backtrace; + mg_rpc_ok(r, + "{%m:%m,%m:%llu,%m:%m,%m:\"mws.%d\",%m:{%m:true," + "%m:{%m:\"0x%08lx\",%m:\"0x%08lx\",%m:\"0x%08lx\"}," + "%m:{%m:\"0x%08lx\",%m:%m}}}", + MG_ESC("fw_version"), MG_ESC(MG_MDASH_FIRMWARE_VERSION), + MG_ESC("uptime"), (uint64_t) (mg_millis() / 1000), + MG_ESC("reboot_reason"), + MG_ESC(mg_health_reason_str(mg_health_reason())), MG_ESC("arch"), + MG_ARCH, MG_ESC("report"), MG_ESC("valid"), MG_ESC("regs"), + MG_ESC("sp"), (unsigned long) data[0], MG_ESC("lr"), + (unsigned long) data[1], MG_ESC("pc"), (unsigned long) data[2], + MG_ESC("stack"), MG_ESC("addr"), (unsigned long) data[0], + MG_ESC("data"), mg_print_base64, + (int) ((MG_HEALTH_BACKTRACE - 3) * sizeof(data[0])), + (uint8_t *) &data[3]); + } else { + mg_rpc_ok(r, "{%m:%m,%m:%llu,%m:%m,%m:\"mws.%d\",%m:{%m:false}}", + MG_ESC("fw_version"), MG_ESC(MG_MDASH_FIRMWARE_VERSION), + MG_ESC("uptime"), (uint64_t) (mg_millis() / 1000), + MG_ESC("reboot_reason"), + MG_ESC(mg_health_reason_str(mg_health_reason())), MG_ESC("arch"), + MG_ARCH, MG_ESC("report"), MG_ESC("valid")); + } } static void mg_mdash_rpc_ota_begin(struct mg_rpc_req *r) { diff --git a/mongoose.h b/mongoose.h index e7e93b32..191207ab 100644 --- a/mongoose.h +++ b/mongoose.h @@ -4968,7 +4968,9 @@ enum mg_health_reason { MG_HEALTH_RESET_FAULT // Fault handler ran, see regs[] and saved_stack }; +#ifndef MG_HEALTH_BACKTRACE #define MG_HEALTH_BACKTRACE 20 // Return addresses in mg_health::backtrace +#endif struct mg_health { char magic[4]; // MG_HEALTH_MAGIC when the record holds valid data diff --git a/src/health.h b/src/health.h index 3fc1ed92..15a29842 100644 --- a/src/health.h +++ b/src/health.h @@ -52,7 +52,9 @@ enum mg_health_reason { MG_HEALTH_RESET_FAULT // Fault handler ran, see regs[] and saved_stack }; +#ifndef MG_HEALTH_BACKTRACE #define MG_HEALTH_BACKTRACE 20 // Return addresses in mg_health::backtrace +#endif struct mg_health { char magic[4]; // MG_HEALTH_MAGIC when the record holds valid data diff --git a/src/mdash.c b/src/mdash.c index 9ec5a4a3..8580514a 100644 --- a/src/mdash.c +++ b/src/mdash.c @@ -91,11 +91,31 @@ static void mg_mdash_fn(struct mg_connection *c, int ev, void *ev_data) { } static void mg_mdash_rpc_get_info(struct mg_rpc_req *r) { - mg_rpc_ok(r, "{%m:%m,%m:%llu,%m:%m,%m:\"mws.%d\"}", MG_ESC("fw_version"), - MG_ESC(MG_MDASH_FIRMWARE_VERSION), MG_ESC("uptime"), - (uint64_t) (mg_millis() / 1000), MG_ESC("reboot_reason"), - MG_ESC(mg_health_reason_str(mg_health_reason())), MG_ESC("arch"), - MG_ARCH); + if (mg_health_valid()) { + uint32_t *data = mg_health_record.backtrace; + mg_rpc_ok(r, + "{%m:%m,%m:%llu,%m:%m,%m:\"mws.%d\",%m:{%m:true," + "%m:{%m:\"0x%08lx\",%m:\"0x%08lx\",%m:\"0x%08lx\"}," + "%m:{%m:\"0x%08lx\",%m:%m}}}", + MG_ESC("fw_version"), MG_ESC(MG_MDASH_FIRMWARE_VERSION), + MG_ESC("uptime"), (uint64_t) (mg_millis() / 1000), + MG_ESC("reboot_reason"), + MG_ESC(mg_health_reason_str(mg_health_reason())), MG_ESC("arch"), + MG_ARCH, MG_ESC("report"), MG_ESC("valid"), MG_ESC("regs"), + MG_ESC("sp"), (unsigned long) data[0], MG_ESC("lr"), + (unsigned long) data[1], MG_ESC("pc"), (unsigned long) data[2], + MG_ESC("stack"), MG_ESC("addr"), (unsigned long) data[0], + MG_ESC("data"), mg_print_base64, + (int) ((MG_HEALTH_BACKTRACE - 3) * sizeof(data[0])), + (uint8_t *) &data[3]); + } else { + mg_rpc_ok(r, "{%m:%m,%m:%llu,%m:%m,%m:\"mws.%d\",%m:{%m:false}}", + MG_ESC("fw_version"), MG_ESC(MG_MDASH_FIRMWARE_VERSION), + MG_ESC("uptime"), (uint64_t) (mg_millis() / 1000), + MG_ESC("reboot_reason"), + MG_ESC(mg_health_reason_str(mg_health_reason())), MG_ESC("arch"), + MG_ARCH, MG_ESC("report"), MG_ESC("valid")); + } } static void mg_mdash_rpc_ota_begin(struct mg_rpc_req *r) { diff --git a/tutorials/stm32/nucleo-h723zg/minimal/main.c b/tutorials/stm32/nucleo-h723zg/minimal/main.c index 215b52d3..d4983ec7 100644 --- a/tutorials/stm32/nucleo-h723zg/minimal/main.c +++ b/tutorials/stm32/nucleo-h723zg/minimal/main.c @@ -117,27 +117,6 @@ int main(void) { MG_INFO(("Initialised. CPU clock: %lu MHz", SystemCoreClock / 1000000)); - // Report the previous boot's crash backtrace, if any - if (mg_health_reason() == MG_HEALTH_RESET_FAULT) { - uint32_t *r = mg_health_record.backtrace; - static char buf[512]; - size_t len = mg_snprintf( - buf, sizeof(buf), - "{\"image\":\"firmware.elf\",\"binary\":\"firmware.bin\"," - "\"regs\":{\"sp\":\"0x%08lx\",\"lr\":\"0x%08lx\"," - "\"pc\":\"0x%08lx\"},\"stack\":{\"addr\":\"0x%08lx\"," - "\"words\":[", - (unsigned long) r[CRASH_SP], (unsigned long) r[CRASH_LR], - (unsigned long) r[CRASH_PC], (unsigned long) r[CRASH_SP]); - for (size_t i = CRASH_STACK; i < MG_HEALTH_BACKTRACE; i++) { - len += mg_snprintf(buf + len, sizeof(buf) - len, "%s\"0x%08lx\"", - i == CRASH_STACK ? "" : ",", - (unsigned long) r[i]); - } - mg_snprintf(buf + len, sizeof(buf) - len, "]}}"); - MG_INFO(("Previous boot crash: %s", buf)); - } - struct mg_mgr mgr; mg_mgr_init(&mgr); mg_http_listen(&mgr, "http://0.0.0.0", http_ev_handler, NULL); diff --git a/tutorials/stm32/nucleo-h723zg/minimal/mongoose_config.h b/tutorials/stm32/nucleo-h723zg/minimal/mongoose_config.h index 097774f1..4195210d 100644 --- a/tutorials/stm32/nucleo-h723zg/minimal/mongoose_config.h +++ b/tutorials/stm32/nucleo-h723zg/minimal/mongoose_config.h @@ -28,6 +28,7 @@ // Crash report support. Health record lives in the .mg_health region, see link.ld #define MG_HEALTH_RAM __attribute__((section(".mg_health"))) +#define MG_HEALTH_BACKTRACE 1022 // fill the 4KB backup SRAM // mdash.net device management service support #define MG_ENABLE_MDASH 1