My apologies for resurrecting and blowing the dust off this ancient thread about the Arduino Zero Watchdog, but I'd thought I'd share some of my observations and difficulties I've had using it.
1) Generic Clock
By default SAMD21's Watchdog Timer (WDT) is connected to generic clock 2 (GCLK2), whose source is the ultra low power 32.768kHz internal oscillator (OSCULP32K). This allows the WDT to operate while the processor is sleeping and if the main oscillator happens to fail during operation.
The SAMD21 datasheet states that the OSCULP32K is capable of generating both a 32.768kHz and 1.024kHz outputs and suggests that by default the WDT is clocked by the 1.024kHz clock, giving a minimium time before reset of 8ms and a maximum of 16s.
I can only assume that the OSCULP32K's 1.024kHz clock output was at one stage intended, but never implemented, as in reality the WDT is connected directly to the 32.768kHz OSCULP32K, resulting in a minimum time before reset of 250us and a maximum of 0.5s, that's 32 times faster than advertised in the datasheet.
It's possible to obtain the 1.024kHz clock for the 8ms and 16s WDT reset times, by just dividing the OSCULP32K's 32.768kHz clock source by 32 in the GCLK2's generic clock divider register. It's also possible to clock the WDT from any other free GCLK.
2) Synchronization Delay
Furthermore, in order to keep the WDT from timing out it's necessary to load its CLEAR register with a value of 0xA5 (WDT_CLEAR_CLEAR_KEY) in your loop(), however the CLEAR register requires synchronization:
REG_WDT_CLEAR = WDT_CLEAR_CLEAR_KEY; // Clear the watchdog timer
while(WDT->STATUS.bit.SYNCBUSY); // Wait for synchronization
The thing is, with the WDT being clocked by a 1.024kHz generic clock, this leads to a massive 5ms synchronization delay, as the code blocks in the while loop. If you insert this code into any high performance application, well...it won't be high performance any longer.
Fortunately, a user named kaktus circuits has come up with a rather neat solution on the hackaday.io website: Found and fixed a bug in sketch for Arduino Zero | Details | Hackaday.io.
The solution is to simply test for synchronization before writing to the WDT's CLEAR register, instead of using a blocking while loop:
if (!WDT->STATUS.bit.SYNCBUSY) // Check if the WDT registers are synchronized
{
REG_WDT_CLEAR = WDT_CLEAR_CLEAR_KEY; // Clear the watchdog timer
}
You can get away with doing this, as normally this the only WDT register you need to access in the loop() portion of your code. The if() statement is just checking that the synchronization of the CLEAR register is not currently taking place, before the register is written. If you're looping faster than 5ms then occasionally you'll skip a write, but this should be OK provided your WDT timeout is long enough. This enables the SAMD21's WDT to be used with high performance applications without any synchronization delay.
Thanks kaktus circuits.