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()
{
if(code_seen('E'))
xfdump_full_dump_and_reset();
xfdump_full_dump_and_reset(SP);
else
{
unsigned long ts = _millis();
xfdump_dump();
xfdump_dump(SP);
ts = _millis() - ts;
DBG(_N("dump completed in %lums\n"), ts);
}
@ -971,7 +971,7 @@ void dcode_22()
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
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
// printf family of functions that use the heap or grow the stack.
SERIAL_ECHOLNPGM("D23 - emergency serial dump");
SERIAL_ECHOPGM("reason: ");
SERIAL_ECHOPGM("exception: ");
SERIAL_ECHO(sp);
SERIAL_ECHO(" ");
SERIAL_ECHOLN((unsigned)reason);
// 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
#include "xflash_dump.h"
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
#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);
eeprom_update_byte((uint8_t*)EEPROM_FW_CRASH_FLAG, (uint8_t)reason);
#ifdef EMERGENCY_DUMP
xfdump_full_dump_and_reset(reason);
xfdump_full_dump_and_reset(sp, reason);
#elif defined(EMERGENCY_SERIAL_DUMP)
if(emergency_serial_dump)
serial_dump_and_reset(reason);
serial_dump_and_reset(sp, reason);
#endif
softReset();
}
@ -1733,18 +1733,18 @@ static inline void crash_and_burn(dump_crash_reason reason)
#ifdef WATCHDOG
ISR(WDT_vect)
{
crash_and_burn(dump_crash_reason::watchdog);
crash_and_burn(SP, dump_crash_reason::watchdog);
}
#endif
ISR(BADISR_vect)
{
crash_and_burn(dump_crash_reason::bad_isr);
crash_and_burn(SP, dump_crash_reason::bad_isr);
}
#endif //EMERGENCY_HANDLERS
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()
{
lcd_beeper_quick_feedback();
xfdump_dump();
xfdump_dump(SP);
lcd_return_to_status();
}
#endif //MENU_DUMP
@ -1816,7 +1816,7 @@ static void lcd_dump_memory()
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

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;
buf.magic = DUMP_MAGIC;
buf.regs_present = false;
buf.crash_reason = (uint8_t)dump_crash_reason::manual;
buf.sp = sp;
// write sram only
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;
buf.magic = DUMP_MAGIC;
buf.regs_present = true;
buf.crash_reason = (uint8_t)reason;
buf.sp = sp;
// disable interrupts for a cleaner register dump
cli();

View File

@ -11,12 +11,13 @@ enum class dump_crash_reason : uint8_t
};
#ifdef XFLASH_DUMP
void xfdump_reset(); // reset XFLASH dump state
void xfdump_dump(); // create a new SRAM memory dump
void xfdump_reset(); // reset XFLASH dump state
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
bool xfdump_check_state(dump_crash_reason* reason = NULL);
// 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

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 crash_reason; // uses values from dump_crash_source
uint16_t sp; // SP closest to the crash location
};
struct dump_data_t