[OpenTRV-dev] New (slow, zero-power) watchdog

Damon Hart-Davis damon at opentrv.uk
Wed Apr 13 16:08:47 BST 2016


Hi,

I have just slipped in some code in the mainline and OTRadio link (being tested) to support a near-zero-power watchdog to help with reliability, see:

https://opentrv.atlassian.net/browse/TODO-887

Basically if a particular routine is not called at least once each time round the main 2-second loop (and interrupts aren’t blocked) then the device will reset and restart.

We’ve been having some puzzling device deaths (going off the air after a number of days) for ourselves and COHEAT, and I’m hoping this may deal with at least some of them in an acceptable way.

It’s not as comprehensive as using the MCU’s built-in watchdog directly but avoids adding any extra power drain to run the watchdog clock, and leaves the WDT free to be used for other things, with the only overhead being a few extra instructions in the RTC interrupt and the main loop.  Look at the end of the RTC header and .cpp file for:



// RTC-based watchdog, if enabled with enableRTCWatchdog(true),
// will force a reset if the resetRTCWatchDog() is not called
// between one RTC tick interrupt and the next.
//
// One possible usage: as start of each major tick in main loop,
// call resetRTCWatchDog() immediately followed by enableRTCWatchdog(true).
//
// If true, then enable the RTC-based watchdog; disable otherwise.
void enableRTCWatchdog(bool enable);
// Must be called between each 'tick' of the RTC clock if enabled, else system will reset.
void resetRTCWatchDog();



and in the sleep header for:



// Forced MCU reset/restart as near full cold-reset as possible.
// Turns off interrupts, sets the watchdog, and busy-spins until the watchdog forces a reset.
// The watchdog timeout is long enough that a watchdog-oblivious bootloader
// can successfully drop through to the main code which can the stop a further reset
// else the main line code may never be reached.
// Inline to give the compiler full visibility for efficient use in ISR code (eg avoid full register save).
//
// Background on implementation and issues, see for example:
//   http://forum.arduino.cc/index.php?topic=12874.0
//   http://playground.arduino.cc/Main/ArduinoReset
// This suggests that a timeout of > 2s may be OK with the optiboot loader:
//   https://tushev.org/articles/arduino/5/arduino-and-watchdog-timer
#if defined(__GNUC__)
inline void forceReset() __attribute__ ((noreturn));
#endif // defined(__GNUC__)
#if defined(__AVR_ATmega328P__)
inline void forceReset()
    {
    cli();
    wdt_enable(WDTO_4S); // Must be long enough for bootloader to pass control to main code.
    for( ; ; ) { }
    }
#endif // defined(__AVR_ATmega328P__)



Rgds

Damon


More information about the OpenTRV-dev mailing list