Using an external watchdog circuit to cycle the power to all your on-board circuity is a rather good idea. It helps to cover cases where some stray external event has caused an upset on some silicon chip circuit. Sometimes these events, whether they be high voltage spikes, reverse bias on signal inputs or even alpha particles can cause localized latchup on-board the chip and the only realistic way to clear such fault is to cycle the power.
Using the scheme to connect the WDT to the enable of the voltage regulator does require some due diligence on your part.
a) Make sure the WDT circuit is not powered by the same voltage rails as the disabled regulator.
b) Make sure that the length of time that the regulator is disabled is long enough. Bypass and filter capacitors on the output of the regulator need to discharge to the greatest degree possible in order to qualify as a power cycle to the silicon. In many instances a millisecond or so of disable time will only allow a partial discharge of the output rails.
You most certainly can. According to the datasheet, the watchdog timer can be setup to reset the MCU or cause an interrupt when it triggers. It seems you are more interested in the interrupt possibility.
The WDT is actually easier to setup than a normal Timer for the same reason it is less useful: fewer options. It runs on an internally calibrated 128kHz clock, meaning its timing is not effected by the main clock speed of the MCU. It can also continue to run during the deepest sleep modes to provide a wake up source.
I will go over a couple of the datasheet examples as well as some code I have used (in C).
Included Files and Definitions
To start, you will probably want to include the following two header files for things to work:
#include <avr/wdt.h> // Supplied Watch Dog Timer Macros
#include <avr/sleep.h> // Supplied AVR Sleep Macros
Also, I use the Macro <_BV(BIT)> which is defined in one of the standard AVR headers as the following (which might be more familial to you):
#define _BV(BIT) (1<<BIT)
Beginning of Code
When the MCU is first started, you would typically initialize the I/O, set up timers, etc. Somewhere here is a good time to make sure the WDT didn't cause a reset because it could do it again, keeping your program in an unstable loop.
if(MCUSR & _BV(WDRF)){ // If a reset was caused by the Watchdog Timer...
MCUSR &= ~_BV(WDRF); // Clear the WDT reset flag
WDTCSR |= (_BV(WDCE) | _BV(WDE)); // Enable the WD Change Bit
WDTCSR = 0x00; // Disable the WDT
}
WDT Setup
Then, after you have setup the rest of the chip, redo the WDT. Setting up the WDT requires a "timed sequence," but it is really easy to do...
// Set up Watch Dog Timer for Inactivity
WDTCSR |= (_BV(WDCE) | _BV(WDE)); // Enable the WD Change Bit
WDTCSR = _BV(WDIE) | // Enable WDT Interrupt
_BV(WDP2) | _BV(WDP1); // Set Timeout to ~1 seconds
Of course, your interrupts should be disabled during this code. Be sure to re-enable them afterwards!
cli(); // Disable the Interrupts
sei(); // Enable the Interrupts
WDT Interrupt Service Routine
The next thing to worry about is handling the WDT ISR. This is done as such:
ISR(WDT_vect)
{
sleep_disable(); // Disable Sleep on Wakeup
// Your code goes here...
// Whatever needs to happen every 1 second
sleep_enable(); // Enable Sleep Mode
}
MCU Sleep
Rather than put the MCU to sleep inside of the WDT ISR, I recommend simply enabling the sleep mode at the end of the ISR, then have the MAIN program put the MCU to sleep. That way, the program is actually leaving the ISR before it goes to sleep, and it will wake up and go directly back into the WDT ISR.
// Enable Sleep Mode for Power Down
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Set Sleep Mode: Power Down
sleep_enable(); // Enable Sleep Mode
sei(); // Enable Interrupts
/****************************
* Enter Main Program Loop *
****************************/
for(;;)
{
if (MCUCR & _BV(SE)){ // If Sleep is Enabled...
cli(); // Disable Interrupts
sleep_bod_disable(); // Disable BOD
sei(); // Enable Interrupts
sleep_cpu(); // Go to Sleep
/****************************
* Sleep Until WDT Times Out
* -> Go to WDT ISR
****************************/
}
}
Best Answer
The "about to fire" indication can be implemented by delaying the reset pulse.
I suggest using a small microcontroller together with reset chip. The internal separately clocked hardware windowed WDT on the MCU can keep the micro honest and then you can use that to implement the reset. For example, you can implement a windowed WDT.
The implementation should be easy enough for anyone that thoroughly understands both microcontrollers and watchdog timers. It won't be much more than a couple of chips.
I assume you've already considered the RPi internal hardware WDT and found it wanting, but you could combine the two to increase the likelihood of a reset occurring under any conceivable circumstances.