Browse Source

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.
Yuri D'Elia 2 years ago
parent
commit
928c7211ad

+ 6 - 4
Firmware/Dcodes.cpp

@@ -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

+ 1 - 1
Firmware/Dcodes.h

@@ -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

+ 6 - 6
Firmware/Marlin_main.cpp

@@ -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);
 }
 
 

+ 2 - 2
Firmware/ultralcd.cpp

@@ -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
 

+ 4 - 2
Firmware/xflash_dump.cpp

@@ -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();

+ 4 - 3
Firmware/xflash_dump.h

@@ -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

+ 1 - 0
Firmware/xflash_layout.h

@@ -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