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.