emergency handlers: always save SP _at_ the crash location

Save SP which is closest to the crash location, which simplifies
debugging. For serial_dump, write SP just before the dump.
For xfdump, save SP in the dump header.

This makes xfdump_dump and xfdump_full_dump_and_reset() equivalent for
stack debugging.
This commit is contained in:
Yuri D'Elia 2021-06-15 11:47:27 +02:00
parent 96aad0a475
commit 928c7211ad
7 changed files with 24 additions and 18 deletions

View File

@ -932,11 +932,11 @@ void dcode_9125()
void dcode_20() void dcode_20()
{ {
if(code_seen('E')) if(code_seen('E'))
xfdump_full_dump_and_reset(); xfdump_full_dump_and_reset(SP);
else else
{ {
unsigned long ts = _millis(); unsigned long ts = _millis();
xfdump_dump(); xfdump_dump(SP);
ts = _millis() - ts; ts = _millis() - ts;
DBG(_N("dump completed in %lums\n"), ts); DBG(_N("dump completed in %lums\n"), ts);
} }
@ -971,7 +971,7 @@ void dcode_22()
bool emergency_serial_dump = false; bool emergency_serial_dump = false;
void serial_dump_and_reset(dump_crash_reason reason) void serial_dump_and_reset(uint16_t sp, dump_crash_reason reason)
{ {
// we're being called from a live state, so shut off interrupts and heaters // we're being called from a live state, so shut off interrupts and heaters
cli(); cli();
@ -982,7 +982,9 @@ void serial_dump_and_reset(dump_crash_reason reason)
// this function can also be called from within a corrupted state, so not use // this function can also be called from within a corrupted state, so not use
// printf family of functions that use the heap or grow the stack. // printf family of functions that use the heap or grow the stack.
SERIAL_ECHOLNPGM("D23 - emergency serial dump"); SERIAL_ECHOLNPGM("D23 - emergency serial dump");
SERIAL_ECHOPGM("reason: "); SERIAL_ECHOPGM("exception: ");
SERIAL_ECHO(sp);
SERIAL_ECHO(" ");
SERIAL_ECHOLN((unsigned)reason); SERIAL_ECHOLN((unsigned)reason);
// set WDT long enough to allow writing the entire stream // set WDT long enough to allow writing the entire stream

View File

@ -38,7 +38,7 @@ extern void dcode_22(); //D22 - Clear crash dump state
#ifdef EMERGENCY_SERIAL_DUMP #ifdef EMERGENCY_SERIAL_DUMP
#include "xflash_dump.h" #include "xflash_dump.h"
extern bool emergency_serial_dump; extern bool emergency_serial_dump;
extern void serial_dump_and_reset(dump_crash_reason); extern void serial_dump_and_reset(uint16_t sp, dump_crash_reason);
#endif #endif
#ifdef HEATBED_ANALYSIS #ifdef HEATBED_ANALYSIS

View File

@ -1716,15 +1716,15 @@ void setup()
} }
static inline void crash_and_burn(dump_crash_reason reason) static inline void crash_and_burn(uint16_t sp, dump_crash_reason reason)
{ {
WRITE(BEEPER, HIGH); WRITE(BEEPER, HIGH);
eeprom_update_byte((uint8_t*)EEPROM_FW_CRASH_FLAG, (uint8_t)reason); eeprom_update_byte((uint8_t*)EEPROM_FW_CRASH_FLAG, (uint8_t)reason);
#ifdef EMERGENCY_DUMP #ifdef EMERGENCY_DUMP
xfdump_full_dump_and_reset(reason); xfdump_full_dump_and_reset(sp, reason);
#elif defined(EMERGENCY_SERIAL_DUMP) #elif defined(EMERGENCY_SERIAL_DUMP)
if(emergency_serial_dump) if(emergency_serial_dump)
serial_dump_and_reset(reason); serial_dump_and_reset(sp, reason);
#endif #endif
softReset(); softReset();
} }
@ -1733,18 +1733,18 @@ static inline void crash_and_burn(dump_crash_reason reason)
#ifdef WATCHDOG #ifdef WATCHDOG
ISR(WDT_vect) ISR(WDT_vect)
{ {
crash_and_burn(dump_crash_reason::watchdog); crash_and_burn(SP, dump_crash_reason::watchdog);
} }
#endif #endif
ISR(BADISR_vect) ISR(BADISR_vect)
{ {
crash_and_burn(dump_crash_reason::bad_isr); crash_and_burn(SP, dump_crash_reason::bad_isr);
} }
#endif //EMERGENCY_HANDLERS #endif //EMERGENCY_HANDLERS
void stack_error() { void stack_error() {
crash_and_burn(dump_crash_reason::stack_error); crash_and_burn(SP, dump_crash_reason::stack_error);
} }

View File

@ -1807,7 +1807,7 @@ static void lcd_preheat_menu()
static void lcd_dump_memory() static void lcd_dump_memory()
{ {
lcd_beeper_quick_feedback(); lcd_beeper_quick_feedback();
xfdump_dump(); xfdump_dump(SP);
lcd_return_to_status(); lcd_return_to_status();
} }
#endif //MENU_DUMP #endif //MENU_DUMP
@ -1816,7 +1816,7 @@ static void lcd_dump_memory()
static void lcd_serial_dump() static void lcd_serial_dump()
{ {
serial_dump_and_reset(dump_crash_reason::manual); serial_dump_and_reset(SP, dump_crash_reason::manual);
} }
#endif //MENU_SERIAL_DUMP #endif //MENU_SERIAL_DUMP

View File

@ -68,12 +68,13 @@ static void xfdump_dump_core(dump_header_t& hdr, uint32_t addr, uint8_t* buf, ui
} }
void xfdump_dump() void xfdump_dump(uint16_t sp)
{ {
dump_header_t buf; dump_header_t buf;
buf.magic = DUMP_MAGIC; buf.magic = DUMP_MAGIC;
buf.regs_present = false; buf.regs_present = false;
buf.crash_reason = (uint8_t)dump_crash_reason::manual; buf.crash_reason = (uint8_t)dump_crash_reason::manual;
buf.sp = sp;
// write sram only // write sram only
xfdump_dump_core(buf, DUMP_OFFSET + offsetof(dump_t, data.sram), xfdump_dump_core(buf, DUMP_OFFSET + offsetof(dump_t, data.sram),
@ -81,12 +82,13 @@ void xfdump_dump()
} }
void xfdump_full_dump_and_reset(dump_crash_reason reason) void xfdump_full_dump_and_reset(uint16_t sp, dump_crash_reason reason)
{ {
dump_header_t buf; dump_header_t buf;
buf.magic = DUMP_MAGIC; buf.magic = DUMP_MAGIC;
buf.regs_present = true; buf.regs_present = true;
buf.crash_reason = (uint8_t)reason; buf.crash_reason = (uint8_t)reason;
buf.sp = sp;
// disable interrupts for a cleaner register dump // disable interrupts for a cleaner register dump
cli(); cli();

View File

@ -11,12 +11,13 @@ enum class dump_crash_reason : uint8_t
}; };
#ifdef XFLASH_DUMP #ifdef XFLASH_DUMP
void xfdump_reset(); // reset XFLASH dump state void xfdump_reset(); // reset XFLASH dump state
void xfdump_dump(); // create a new SRAM memory dump void xfdump_dump(uint16_t sp); // create a new SRAM memory dump
// return true if a dump is present, save type in "reason" if provided // return true if a dump is present, save type in "reason" if provided
bool xfdump_check_state(dump_crash_reason* reason = NULL); bool xfdump_check_state(dump_crash_reason* reason = NULL);
// create a new dump containing registers and SRAM, then reset // create a new dump containing registers and SRAM, then reset
void xfdump_full_dump_and_reset(dump_crash_reason crash = dump_crash_reason::manual); void xfdump_full_dump_and_reset(
uint16_t sp, dump_crash_reason crash = dump_crash_reason::manual);
#endif #endif

View File

@ -21,6 +21,7 @@ struct dump_header_t
uint8_t regs_present; // true when the lower segment containing registers is present uint8_t regs_present; // true when the lower segment containing registers is present
uint8_t crash_reason; // uses values from dump_crash_source uint8_t crash_reason; // uses values from dump_crash_source
uint16_t sp; // SP closest to the crash location
}; };
struct dump_data_t struct dump_data_t