Hi
Does anybody know of a watchdog library that works with the MKR Zero? I have tried a few but no dice.
Nick
Hi
Does anybody know of a watchdog library that works with the MKR Zero? I have tried a few but no dice.
Nick
Hi,
Did you find a solution to this? Did you try the SleepyDog library?
I know this is an old post, but here is what I found (sorry to the original/source of this as I am not sure where I originally found it but thank you!).
I wanted a simple watchdog reset only, no sleep modes, just feed a watchdog clear and reset the SAMD21 if it does not get cleared within a set time.
Also, I did not want to use a library so this is what I used.
// I needed to add these or it would not compile.
// Each cycle is about 1mS.
#define WDT_CONFIG_PER_3 0x3u // 64 clock cycles
#define WDT_CONFIG_PER_4 0x4u // 128 clock cycles
#define WDT_CONFIG_PER_5 0x5u // 256 clock cycles
#define WDT_CONFIG_PER_6 0x6u // 512 clock cycles
#define WDT_CONFIG_PER_7 0x7u // 1024 clock cycles
#define WDT_CONFIG_PER_8 0x8u // 2048 clock cycles
#define WDT_CONFIG_PER_9 0x9u // 4096 clock cycles
#define WDT_CONFIG_PER_10 0xAu // 8192 clock cycles
#define WDT_CONFIG_PER_11 0xBu // 16384 clock cycles
void watchdog_setup(void){
// Set up the generic clock (GCLK2) used to clock the watchdog timer at 1.024kHz
REG_GCLK_GENDIV = GCLK_GENDIV_DIV(4) | // Divide the 32.768kHz clock source by divisor 32, where 2^(4 + 1): 32.768kHz/32=1.024kHz
GCLK_GENDIV_ID(2); // Select Generic Clock (GCLK) 2
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
REG_GCLK_GENCTRL = GCLK_GENCTRL_DIVSEL | // Set to divide by 2^(GCLK_GENDIV_DIV(4) + 1)
GCLK_GENCTRL_IDC | // Set the duty cycle to 50/50 HIGH/LOW
GCLK_GENCTRL_GENEN | // Enable GCLK2
GCLK_GENCTRL_SRC_OSCULP32K | // Set the clock source to the ultra low power oscillator (OSCULP32K)
GCLK_GENCTRL_ID(2); // Select GCLK2
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
// Feed GCLK2 to WDT (Watchdog Timer)
REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN | // Enable GCLK2 to the WDT
GCLK_CLKCTRL_GEN_GCLK2 | // Select GCLK2
GCLK_CLKCTRL_ID_WDT; // Feed the GCLK2 to the WDT
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
REG_WDT_CONFIG = WDT_CONFIG_PER_11; // Set the WDT reset timeout to 16 seconds
while(WDT->STATUS.bit.SYNCBUSY); // Wait for synchronization
REG_WDT_CTRL = WDT_CTRL_ENABLE; // Enable the WDT in normal mode
while(WDT->STATUS.bit.SYNCBUSY); // Wait for synchronization
}
void watchdog_clear(void){
if (!WDT->STATUS.bit.SYNCBUSY) // Check if the WDT registers are synchronized
{
REG_WDT_CLEAR = WDT_CLEAR_CLEAR_KEY; // Clear the watchdog timer
}
}
Now in your setup() call the watchdog_setup();
once. At this time your watchdog is now active and running and will reset the SAMD21 if it times out within the interval you used.
You will need to continually call the function watchdog_clear();
to prevent the watchdog resetting the MCU.
Make sure you change the timeout in the setup function to suit your needs.
It also does NOT wait for the SYNC bit when you request a clear. This can take some time (maybe 5mS) so it won't clear the watchdog in that case.
Hopefully this will help someone as it did help me.
Hi gjt211,
I know this is an old post, but here is what I found (sorry to the original/source of this as I am not sure where I originally found it but thank you!).
You found it 3 days ago on the Arduino Zero forum: WDT Watchdog timer code - Arduino Zero - Arduino Forum.
The orginal source is here: Found and fixed a bug in sketch for Arduino Zero | Details | Hackaday.io.
By the way, there's no need to use the WDT_CONFIG_PER_X definitions, as the SAMD21 CMSIS register definitions have changed in version 1.2.0.
Just replace the line:
REG_WDT_CONFIG = WDT_CONFIG_PER_7; // Set the WDT reset timeout to 1 second
with:
REG_WDT_CONFIG = WDT_CONFIG_PER_1K; // Set the WDT reset timeout to 1 second