diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index eafe7b77..58c50f6c 100644 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -84,6 +84,7 @@ #include "Prusa_farm.h" #include +#include #include #include "Dcodes.h" @@ -700,10 +701,40 @@ void failstats_reset_print() #endif } -void softReset() -{ +void watchdogEarlyDisable(void) { + // Regardless if the watchdog support is enabled or not, disable the watchdog very early + // after the program starts since there's no danger in doing this. + // The reason for this is because old bootloaders might not handle the watchdog timer at all, + // leaving it enabled when jumping to the program. This could cause another watchdog reset + // during setup() if not handled properly. So to avoid any issue of this kind, stop the + // watchdog timer manually. + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { + wdt_reset(); + MCUSR &= ~_BV(WDRF); + wdt_disable(); + } +} + +void softReset(void) { cli(); - wdt_enable(WDTO_15MS); +#ifdef WATCHDOG + // If the watchdog support is enabled, use that for resetting. The timeout value is customized + // for each board since the miniRambo ships with a bootloader which doesn't properly handle the + // WDT. In order to avoid bootlooping, the watchdog is set to a value large enough for the + // usual timeout of the bootloader to pass. + wdt_enable(WATCHDOG_SOFT_RESET_VALUE); +#else + #warning WATCHDOG not defined. See the following comment for more details about the implications + // In case the watchdog is not enabled, the reset is acomplished by jumping to the bootloader + // vector manually. This however is somewhat dangerous since the peripherals don't get reset + // by this operation. Considering this is not going to be used in any production firmware, + // it can be left as is and just be cautious with it. The only way to accomplish a peripheral + // reset is by an external reset, by a watchdog reset or by a power cycle. All of these options + // can't be accomplished just from software. One way to minimize the dangers of this is by + // setting all dangerous pins to INPUT before jumping to the bootloader, but that still doesn't + // reset other peripherals such as UART, timers, INT, PCINT, etc... + asm volatile("jmp 0x3E000"); +#endif while(1); } @@ -1061,6 +1092,8 @@ static void xflash_err_msg() // are initialized by the main() routine provided by the Arduino framework. void setup() { + watchdogEarlyDisable(); + timer2_init(); // enables functional millis mmu_init(); @@ -4282,18 +4315,14 @@ void process_commands() mmu_reset(); } else if (code_seen_P(PSTR("RESET"))) { // PRUSA RESET -#ifdef WATCHDOG #if defined(XFLASH) && defined(BOOTAPP) boot_app_magic = BOOT_APP_MAGIC; boot_app_flags = BOOT_APP_FLG_RUN; #endif //defined(XFLASH) && defined(BOOTAPP) softReset(); -#elif defined(BOOTAPP) //this is a safety precaution. This is because the new bootloader turns off the heaters, but the old one doesn't. The watchdog should be used most of the time. - asm volatile("jmp 0x3E000"); -#endif - } + } #ifdef PRUSA_SN_SUPPORT - else if (code_seen_P(PSTR("SN"))) { // PRUSA SN + else if (code_seen_P(PSTR("SN"))) { // PRUSA SN char SN[20]; eeprom_read_block(SN, (uint8_t*)EEPROM_PRUSA_SN, 20); if (SN[19]) diff --git a/Firmware/optiboot_xflash.cpp b/Firmware/optiboot_xflash.cpp index 02d19891..791435b8 100644 --- a/Firmware/optiboot_xflash.cpp +++ b/Firmware/optiboot_xflash.cpp @@ -55,9 +55,7 @@ static void putch(char ch) { static void verifySpace() { if (getch() != CRC_EOP) { putch(STK_FAILED); - wdt_enable(WDTO_15MS); // shorten WD timeout - while (1) // and busy-loop so that WD causes - ; // a reset and app start. + softReset(); } putch(STK_INSYNC); } @@ -300,7 +298,7 @@ uint8_t optiboot_xflash_enter() } else if (ch == STK_LEAVE_PROGMODE) { /* 'Q' */ // Adaboot no-wait mod - wdt_enable(WDTO_15MS); + wdt_enable(WATCHDOG_SOFT_RESET_VALUE); verifySpace(); } else { diff --git a/Firmware/pins_Einsy_1_0.h b/Firmware/pins_Einsy_1_0.h index d8c316b4..12409de4 100755 --- a/Firmware/pins_Einsy_1_0.h +++ b/Firmware/pins_Einsy_1_0.h @@ -19,6 +19,7 @@ #define XFLASH // external 256kB flash #define BOOTAPP // bootloader support +#define WATCHDOG_SOFT_RESET_VALUE WDTO_15MS #define XFLASH_PIN_CS 32 diff --git a/Firmware/pins_Rambo_1_0.h b/Firmware/pins_Rambo_1_0.h index b727e52f..17629af6 100644 --- a/Firmware/pins_Rambo_1_0.h +++ b/Firmware/pins_Rambo_1_0.h @@ -14,6 +14,8 @@ #define SWI2C_SDA 20 //SDA on P3 #define SWI2C_SCL 84 //PH2 on P3, sensor cable must be rewired +// This should be long enough to safely exit the bootloader when it uses the default timeout (~1-2s) +#define WATCHDOG_SOFT_RESET_VALUE WDTO_2S #define X_STEP_PIN 37 diff --git a/Firmware/pins_Rambo_1_3.h b/Firmware/pins_Rambo_1_3.h index e6bdfd93..3d8099e5 100644 --- a/Firmware/pins_Rambo_1_3.h +++ b/Firmware/pins_Rambo_1_3.h @@ -17,6 +17,8 @@ #define D_REQUIRE 23 //Z_MAX (white) #endif //MICROMETER_LOGGING +// This should be long enough to safely exit the bootloader when it uses the default timeout (~1-2s) +#define WATCHDOG_SOFT_RESET_VALUE WDTO_2S #define X_STEP_PIN 37