The attached sketch shows the Zero's watchdog timer and sample code to implement it. The code included enables the WDT with a period of about 500 milli-seconds and if not reset during that time, the WDT times out and causes a system reset. This reset returns the processor to the same state as the RESET pushbutton or initial power-on state.

A function systemReset() is included so the programmer can code a system reset at any desired point in time, as long as the WDT is running.

User code may use the included functions:

setupWDT( uint8_t period); // to set up the WDT with any valid period selection

resetWDT(); // must be called by the sketch regularly before the WDT timer times out to prevent the watchdog from resetting the system.

I did not implement the window timer function or the early warning interrupt as my application does not need them. It should not be difficult to add these.

It looks like you already had a WDTsync() function declared. Glad you got it to work. I am looking now at changing the generic clock for the WDT. By default and with the maximum number of clock cycles selected for period, the WDT resets at 500 milli-seconds. My project uses a Vizic SmartGPU2 display screen and some of its functions, such as screenShot take longer than 500 mS. So I would have to re-write their library to include a call to resetWDT() while waiting for the return code from the display. Possible, but messy if they ever update their library.

If I can figure out how to access GCLK->CLKCTRL.ID to select the WDT, then set the clock divider to something like 10, I will then WDT reset in 5 seconds.

It is just some little detail I am missing. I need to write to the bit group ID in CLKCTRL, something like:

I wrote a library to dump out the samd21 registers. Not all are implemented yet, but you should be able to use it to show the generic clocks.https://github.com/drewfish/arduino-ZeroRegs

I've been using it to see how the Arduino samd core changes things, so that I then know what to tweak. (For example, the RTCZero library sets up GEN 2 to XOSC32K with 32 scalar, and I use that to clock EIC as well.GCLK->CLKCTRL.reg = uint16_t( GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK2 | GCLK_CLKCTRL_ID( GCLK_CLKCTRL_ID_EIC_Val ));

Thanks, drewfish. I have your library installed and now looking how to use it in a sketch. Do you have a sample to show how to call your functions for GCLK and WDT? I need to see the Zero default GCLK assignments for WDT.

Great! Your library is going to be a wealth of information as I now have "x-ray vision" into the SAMD chip. The WDT assignments do not show until enabled so I added my WDT init code to see what the default is (GCLK_WDT connects to GEN02, and GEN02 is assigned to OSCULP32K). The watchdog barked before the registers could print, so I bumped up the serial baud rate.

Now to set the WDT clock with a divider. Without clock divider the maximum WDT period is 0.5 seconds and I would like a longer period.

For others following this thread, I do not have SerialUSB in use, instead I use Serial. Changing your sample code by find/replace SerialUSB to Serial worked perfectly.

For anyone who found this discussion but still looking for a way to setup the clocks for the WDT... Here is a revised setupWDT for sketch rickrlh provided in the first post to setup the WDT to use 1ms periods allowing up to 16sec WDT periods for the Arduino Zero. I use GENCLK5 as it is not being used in my case...

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 timerwhile(WDT->STATUS.bit.SYNCBUSY); // Wait for synchronizationThe 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.

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.

// Set up the WDT to perform a system reset if the loop() blocks for more than 1 secondvoid setup() { // 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

On the SAMD51 things are a bit easier regarding the micro-controller's Watchdog Timer (WDT).

At power on, the WDT is by default wired up to the micro-controller's internal ultra low power oscillator (OSCULP32K) 1.024kHz output. This means that unlike the SAMD21, no generic clock set-up is required.

Here's the code that'll force a system reset if the loop() blocks for more than 1 second on the SAMD51:

// Set up the WDT to perform a system reset if the loop() blocks for more than 1 secondvoid setup() { REG_WDT_CONFIG = WDT_CONFIG_PER_CYC1024; // Set the WDT reset timeout to 1 second REG_WDT_CTRLA = WDT_CTRLA_ENABLE; // Enable the WDT in normal mode while(WDT->SYNCBUSY.bit.ENABLE); // Wait for synchronization}

My apologies, the reason why the code doesn't compile is that the Arduino Zero's CMSIS register definitions have been updated to version 1.2.0. I wrote the code for a custom SAMD21 board using an older CMSIS version.