From bd57e004486a8f6b02fc5f47ae7b15096a1ec396 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Sat, 12 Jun 2021 13:37:20 +0200 Subject: [PATCH] Implement an online crash dumper for MK2.5 boards When XFLASH is not available, allow users to request _online_ crash dumps by using D23 (since these require active user cooperation). Once enabled, instead of just rebooting, dump memory directly to the serial. As similarly done with EMERGENCY_DUMP, we have two features that can be enabled: EMERGENCY_SERIAL_DUMP: enables dumping on crash after being requested MENU_SERIAL_DUMP: allow triggering the same manually through the support menu. --- Firmware/Dcodes.cpp | 28 +++++++++++++++++++ Firmware/Dcodes.h | 6 ++++ Firmware/Marlin_main.cpp | 28 +++++++++++++++++-- Firmware/config.h | 13 +++++++++ Firmware/ultralcd.cpp | 28 ++++++++++++++++--- .../variants/1_75mm_MK25-RAMBo10a-E3Dv6full.h | 4 +++ .../variants/1_75mm_MK25-RAMBo13a-E3Dv6full.h | 4 +++ .../1_75mm_MK25S-RAMBo10a-E3Dv6full.h | 4 +++ .../1_75mm_MK25S-RAMBo13a-E3Dv6full.h | 4 +++ .../variants/1_75mm_MK3-EINSy10a-E3Dv6full.h | 4 +++ .../variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h | 4 +++ Firmware/xflash_dump.h | 9 +++--- Firmware/xyzcal.cpp | 4 +-- 13 files changed, 126 insertions(+), 14 deletions(-) diff --git a/Firmware/Dcodes.cpp b/Firmware/Dcodes.cpp index 1fbca4c60..e9ba04545 100644 --- a/Firmware/Dcodes.cpp +++ b/Firmware/Dcodes.cpp @@ -965,3 +965,31 @@ void dcode_22() } } #endif + +#ifdef EMERGENCY_SERIAL_DUMP +#include "xflash_dump.h" + +bool emergency_serial_dump = false; + +void serial_dump_and_reset(dump_crash_reason reason) +{ + // we're being called from a live state, so shut off interrupts and heaters + cli(); + wdt_enable(WDTO_15MS); + disable_heater(); + + // 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_ECHOLN((unsigned)reason); + + // disable interrupts from now on to avoid wdt while dumping + wdt_disable(); + print_mem(0, RAMEND+1, dcode_mem_t::sram); + SERIAL_ECHOLNRPGM(MSG_OK); + + // reset soon + softReset(); +} +#endif diff --git a/Firmware/Dcodes.h b/Firmware/Dcodes.h index 4e37cc243..c4b470e4b 100644 --- a/Firmware/Dcodes.h +++ b/Firmware/Dcodes.h @@ -35,6 +35,12 @@ extern void dcode_21(); //D21 - Print crash dump to serial extern void dcode_22(); //D22 - Clear crash dump state #endif +#ifdef EMERGENCY_SERIAL_DUMP +#include "xflash_dump.h" +extern bool emergency_serial_dump; +extern void serial_dump_and_reset(dump_crash_reason); +#endif + #ifdef HEATBED_ANALYSIS extern void dcode_80(); //D80 - Bed check. This command will log data to SD card file "mesh.txt". extern void dcode_81(); //D81 - Bed analysis. This command will log data to SD card file "wldsd.txt". diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 91da6cc96..7656ddcd6 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -1679,18 +1679,24 @@ void setup() KEEPALIVE_STATE(NOT_BUSY); #ifdef WATCHDOG wdt_enable(WDTO_4S); -#ifdef EMERGENCY_DUMP +#ifdef EMERGENCY_HANDLERS WDTCSR |= (1 << WDIE); -#endif //EMERGENCY_DUMP +#endif //EMERGENCY_HANDLERS #endif //WATCHDOG } -#if defined(WATCHDOG) && defined(EMERGENCY_DUMP) +#if defined(WATCHDOG) && defined(EMERGENCY_HANDLERS) ISR(WDT_vect) { WRITE(BEEPER, 1); +#ifdef EMERGENCY_DUMP eeprom_update_byte((uint8_t*)EEPROM_CRASH_ACKNOWLEDGED, 0); xfdump_full_dump_and_reset(dump_crash_reason::watchdog); +#else //EMERGENCY_SERIAL_DUMP + if(emergency_serial_dump) + serial_dump_and_reset(dump_crash_reason::watchdog); + softReset(); +#endif } #endif @@ -9292,6 +9298,22 @@ Sigma_Exit: dcode_22(); break; }; +#endif //XFLASH_DUMP + +#ifdef EMERGENCY_SERIAL_DUMP + /*! + ### D23 - Request emergency dump on serial + On boards without offline dump support, request online dumps to the serial port on firmware faults. + When online dumps are enabled, the FW will dump memory on the serial before resetting. + #### Usage + + D23 [R] + #### Parameters + - `R` - Disable online dumps. + */ + case 23: { + emergency_serial_dump = !code_seen('R'); + }; #endif #ifdef HEATBED_ANALYSIS diff --git a/Firmware/config.h b/Firmware/config.h index fa86f4567..5adba50df 100644 --- a/Firmware/config.h +++ b/Firmware/config.h @@ -76,4 +76,17 @@ #error "MENU_DUMP and EMERGENCY_DUMP require XFLASH_DUMP" #endif +// Support for serial dumps is mutually exclusive with XFLASH_DUMP features +#if defined(EMERGENCY_DUMP) && defined(EMERGENCY_SERIAL_DUMP) +#error "EMERGENCY_DUMP and EMERGENCY_SERIAL_DUMP are mutually exclusive" +#endif +#if defined(MENU_DUMP) && defined(MENU_SERIAL_DUMP) +#error "MENU_DUMP and MENU_SERIAL_DUMP are mutually exclusive" +#endif + +// Reduce internal duplication +#if defined(EMERGENCY_DUMP) || defined(EMERGENCY_SERIAL_DUMP) +#define EMERGENCY_HANDLERS +#endif + #endif //_CONFIG_H diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index c07292456..fcf2e4584 100755 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -1812,8 +1812,16 @@ static void lcd_dump_memory() lcd_return_to_status(); } #endif //MENU_DUMP +#ifdef MENU_SERIAL_DUMP +#include "Dcodes.h" -#if defined(WATCHDOG) && defined(EMERGENCY_DUMP) && defined(DEBUG_BUILD) +static void lcd_serial_dump() +{ + serial_dump_and_reset(dump_crash_reason::manual); +} +#endif //MENU_SERIAL_DUMP + +#if defined(WATCHDOG) && defined(DEBUG_BUILD) && defined(EMERGENCY_HANDLERS) static void lcd_wdr_crash() { while (1); @@ -2015,8 +2023,12 @@ static void lcd_support_menu() #ifdef MENU_DUMP MENU_ITEM_FUNCTION_P(_i("Dump memory"), lcd_dump_memory); #endif //MENU_DUMP +#ifdef MENU_SERIAL_DUMP + if (emergency_serial_dump) + MENU_ITEM_FUNCTION_P(_i("Dump to serial"), lcd_serial_dump); +#endif #ifdef DEBUG_BUILD -#if defined(WATCHDOG) && defined(EMERGENCY_DUMP) +#if defined(WATCHDOG) && defined(EMERGENCY_HANDLERS) MENU_ITEM_FUNCTION_P(PSTR("WDR crash"), lcd_wdr_crash); #endif MENU_ITEM_SUBMENU_P(PSTR("Debug"), lcd_menu_debug);////MSG_DEBUG c=18 @@ -6716,14 +6728,22 @@ void stack_error() { eeprom_update_byte((uint8_t*)EEPROM_CRASH_ACKNOWLEDGED, 0); xfdump_full_dump_and_reset(dump_crash_reason::stack_error); } -#else +#else //EMERGENCY_DUMP +#ifdef EMERGENCY_SERIAL_DUMP +#include "Dcodes.h" +#endif + void stack_error() { +#ifdef EMERGENCY_SERIAL_DUMP + if (emergency_serial_dump) + serial_dump_and_reset(dump_crash_reason::stack_error); +#endif Sound_MakeCustom(1000,0,true); lcd_display_message_fullscreen_P(_i("Error - static memory has been overwritten"));////MSG_STACK_ERROR c=20 r=4 //err_triggered = 1; while (1) delay_keep_alive(1000); } -#endif +#endif //EMERGENCY_DUMP #ifdef DEBUG_STEPPER_TIMER_MISSED bool stepper_timer_overflow_state = false; diff --git a/Firmware/variants/1_75mm_MK25-RAMBo10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK25-RAMBo10a-E3Dv6full.h index fa7f26902..3cbc3829f 100644 --- a/Firmware/variants/1_75mm_MK25-RAMBo10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK25-RAMBo10a-E3Dv6full.h @@ -119,6 +119,10 @@ #define DEFAULT_SAFETYTIMER_TIME_MINS 30 #define FARM_DEFAULT_SAFETYTIMER_TIME_ms (45*60*1000ul) +// Online crash dumper +//#define EMERGENCY_SERIAL_DUMP // Request dump via serial on stack corruption and WDR +//#define MENU_SERIAL_DUMP // Enable "Memory dump" in Settings menu + // Filament sensor #define FILAMENT_SENSOR #define PAT9125 diff --git a/Firmware/variants/1_75mm_MK25-RAMBo13a-E3Dv6full.h b/Firmware/variants/1_75mm_MK25-RAMBo13a-E3Dv6full.h index 10aa14f90..9b4e591ae 100644 --- a/Firmware/variants/1_75mm_MK25-RAMBo13a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK25-RAMBo13a-E3Dv6full.h @@ -120,6 +120,10 @@ #define DEFAULT_SAFETYTIMER_TIME_MINS 30 #define FARM_DEFAULT_SAFETYTIMER_TIME_ms (45*60*1000ul) +// Online crash dumper +//#define EMERGENCY_SERIAL_DUMP // Request dump via serial on stack corruption and WDR +//#define MENU_SERIAL_DUMP // Enable "Memory dump" in Settings menu + // Filament sensor #define FILAMENT_SENSOR #define PAT9125 diff --git a/Firmware/variants/1_75mm_MK25S-RAMBo10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK25S-RAMBo10a-E3Dv6full.h index 4540fd729..74ef38b6e 100644 --- a/Firmware/variants/1_75mm_MK25S-RAMBo10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK25S-RAMBo10a-E3Dv6full.h @@ -119,6 +119,10 @@ #define DEFAULT_SAFETYTIMER_TIME_MINS 30 #define FARM_DEFAULT_SAFETYTIMER_TIME_ms (45*60*1000ul) +// Online crash dumper +//#define EMERGENCY_SERIAL_DUMP // Request dump via serial on stack corruption and WDR +//#define MENU_SERIAL_DUMP // Enable "Memory dump" in Settings menu + // Filament sensor #define FILAMENT_SENSOR #define IR_SENSOR diff --git a/Firmware/variants/1_75mm_MK25S-RAMBo13a-E3Dv6full.h b/Firmware/variants/1_75mm_MK25S-RAMBo13a-E3Dv6full.h index 53773e97c..177586135 100644 --- a/Firmware/variants/1_75mm_MK25S-RAMBo13a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK25S-RAMBo13a-E3Dv6full.h @@ -120,6 +120,10 @@ #define DEFAULT_SAFETYTIMER_TIME_MINS 30 #define FARM_DEFAULT_SAFETYTIMER_TIME_ms (45*60*1000ul) +// Online crash dumper +//#define EMERGENCY_SERIAL_DUMP // Request dump via serial on stack corruption and WDR +//#define MENU_SERIAL_DUMP // Enable "Memory dump" in Settings menu + // Filament sensor #define FILAMENT_SENSOR #define IR_SENSOR diff --git a/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h index f6b178896..66643556a 100644 --- a/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h @@ -144,6 +144,10 @@ //#define MENU_DUMP // enable "Memory dump" in Settings menu //#define EMERGENCY_DUMP // trigger crash on stack corruption and WDR +// Online crash dumper +//#define EMERGENCY_SERIAL_DUMP // Request dump via serial on stack corruption and WDR +//#define MENU_SERIAL_DUMP // Enable "Memory dump" in Settings menu + // Filament sensor #define FILAMENT_SENSOR #define PAT9125 diff --git a/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h index 92698b47a..842ff40be 100644 --- a/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h @@ -146,6 +146,10 @@ //#define MENU_DUMP // enable "Memory dump" in Settings menu //#define EMERGENCY_DUMP // trigger crash on stack corruption and WDR +// Online crash dumper +//#define EMERGENCY_SERIAL_DUMP // Request dump via serial on stack corruption and WDR +//#define MENU_SERIAL_DUMP // Enable "Memory dump" in Settings menu + // Filament sensor #define FILAMENT_SENSOR #define IR_SENSOR diff --git a/Firmware/xflash_dump.h b/Firmware/xflash_dump.h index 658ecd2dc..f517a5921 100644 --- a/Firmware/xflash_dump.h +++ b/Firmware/xflash_dump.h @@ -1,10 +1,6 @@ // XFLASH dumper #pragma once #include "xflash_layout.h" -#ifdef XFLASH_DUMP - -void xfdump_reset(); // reset XFLASH dump state -void xfdump_dump(); // create a new SRAM memory dump enum class dump_crash_reason : uint8_t { @@ -13,10 +9,13 @@ enum class dump_crash_reason : uint8_t watchdog, }; +#ifdef XFLASH_DUMP +void xfdump_reset(); // reset XFLASH dump state +void xfdump_dump(); // 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); - #endif diff --git a/Firmware/xyzcal.cpp b/Firmware/xyzcal.cpp index bc3353070..cc2d940df 100644 --- a/Firmware/xyzcal.cpp +++ b/Firmware/xyzcal.cpp @@ -163,9 +163,9 @@ void xyzcal_meassure_leave(void) ENABLE_STEPPER_DRIVER_INTERRUPT(); #ifdef WATCHDOG wdt_enable(WDTO_4S); -#ifdef EMERGENCY_DUMP +#ifdef EMERGENCY_HANDLERS WDTCSR |= (1 << WDIE); -#endif //EMERGENCY_DUMP +#endif //EMERGENCY_HANDLERS #endif //WATCHDOG sm4_stop_cb = 0; sm4_update_pos_cb = 0;