Hi @anthonylimon
The issue with the WDTZero library is that it doesn't take into account the time taken to synchronise registers on the SAMD21.
The SAMD21 has the advantage of a flexible clock system that allows practically any on-chip or external clock source to drive its peripheral modules, such as its TCC/TC timers, RTC, WDT etc... The disadvantage however is that certain registers have to be read and/or write synchronised between the peripheral and the CPU, this can take up to 5 to 6 clock source cycles.
The problem occurs if the clock source that's driving the peripheral is slow, such as the on-chip, low power 32.768kHz oscillator usually used to clock the watchdog. In this case, resetting the watchdog by writing CLEAR register requires a synchronisation time of 5 to 6 milliseconds.
The standard procedure for write synchronisation is to block and wait for the periperhal's register to synchronise:
WDT->CLEAR.reg = WDT_CLEAR_CLEAR_KEY; // Reset the watchdog
while(WDT->STATUS.bit.SYNCBUSY); // Wait for synchronisation
This works just fine if the peripheral is clocked at 48MHz like the CPU, but causes the program to block for 5 to 6 millisconds while writing to the watchdog's CLEAR register. This can be problematic if your program requires a fast loop time.
The solution is to use an if() statement in the loop(), to check whether register synchronisation is taking place, and only reset the watchdog if it isn't:
if (!WDT->STATUS.bit.SYNCBUSY) // Check if the WDT register CLEAR register is not being synchronized
{
WDT->CLEAR.reg = WDT_CLEAR_CLEAR_KEY; // Reset the watchdog timer
}
This allows the watchdog to be reset without blocking. It might be worth modifying WDTZero library's clear() function, since others have raised a pull request for this change on Github, but the owner hasn't responded.
This issue was first described here: