Beware of the watchdog!
Introduction
A watchdog timer (WDT) is a timer that is able to reset a system when it elapses, recovering a hung system: resetting a system is not exactly what would you call recovering but sometimes it’s the only option. The timer must be refreshed (or fed) periodically by software to avoid the reset: if the software is not able to do it, probably the software itself is hanging so resetting the system will unblock the situation.
Most embedded processors and microcontrollers have an integrated WDT while some Super I/O chips implement watchdog for processors that do not integrate one.
Watchdog support in Windows Embedded CE
Windows CE kernel supports by default software watchdog timers: a thread can create a WDT using the
CreateWatchDogTimer function. The function has several parameters but the most significant are:
- The timeout value
- The action the kernel will take when the timeout expires (kill the process which owns the WDT, reset the system or no action at all)
Note that the kernel will use IOCTL_HAL_REBOOT to reset the system so the OAL must implement it for the watchdog to actually trigger a reset.
CreateWatchDogTimer returns a handle that you can pass to other functions:
You can take a look at the kernel watchdog code if you installed the shared source code (%_WINCEROOT%\PRIVATE\WINCEOS\COREOS\NK\KERNEL\watchdog.c)
If the device has a hardware WDT the OEM can support it through the following OAL global variables:
- pfnRefreshWatchDog: this is a pointer to a function which is called by the kernel to refresh the hardware watchdog. The default value for pfnRefreshWatchDog is NULL, which indicates that there is a watchdog timer does not exist.
- dwWatchDogPeriod: this variable specifies the watchdog period, in milliseconds, where the hardware watchdog must be refreshed before system reset. The default value for dwWatchDogPeriod is 0, which indicates that there is a watchdog timer does not exist.
- dwWatchDogThreadPriority: this variable specifies the kernel watchdog thread priority. The default value of dwWatchDogThreadPriority is DEFAULT_WATCHDOG_PRIORITY, which is equal to 100.
The kernel watchdog thread will call pfnRefreshWatchDog every dwWatchDogPeriod milliseconds refershing the timer thus avoiding the system reset. If you have a hardware watchdog you can recover the system in two critical situations: a critical thread hangs (the software WDT will trigger); the kernel hangs (the hardware WDT will trigger).
Take in account that having the hardware WDT enabled and breaking into the debugger will probably hurt you…
Attached to this post you can find a sample application that create a WDT, refresh it for some time than stops doing it resetting the system. Thanks to my collegue Lorenzo Bertolissi that coded it