Use a system timer as a watchdog

Important

This is the Azure Sphere (Legacy) documentation. Azure Sphere (Legacy) is retiring on 27 September 2027, and users must migrate to Azure Sphere (Integrated) by this time. Use the Version selector located above the TOC to view the Azure Sphere (Integrated) documentation.

A high-level application can use a system timer as a watchdog to cause the OS to terminate and restart that application if it becomes unresponsive. When the watchdog expires, it raises a signal that the application doesn't handle, which in turn causes the OS to terminate the application. After termination, the OS automatically restarts the application.

To use a watchdog timer:

  • Define the timer
  • Create and arm the timer
  • Reset the timer regularly before it expires

To define the timer, create an itimerspec structure and set the interval and initial expiration to a fixed value, such as one second.

#include <time.h>

const struct itimerspec watchdogInterval = { { 1, 0 },{ 1, 0 } };
timer_t watchdogTimer;

Set a notification event, signal, and signal value for the watchdog, call timer_create to create it, and call timer_settime to arm it. In this example, watchdogTimer raises the SIGALRM event. The application doesn't handle the event, so the OS terminates the application.

void SetupWatchdog(void)
{
    struct sigevent alarmEvent;
    alarmEvent.sigev_notify = SIGEV_SIGNAL;
    alarmEvent.sigev_signo = SIGALRM;
    alarmEvent.sigev_value.sival_ptr = &watchdogTimer;

    int result = timer_create(CLOCK_MONOTONIC, &alarmEvent, &watchdogTimer);
    result = timer_settime(watchdogTimer, 0, &watchdogInterval, NULL);
}

Elsewhere in the application code, reset the watchdog periodically. One technique is to use a second timer, which has a period shorter than the watchdogInterval, to verify that the application is operating as expected and, if so, reset the watchdog timer.

// Must be called periodically
void ExtendWatchdogExpiry(void)
{
    //check that application is operating normally
    //if so, reset the watchdog
    timer_settime(watchdogTimer, 0, &watchdogInterval, NULL);
}