BUGFIX: fix issue 6 to really disable watchdog timer
authorStephan Baerwolf <stephan.baerwolf@tu-ilmenau.de>
Sun, 31 Mar 2013 17:31:23 +0000 (19:31 +0200)
committerStephan Baerwolf <stephan.baerwolf@tu-ilmenau.de>
Sun, 31 Mar 2013 23:04:38 +0000 (23:04 +0000)
On "https://github.com/baerwolf/USBaspLoader/issues/6" coldtobi
reported an issue of disabling the watchdog timer in a wrong way.
(At least on some newer devices.)
This can lead to unexpected reboots within bootloader mode,
and result in data losses / broken firmwares.

The original report:
====================

At least on the ATMega644, the MCUSR bit WDRF in the MCUSR needs to be cleared first, otherwise it is not possible to disable the watchdog. (See http://www.atmel.com/Images/doc2593.pdf, p.53)

    ? Bit 3 - WDE: Watchdog System Reset Enable
    WDE is overridden by WDRF in MCUSR. This means that WDE is always set when
    WDRF is set. To clear WDE, WDRF must be cleared first. This feature ensures
    multiple resets during conditions causing failure, and a safe start-up after the failure.

    Otherwise the software cannot disable the wdt.

This line just before wdt_disable will fix this

MCUCSR = ~(1<<WDRF);
wdt_disable(); /* main app may have enabled watchdog */

Reported-by: coldtobi <https://github.com/coldtobi>
Signed-off-by: Stephan Baerwolf <stephan.baerwolf@tu-ilmenau.de>
firmware/main.c

index 87f0641..bd36e06 100644 (file)
@@ -644,6 +644,15 @@ int __attribute__((__noreturn__)) main(void)
 #endif
     if(bootLoaderCondition()){
 #if NEED_WATCHDOG
+#      if (defined(MCUSR) && defined(WDRF))
+       /* 
+        * Fix issue 6: (special thanks to coldtobi)
+        * 
+        * The WDRF bit in the MCUSR needs to be cleared first,
+        * otherwise it is not possible to disable the watchdog
+        */
+       MCUSR &= ~(_BV(WDRF));
+#      endif
        wdt_disable();    /* main app may have enabled watchdog */
 #endif
         initForUsbConnectivity();