Przeglądaj źródła

Merge pull request #3833 from leptun/MK3_fix_MK2.5_softReset

Alex Voinea 1 rok temu
rodzic
commit
2b38080c7e

+ 38 - 9
Firmware/Marlin_main.cpp

@@ -84,6 +84,7 @@
 #include "Prusa_farm.h"
 
 #include <avr/wdt.h>
+#include <util/atomic.h>
 #include <avr/pgmspace.h>
 
 #include "Tcodes.h"
@@ -693,10 +694,40 @@ void failstats_reset_print()
 	eeprom_update_byte((uint8_t *)EEPROM_MMU_LOAD_FAIL, 0);
 }
 
-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);
 }
 
@@ -1043,6 +1074,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
 
 
@@ -4281,17 +4314,13 @@ void process_commands()
 			MMU2::mmu2.Reset(MMU2::MMU2::Software);
 		}
 		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
-        }
-	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])

+ 2 - 4
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 {

+ 1 - 0
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
 

+ 2 - 0
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

+ 2 - 0
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