You can chat about native SDK questions and issues here.

User avatar
By Jeff Stuart
#88711 I see the ESP32 SDK provides the capability to record panic dumps to flash. On an embedded system this is insanely useful. I don't see the same for the ESP8266 in the RTOS SDK, or am I missing it?

Assuming the 8266 don't have it, and the 8266 never will, is there a way to hijack the panic dump process and roll my own? I sure could use it.

Thanks, Jeff
User avatar
By quackmore
#88713 I was missing that too

I found valuable informations into Arduino and Sming code
also Espressif esp-gdbstub (https://github.com/espressif/esp-gdbstub)
and Cesanta's blog (https://backend.cesanta.com/blog/esp8266-gdb.shtml)
are totally worth a reading

then I found that xtensa provide a weak symbol for system restart
so I used that for hijacking exceptions and watchdog triggers
and save relevant information from the stack to RTC memory (that's persistent)

some code below



Code: Select all// there is a weak symbol for system_restart_hook
// into libmain.a
// 00000338 W system_restart_hook
//
// that in the assemly file shows up like this:
//
// 4022ea90 <system_restart_hook>:
// 4022ea90:       f00d            ret.n
// 4022ea92:       ff0000          excw
// 4022ea95:       ffff00          excw
// 4022ea98:       07a120          excw
//
// the following will override the weak symbol to dump relevant stack content
// in case of an exception or software watchdog trigger
// following informations will e saved to RTC memory
// - stack pointer
// - stack content that likely refer to code address (PC return address)
//

void system_restart_hook()
{
    struct rst_info reset_info;
    // SDK APIs for obtaining rst_info does not work...
    // so copying from RTC memory (credits to Sming's guys)
    system_rtc_mem_read(0, &reset_info, sizeof(reset_info));

    uint32_t sp_offset = 0;

    switch (reset_info.reason)
    {
    case REASON_SOFT_WDT_RST:
        sp_offset = 0xF4;
        break;
    case REASON_EXCEPTION_RST:
        sp_offset = 0xC0;
        break;
    case REASON_WDT_RST: // would have liked this one too, but it's not working
    case REASON_DEFAULT_RST:
    case REASON_SOFT_RESTART:
    case REASON_DEEP_SLEEP_AWAKE:
    case REASON_EXT_SYS_RST:
    default:
        return;
    }

    uint32_t idx;
    uint32_t stack_pointer;
    uint32_t rtc_ptr;
    uint32_t rtc_ptr_blank = 0;

    // use without offset to find the sp_offset ...
    // stack_pointer = (uint32_t)&reset_info;
    stack_pointer = (uint32_t)&reset_info + sp_offset;
    rtc_ptr = RTC_STACKDUMP;
    // save to RTC memory
    // start saving the stack pointer
    system_rtc_mem_write(rtc_ptr, (void *)&stack_pointer, 4);
    rtc_ptr++;

    fs_printf("exception epc->0x%X\n", reset_info.epc1);
    fs_printf("stack dump SP->0x%X\n", stack_pointer);
    fs_printf("address  content\n");

    for (idx = 0; idx < STACK_TRACE_LEN; idx++)
    {
        // using 0x3FFFFFF0 as the highest stack pointer address
        if (stack_pointer > 0x3FFFFFF0)
            break;
        // serial log
        fs_printf("%X %X", stack_pointer, *((uint32_t *)stack_pointer));
        if (*((uint32_t *)stack_pointer) == reset_info.epc1)
            // this is for finding the sp_offset
            fs_printf(" <------ %X\n", (stack_pointer - (uint32_t)&reset_info));
        else
            fs_printf("\n");

        // save to RTC memory
        // save only stack content that possibly refers to code address
        // (the 'return address')
        // save up to RTC_STACKDUMP_LEN
        if ((*((uint32_t *)stack_pointer) >= 0x40200000) &&
            ((rtc_ptr - RTC_STACKDUMP) < RTC_STACKDUMP_LEN))
        {
            system_rtc_mem_write(rtc_ptr, (void *)stack_pointer, 4);
            rtc_ptr++;
        }

        stack_pointer += 4;
    }

    // save to RTC memory
    // fill up any remaining stack trace with 0
    while ((rtc_ptr - RTC_STACKDUMP) < RTC_STACKDUMP_LEN)
    {
        system_rtc_mem_write(rtc_ptr, (void *)&rtc_ptr_blank, 4);
        rtc_ptr++;
    }
}

User avatar
By quackmore
#88715 I see,

the solution I provided doesn't really depends on the NONOS SDK

it just depends on the weak symbol system_restart_hook into libmain.a

my code depends on NONOS SDK struct rst_info

but that's just an example