From c39c17c1b5c041a1c90004b09b31571dd9f51f6b Mon Sep 17 00:00:00 2001 From: fedetony <45215920+fedetony@users.noreply.github.com> Date: Sat, 24 Apr 2021 09:53:52 +0200 Subject: [PATCH] Soft Reset via Serial or post-kill button click (#21652) Co-authored-by: Scott Lahteine --- Marlin/Configuration_adv.h | 6 ++++++ Marlin/src/HAL/AVR/HAL.cpp | 9 +++++++++ Marlin/src/HAL/AVR/HAL.h | 2 +- Marlin/src/HAL/DUE/HAL.cpp | 2 ++ Marlin/src/HAL/DUE/HAL.h | 2 +- Marlin/src/HAL/ESP32/HAL.cpp | 2 ++ Marlin/src/HAL/ESP32/HAL.h | 2 +- Marlin/src/HAL/LINUX/HAL.cpp | 2 ++ Marlin/src/HAL/LINUX/HAL.h | 2 +- Marlin/src/HAL/LPC1768/HAL.cpp | 4 +++- Marlin/src/HAL/LPC1768/HAL.h | 2 +- Marlin/src/HAL/SAMD51/HAL.cpp | 2 ++ Marlin/src/HAL/SAMD51/HAL.h | 2 +- Marlin/src/HAL/STM32/HAL.cpp | 6 ++++-- Marlin/src/HAL/STM32/HAL.h | 2 +- Marlin/src/HAL/STM32F1/HAL.cpp | 4 +++- Marlin/src/HAL/STM32F1/HAL.h | 2 +- Marlin/src/HAL/TEENSY31_32/HAL.cpp | 2 ++ Marlin/src/HAL/TEENSY31_32/HAL.h | 3 +-- Marlin/src/HAL/TEENSY35_36/HAL.cpp | 2 ++ Marlin/src/HAL/TEENSY35_36/HAL.h | 2 +- Marlin/src/HAL/TEENSY40_41/HAL.cpp | 2 ++ Marlin/src/HAL/TEENSY40_41/HAL.h | 2 ++ Marlin/src/MarlinCore.cpp | 18 ++++++++++-------- Marlin/src/feature/e_parser.h | 20 ++++++++++++++++++++ Marlin/src/gcode/gcode_d.cpp | 7 ++++++- Marlin/src/inc/SanityCheck.h | 9 ++++++++- Marlin/src/lcd/marlinui.h | 2 +- buildroot/tests/LPC1768 | 2 +- 29 files changed, 97 insertions(+), 27 deletions(-) diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index ac9b49fe4d..d72feab433 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -3976,3 +3976,9 @@ * a crash from a remote location. Requires ~400 bytes of SRAM and 5Kb of flash. */ //#define POSTMORTEM_DEBUGGING + +/** + * Software Reset options + */ +//#define SOFT_RESET_VIA_SERIAL // 'KILL' and '^X' commands will soft-reset the controller +//#define SOFT_RESET_ON_KILL // Use a digital button to soft-reset the controller after KILL diff --git a/Marlin/src/HAL/AVR/HAL.cpp b/Marlin/src/HAL/AVR/HAL.cpp index cfa9e47f18..708583b262 100644 --- a/Marlin/src/HAL/AVR/HAL.cpp +++ b/Marlin/src/HAL/AVR/HAL.cpp @@ -58,6 +58,15 @@ void HAL_init() { #endif } +void HAL_reboot() { + #if ENABLED(USE_WATCHDOG) + while (1) { /* run out the watchdog */ } + #else + void (*resetFunc)() = 0; // Declare resetFunc() at address 0 + resetFunc(); // Jump to address 0 + #endif +} + #if ENABLED(SDSUPPORT) #include "../../sd/SdFatUtil.h" diff --git a/Marlin/src/HAL/AVR/HAL.h b/Marlin/src/HAL/AVR/HAL.h index 890798a719..7adf1aad49 100644 --- a/Marlin/src/HAL/AVR/HAL.h +++ b/Marlin/src/HAL/AVR/HAL.h @@ -135,7 +135,7 @@ void HAL_init(); inline void HAL_clear_reset_source() { MCUSR = 0; } inline uint8_t HAL_get_reset_source() { return MCUSR; } -inline void HAL_reboot() {} // reboot the board or restart the bootloader +void HAL_reboot(); #if GCC_VERSION <= 50000 #pragma GCC diagnostic push diff --git a/Marlin/src/HAL/DUE/HAL.cpp b/Marlin/src/HAL/DUE/HAL.cpp index 249535723f..a3985652e7 100644 --- a/Marlin/src/HAL/DUE/HAL.cpp +++ b/Marlin/src/HAL/DUE/HAL.cpp @@ -77,6 +77,8 @@ uint8_t HAL_get_reset_source() { } } +void HAL_reboot() { rstc_start_software_reset(RSTC); } + void _delay_ms(const int delay_ms) { // Todo: port for Due? delay(delay_ms); diff --git a/Marlin/src/HAL/DUE/HAL.h b/Marlin/src/HAL/DUE/HAL.h index 501e2f0b06..1bc3bf7410 100644 --- a/Marlin/src/HAL/DUE/HAL.h +++ b/Marlin/src/HAL/DUE/HAL.h @@ -113,7 +113,7 @@ void sei(); // Enable interrupts void HAL_clear_reset_source(); // clear reset reason uint8_t HAL_get_reset_source(); // get reset reason -inline void HAL_reboot() {} // reboot the board or restart the bootloader +void HAL_reboot(); // // ADC diff --git a/Marlin/src/HAL/ESP32/HAL.cpp b/Marlin/src/HAL/ESP32/HAL.cpp index 365706c3e2..7818dbdd87 100644 --- a/Marlin/src/HAL/ESP32/HAL.cpp +++ b/Marlin/src/HAL/ESP32/HAL.cpp @@ -141,6 +141,8 @@ void HAL_clear_reset_source() { } uint8_t HAL_get_reset_source() { return rtc_get_reset_reason(1); } +void HAL_reboot() { ESP.restart(); } + void _delay_ms(int delay_ms) { delay(delay_ms); } // return free memory between end of heap (or end bss) and whatever is current diff --git a/Marlin/src/HAL/ESP32/HAL.h b/Marlin/src/HAL/ESP32/HAL.h index 9258f97702..0f92052030 100644 --- a/Marlin/src/HAL/ESP32/HAL.h +++ b/Marlin/src/HAL/ESP32/HAL.h @@ -101,7 +101,7 @@ void HAL_clear_reset_source(); // reset reason uint8_t HAL_get_reset_source(); -inline void HAL_reboot() {} // reboot the board or restart the bootloader +void HAL_reboot(); void _delay_ms(int delay); diff --git a/Marlin/src/HAL/LINUX/HAL.cpp b/Marlin/src/HAL/LINUX/HAL.cpp index 771f1d2a08..0b679170ef 100644 --- a/Marlin/src/HAL/LINUX/HAL.cpp +++ b/Marlin/src/HAL/LINUX/HAL.cpp @@ -73,4 +73,6 @@ void HAL_pwm_init() { } +void HAL_reboot() { /* Reset the application state and GPIO */ } + #endif // __PLAT_LINUX__ diff --git a/Marlin/src/HAL/LINUX/HAL.h b/Marlin/src/HAL/LINUX/HAL.h index f21e3e2c65..36906bffc8 100644 --- a/Marlin/src/HAL/LINUX/HAL.h +++ b/Marlin/src/HAL/LINUX/HAL.h @@ -107,7 +107,7 @@ uint16_t HAL_adc_get_result(); inline void HAL_clear_reset_source(void) {} inline uint8_t HAL_get_reset_source(void) { return RST_POWER_ON; } -inline void HAL_reboot() {} // reboot the board or restart the bootloader +void HAL_reboot(); // Reset the application state and GPIO /* ---------------- Delay in cycles */ FORCE_INLINE static void DELAY_CYCLES(uint64_t x) { diff --git a/Marlin/src/HAL/LPC1768/HAL.cpp b/Marlin/src/HAL/LPC1768/HAL.cpp index 442c41afe7..cee9cfc5f7 100644 --- a/Marlin/src/HAL/LPC1768/HAL.cpp +++ b/Marlin/src/HAL/LPC1768/HAL.cpp @@ -67,7 +67,7 @@ void flashFirmware(const int16_t) { delay(500); // Give OS time to disconnect USB_Connect(false); // USB clear connection delay(1000); // Give OS time to notice - NVIC_SystemReset(); + HAL_reboot(); } void HAL_clear_reset_source(void) { @@ -81,4 +81,6 @@ uint8_t HAL_get_reset_source(void) { return RST_POWER_ON; } +void HAL_reboot() { NVIC_SystemReset(); } + #endif // TARGET_LPC1768 diff --git a/Marlin/src/HAL/LPC1768/HAL.h b/Marlin/src/HAL/LPC1768/HAL.h index 07385261da..bcfa6c412f 100644 --- a/Marlin/src/HAL/LPC1768/HAL.h +++ b/Marlin/src/HAL/LPC1768/HAL.h @@ -218,4 +218,4 @@ void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size=255, void HAL_clear_reset_source(void); uint8_t HAL_get_reset_source(void); -inline void HAL_reboot() {} // reboot the board or restart the bootloader +void HAL_reboot(); diff --git a/Marlin/src/HAL/SAMD51/HAL.cpp b/Marlin/src/HAL/SAMD51/HAL.cpp index 39167fc467..5aa23cdaeb 100644 --- a/Marlin/src/HAL/SAMD51/HAL.cpp +++ b/Marlin/src/HAL/SAMD51/HAL.cpp @@ -436,6 +436,8 @@ uint8_t HAL_get_reset_source() { } #pragma pop_macro("WDT") +void HAL_reboot() { NVIC_SystemReset(); } + extern "C" { void * _sbrk(int incr); diff --git a/Marlin/src/HAL/SAMD51/HAL.h b/Marlin/src/HAL/SAMD51/HAL.h index 3add6c9b69..85ac5dd00c 100644 --- a/Marlin/src/HAL/SAMD51/HAL.h +++ b/Marlin/src/HAL/SAMD51/HAL.h @@ -109,7 +109,7 @@ typedef int8_t pin_t; void HAL_clear_reset_source(); // clear reset reason uint8_t HAL_get_reset_source(); // get reset reason -inline void HAL_reboot() {} // reboot the board or restart the bootloader +void HAL_reboot(); // // ADC diff --git a/Marlin/src/HAL/STM32/HAL.cpp b/Marlin/src/HAL/STM32/HAL.cpp index c66f061d91..3bb12fd9e0 100644 --- a/Marlin/src/HAL/STM32/HAL.cpp +++ b/Marlin/src/HAL/STM32/HAL.cpp @@ -133,6 +133,8 @@ uint8_t HAL_get_reset_source() { ; } +void HAL_reboot() { NVIC_SystemReset(); } + void _delay_ms(const int delay_ms) { delay(delay_ms); } extern "C" { @@ -147,8 +149,8 @@ extern "C" { void HAL_adc_start_conversion(const uint8_t adc_pin) { HAL_adc_result = analogRead(adc_pin); } uint16_t HAL_adc_get_result() { return HAL_adc_result; } -// Reset the system (to initiate a firmware flash) -void flashFirmware(const int16_t) { NVIC_SystemReset(); } +// Reset the system to initiate a firmware flash +void flashFirmware(const int16_t) { HAL_reboot(); } // Maple Compatibility volatile uint32_t systick_uptime_millis = 0; diff --git a/Marlin/src/HAL/STM32/HAL.h b/Marlin/src/HAL/STM32/HAL.h index d8e45670e6..469d08e435 100644 --- a/Marlin/src/HAL/STM32/HAL.h +++ b/Marlin/src/HAL/STM32/HAL.h @@ -144,7 +144,7 @@ void HAL_clear_reset_source(); // Reset reason uint8_t HAL_get_reset_source(); -inline void HAL_reboot() {} // reboot the board or restart the bootloader +void HAL_reboot(); void _delay_ms(const int delay); diff --git a/Marlin/src/HAL/STM32F1/HAL.cpp b/Marlin/src/HAL/STM32F1/HAL.cpp index 40452b5d70..2efea4f001 100644 --- a/Marlin/src/HAL/STM32F1/HAL.cpp +++ b/Marlin/src/HAL/STM32F1/HAL.cpp @@ -453,6 +453,8 @@ void analogWrite(pin_t pin, int pwm_val8) { analogWrite(uint8_t(pin), pwm_val8); } -void flashFirmware(const int16_t) { nvic_sys_reset(); } +void HAL_reboot() { nvic_sys_reset(); } + +void flashFirmware(const int16_t) { HAL_reboot(); } #endif // __STM32F1__ diff --git a/Marlin/src/HAL/STM32F1/HAL.h b/Marlin/src/HAL/STM32F1/HAL.h index f37b0f2728..af4d27f43e 100644 --- a/Marlin/src/HAL/STM32F1/HAL.h +++ b/Marlin/src/HAL/STM32F1/HAL.h @@ -207,7 +207,7 @@ void HAL_clear_reset_source(); // Reset reason uint8_t HAL_get_reset_source(); -inline void HAL_reboot() {} // reboot the board or restart the bootloader +void HAL_reboot(); void _delay_ms(const int delay); diff --git a/Marlin/src/HAL/TEENSY31_32/HAL.cpp b/Marlin/src/HAL/TEENSY31_32/HAL.cpp index 67f716c5d3..f08cf799e9 100644 --- a/Marlin/src/HAL/TEENSY31_32/HAL.cpp +++ b/Marlin/src/HAL/TEENSY31_32/HAL.cpp @@ -78,6 +78,8 @@ uint8_t HAL_get_reset_source() { return 0; } +void HAL_reboot() { _reboot_Teensyduino_(); } + extern "C" { extern char __bss_end; extern char __heap_start; diff --git a/Marlin/src/HAL/TEENSY31_32/HAL.h b/Marlin/src/HAL/TEENSY31_32/HAL.h index bbfc50a36f..52904465be 100644 --- a/Marlin/src/HAL/TEENSY31_32/HAL.h +++ b/Marlin/src/HAL/TEENSY31_32/HAL.h @@ -34,7 +34,6 @@ #include "fastio.h" #include "watchdog.h" - #include #define ST7920_DELAY_1 DELAY_NS(600) @@ -93,7 +92,7 @@ void HAL_clear_reset_source(); // Get the reason for the reset uint8_t HAL_get_reset_source(); -inline void HAL_reboot() {} // reboot the board or restart the bootloader +void HAL_reboot(); FORCE_INLINE void _delay_ms(const int delay_ms) { delay(delay_ms); } diff --git a/Marlin/src/HAL/TEENSY35_36/HAL.cpp b/Marlin/src/HAL/TEENSY35_36/HAL.cpp index 5d808cd19b..046c00b56e 100644 --- a/Marlin/src/HAL/TEENSY35_36/HAL.cpp +++ b/Marlin/src/HAL/TEENSY35_36/HAL.cpp @@ -86,6 +86,8 @@ uint8_t HAL_get_reset_source() { return 0; } +void HAL_reboot() { _reboot_Teensyduino_(); } + extern "C" { extern char __bss_end; extern char __heap_start; diff --git a/Marlin/src/HAL/TEENSY35_36/HAL.h b/Marlin/src/HAL/TEENSY35_36/HAL.h index 50008d72f6..26c35223bd 100644 --- a/Marlin/src/HAL/TEENSY35_36/HAL.h +++ b/Marlin/src/HAL/TEENSY35_36/HAL.h @@ -101,7 +101,7 @@ void HAL_clear_reset_source(); // Reset reason uint8_t HAL_get_reset_source(); -inline void HAL_reboot() {} // reboot the board or restart the bootloader +void HAL_reboot(); FORCE_INLINE void _delay_ms(const int delay_ms) { delay(delay_ms); } diff --git a/Marlin/src/HAL/TEENSY40_41/HAL.cpp b/Marlin/src/HAL/TEENSY40_41/HAL.cpp index 1eab3d837e..a986c293a9 100644 --- a/Marlin/src/HAL/TEENSY40_41/HAL.cpp +++ b/Marlin/src/HAL/TEENSY40_41/HAL.cpp @@ -120,6 +120,8 @@ uint8_t HAL_get_reset_source() { return 0; } +void HAL_reboot() { _reboot_Teensyduino_(); } + #define __bss_end _ebss extern "C" { diff --git a/Marlin/src/HAL/TEENSY40_41/HAL.h b/Marlin/src/HAL/TEENSY40_41/HAL.h index 701d690382..1d00447fe8 100644 --- a/Marlin/src/HAL/TEENSY40_41/HAL.h +++ b/Marlin/src/HAL/TEENSY40_41/HAL.h @@ -121,6 +121,8 @@ void HAL_clear_reset_source(); // Reset reason uint8_t HAL_get_reset_source(); +void HAL_reboot(); + FORCE_INLINE void _delay_ms(const int delay_ms) { delay(delay_ms); } #if GCC_VERSION <= 50000 diff --git a/Marlin/src/MarlinCore.cpp b/Marlin/src/MarlinCore.cpp index 6cb51bc577..7139d54f25 100644 --- a/Marlin/src/MarlinCore.cpp +++ b/Marlin/src/MarlinCore.cpp @@ -863,20 +863,22 @@ void minkill(const bool steppers_off/*=false*/) { TERN_(HAS_SUICIDE, suicide()); - #if HAS_KILL + #if EITHER(HAS_KILL, SOFT_RESET_ON_KILL) - // Wait for kill to be released - while (kill_state()) watchdog_refresh(); + // Wait for both KILL and ENC to be released + while (TERN0(HAS_KILL, !kill_state()) || TERN0(SOFT_RESET_ON_KILL, !ui.button_pressed())) + watchdog_refresh(); - // Wait for kill to be pressed - while (!kill_state()) watchdog_refresh(); + // Wait for either KILL or ENC press + while (TERN1(HAS_KILL, kill_state()) && TERN1(SOFT_RESET_ON_KILL, ui.button_pressed())) + watchdog_refresh(); - void (*resetFunc)() = 0; // Declare resetFunc() at address 0 - resetFunc(); // Jump to address 0 + // Reboot the board + HAL_reboot(); #else - for (;;) watchdog_refresh(); // Wait for reset + for (;;) watchdog_refresh(); // Wait for RESET button or power-cycle #endif } diff --git a/Marlin/src/feature/e_parser.h b/Marlin/src/feature/e_parser.h index c12fd14ad1..3723caa35e 100644 --- a/Marlin/src/feature/e_parser.h +++ b/Marlin/src/feature/e_parser.h @@ -41,6 +41,8 @@ extern bool wait_for_user, wait_for_heatup; void quickresume_stepper(); #endif +void HAL_reboot(); + class EmergencyParser { public: @@ -62,6 +64,10 @@ public: EP_R, EP_R0, EP_R00, EP_GRBL_RESUME, EP_P, EP_P0, EP_P00, EP_GRBL_PAUSE, #endif + #if ENABLED(SOFT_RESET_VIA_SERIAL) + EP_ctrl, + EP_K, EP_KI, EP_KIL, EP_KILL, + #endif EP_IGNORE // to '\n' }; @@ -89,6 +95,10 @@ public: case 'P': state = EP_P; break; case 'R': state = EP_R; break; #endif + #if ENABLED(SOFT_RESET_VIA_SERIAL) + case '^': state = EP_ctrl; break; + case 'K': state = EP_K; break; + #endif default: state = EP_IGNORE; } break; @@ -121,6 +131,13 @@ public: case EP_P00: state = (c == '0') ? EP_GRBL_PAUSE : EP_IGNORE; break; #endif + #if ENABLED(SOFT_RESET_VIA_SERIAL) + case EP_ctrl: state = (c == 'X') ? EP_KILL : EP_IGNORE; break; + case EP_K: state = (c == 'I') ? EP_KI : EP_IGNORE; break; + case EP_KI: state = (c == 'L') ? EP_KIL : EP_IGNORE; break; + case EP_KIL: state = (c == 'L') ? EP_KILL : EP_IGNORE; break; + #endif + case EP_M: switch (c) { case ' ': break; @@ -189,6 +206,9 @@ public: case EP_GRBL_PAUSE: quickpause_stepper(); break; case EP_GRBL_RESUME: quickresume_stepper(); break; #endif + #if ENABLED(SOFT_RESET_VIA_SERIAL) + case EP_KILL: HAL_reboot(); break; + #endif default: break; } state = EP_RESET; diff --git a/Marlin/src/gcode/gcode_d.cpp b/Marlin/src/gcode/gcode_d.cpp index f87cebc886..74277291e5 100644 --- a/Marlin/src/gcode/gcode_d.cpp +++ b/Marlin/src/gcode/gcode_d.cpp @@ -30,6 +30,7 @@ #include "../HAL/shared/eeprom_if.h" #include "../HAL/shared/Delay.h" #include "../sd/cardreader.h" + #include "../MarlinCore.h" // for kill extern void dump_delay_accuracy_check(); @@ -44,12 +45,16 @@ switch (dcode) { case -1: - for (;;); // forever + for (;;) { /* loop forever (watchdog reset) */ } case 0: HAL_reboot(); break; + case 10: + kill(PSTR("D10"), PSTR("KILL TEST"), parser.seen('P')); + break; + case 1: { // Zero or pattern-fill the EEPROM data #if ENABLED(EEPROM_SETTINGS) diff --git a/Marlin/src/inc/SanityCheck.h b/Marlin/src/inc/SanityCheck.h index 5a9d6e6040..2d6633b353 100644 --- a/Marlin/src/inc/SanityCheck.h +++ b/Marlin/src/inc/SanityCheck.h @@ -2208,12 +2208,19 @@ static_assert(hbm[Z_AXIS] >= 0, "HOMING_BUMP_MM.Z must be greater than or equal #endif /** - * emergency-command parser + * Emergency Command Parser */ #if ENABLED(EMERGENCY_PARSER) && defined(__AVR__) && defined(USBCON) #error "EMERGENCY_PARSER does not work on boards with AT90USB processors (USBCON)." #endif +/** + * Software Reset on Kill option + */ +#if ENABLED(SOFT_RESET_ON_KILL) && !BUTTON_EXISTS(ENC) + #error "An encoder button is required or SOFT_RESET_ON_KILL will reset the printer without notice!" +#endif + /** * I2C bus */ diff --git a/Marlin/src/lcd/marlinui.h b/Marlin/src/lcd/marlinui.h index 8cbb9ebd19..8befa1d980 100644 --- a/Marlin/src/lcd/marlinui.h +++ b/Marlin/src/lcd/marlinui.h @@ -39,7 +39,7 @@ #include "tft_io/touch_calibration.h" #endif -#if EITHER(HAS_LCD_MENU, ULTIPANEL_FEEDMULTIPLY) +#if ANY(HAS_LCD_MENU, ULTIPANEL_FEEDMULTIPLY, SOFT_RESET_ON_KILL) #define HAS_ENCODER_ACTION 1 #endif diff --git a/buildroot/tests/LPC1768 b/buildroot/tests/LPC1768 index 152a49852a..6b9f6aaac3 100755 --- a/buildroot/tests/LPC1768 +++ b/buildroot/tests/LPC1768 @@ -45,7 +45,7 @@ opt_enable REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER ADAPTIVE_FAN_SLOWING NO Z_SAFE_HOMING ADVANCED_PAUSE_FEATURE PARK_HEAD_ON_PAUSE \ HOST_KEEPALIVE_FEATURE HOST_ACTION_COMMANDS HOST_PROMPT_SUPPORT \ LCD_INFO_MENU ARC_SUPPORT BEZIER_CURVE_SUPPORT EXTENDED_CAPABILITIES_REPORT AUTO_REPORT_TEMPERATURES \ - SDSUPPORT SDCARD_SORT_ALPHA AUTO_REPORT_SD_STATUS EMERGENCY_PARSER + SDSUPPORT SDCARD_SORT_ALPHA AUTO_REPORT_SD_STATUS EMERGENCY_PARSER SOFT_RESET_ON_KILL SOFT_RESET_VIA_SERIAL exec_test $1 $2 "Re-ARM with NOZZLE_AS_PROBE and many features." "$3" # clean up