diff options
| author | Alessandro Gatti <a.gatti@frob.it> | 2025-06-01 18:54:37 +0200 |
|---|---|---|
| committer | Damien George <damien@micropython.org> | 2025-06-04 22:35:39 +1000 |
| commit | e4c0e2b73d0e8842160c86a39706d872ec226b6c (patch) | |
| tree | ff2ef66182d9088c187d9825a792a57459713063 | |
| parent | 4227654d4294b778b2bbba8a3b735882786b1d2d (diff) | |
esp8266/main: Print error information on crash-induced reboots.
This commit adds an optional configuration option for the ESP8266 port
that, if the board rebooted due to a crash, will print to stdout some
information about the error that triggered the issue.
It is not possible using regular SDK functions to intercept errors and
print information at that stage, and the only error response from the
board is to reboot itself. This is the next best thing, print some
error information just once at boot time after the crash - the least
invasive option given the situation we're in.
This is disabled by default, and can be enabled by enabling
MICROPY_HW_HARD_FAULT_DEBUG in the port configuration - obviously with a
small increase in the firmware code footprint.
Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
| -rw-r--r-- | ports/esp8266/main.c | 62 | ||||
| -rw-r--r-- | ports/esp8266/mpconfigport.h | 3 |
2 files changed, 65 insertions, 0 deletions
diff --git a/ports/esp8266/main.c b/ports/esp8266/main.c index 2dd7c1dec..da712fce9 100644 --- a/ports/esp8266/main.c +++ b/ports/esp8266/main.c @@ -49,6 +49,64 @@ static char heap[38 * 1024]; +#if MICROPY_HW_HARD_FAULT_DEBUG + +static void format_hex(uint32_t hex, char *buffer) { + static const char table[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + int offset = 7; + uint32_t value = hex; + while (offset >= 0) { + buffer[offset--] = table[value & 0x0F]; + value >>= 4; + } +} + +static void print_reset_info(void) { + struct rst_info *rst_info = system_get_rst_info(); + if ((rst_info->reason == REASON_WDT_RST) || (rst_info->reason == REASON_EXCEPTION_RST) || (rst_info->reason == REASON_SOFT_WDT_RST)) { + char buffer[8]; + mp_hal_stdout_tx_str("\r\n\r\nThe system restarted due to an error.\r\n\r\nReason: "); + switch (rst_info->reason) { + case REASON_WDT_RST: + mp_hal_stdout_tx_str("WDT"); + break; + + case REASON_EXCEPTION_RST: + mp_hal_stdout_tx_str("EXCEPTION"); + break; + + case REASON_SOFT_WDT_RST: + mp_hal_stdout_tx_str("SOFT_WDT"); + break; + + default: + assert(!"Should not ever get here."); + break; + } + mp_hal_stdout_tx_str(" Cause: "); + format_hex(rst_info->exccause, buffer); + mp_hal_stdout_tx_strn(buffer, sizeof(buffer)); + mp_hal_stdout_tx_str(" EPC1: "); + format_hex(rst_info->epc1, buffer); + mp_hal_stdout_tx_strn(buffer, sizeof(buffer)); + mp_hal_stdout_tx_str(" EPC2: "); + format_hex(rst_info->epc2, buffer); + mp_hal_stdout_tx_strn(buffer, sizeof(buffer)); + mp_hal_stdout_tx_str(" EPC3: "); + format_hex(rst_info->epc3, buffer); + mp_hal_stdout_tx_strn(buffer, sizeof(buffer)); + mp_hal_stdout_tx_str(" Exception Vector address: "); + format_hex(rst_info->excvaddr, buffer); + mp_hal_stdout_tx_strn(buffer, sizeof(buffer)); + mp_hal_stdout_tx_str(" DEPC: "); + format_hex(rst_info->depc, buffer); + mp_hal_stdout_tx_strn(buffer, sizeof(buffer)); + mp_hal_stdout_tx_str("\r\n\r\n"); + } +} + +#endif + static void mp_reset(void) { mp_stack_set_top((void *)0x40000000); mp_stack_set_limit(8192); @@ -114,6 +172,10 @@ void init_done(void) { pyexec_event_repl_init(); #endif + #if MICROPY_HW_HARD_FAULT_DEBUG + print_reset_info(); + #endif + #if !MICROPY_REPL_EVENT_DRIVEN soft_reset: for (;;) { diff --git a/ports/esp8266/mpconfigport.h b/ports/esp8266/mpconfigport.h index 83d80a7c9..03f3bb643 100644 --- a/ports/esp8266/mpconfigport.h +++ b/ports/esp8266/mpconfigport.h @@ -117,6 +117,9 @@ #define MICROPY_FATFS_LFN_CODE_PAGE 437 /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */ #define MICROPY_ESP8266_APA102 (1) +// Print error information at reboot time if the board crashed. +#define MICROPY_HW_HARD_FAULT_DEBUG (0) + // No blocking wait-for-event on ESP8266, only non-blocking pump of the "OS" event // loop // |
