Banner image credit @pasanjayaweera on Unsplash.
At the risk of not only dating myself, but also exposing to you all that I spent years developing web apps in the Microsoft ecosystem, I present to you the most useful yet awful line of code ever written:
on error resume next
When added to a script written in VBScript for Microsoft's Active Server Pages, this line of code would simply tell the interpreter: "Hey whenever you encounter an error, just skip it and go on to the next thing, ok?"
Surely this could never result in any problems, like memory leaks or runaway processes, right?
While this developer's heart was in the right place, in hindsight it wasn't the best way to maintain 99.999% uptime!
Now, when working with embedded systems, ensuring the reliability of your device
is paramount. While not stooping to the level of on error resume next
,
watchdog timers play a key role in maintaining system stability by resetting
the host if it becomes unresponsive.
In this article, we'll take a look at implementing watchdog functionality on the STM32L4-based Blues Swan.
What Exactly is a Watchdog Timer?
A watchdog timer is a hardware timer that, once started, must be periodically reset by the firmware running on the host microcontroller. If the firmware fails to call the method that resets the timer within a specified interval, the watchdog triggers a system reset. I know neither of us write buggy code, but this mechanism helps us to seamlessly recover from anomalies, infinite loops, and other failures that could render our host microcontroller unresponsive.
While it may feel like cheating, using a watchdog ensures that if your program hangs due to some unexpected behavior, it'll at least reset itself to (fingers crossed) a usable state.
Watchdog Timer Implementation on the STM32L4
The STM32 series of microcontrollers offers two types of watchdogs: the Independent Watchdog (IWDG) and the Window Watchdog (WWDG). For the majority of cases, the IWDG is the preferred choice due to its simplicity and independence from the main system clock.
Unfortunately there isn't really a "one size fits all" implementation of watchdogs across the entire STM32 family (the same is true for ESP32 and Nordic nRF MCUs). Luckily for us, there is a simple open source watchdog library available specifically for the STM32L4, the STM32L4xx Watchdog Library.
Let's take a look at how to quickly add this to our project.
Download the Library
Whether you are using the Arduino IDE or (my fave) PlatformIO, simply search for "STM32L4xx Watchdog Library" and add it to your project.
In your firmware, include a reference to the relevant watchdog header file:
#include "WatchDog.hpp"
Next, create a watchdog
variable:
WatchDog watchdog;
Then, in your setup()
method, initialize the watchdog by passing in a number
of seconds. This value corresponds to the interval you want your microcontroller
to wait, unresponsive, until you let the watchdog initiate a system reset:
watchdog.init(90); // i.e. wait for 90 seconds of inactivity
Watchdog timers run independently of any delay
functions you may use, so be
sure you don't use any delays longer than the length of your watchdog timer!
Finally, add the following line of code to your loop()
method. This "pets" the
watchdog to let it know that all is good and it can reset its timer:
watchdog.pet();
You don't just have to use this in your loop()
. You can add this line of code
anywhere you want to ensure the watchdog is resetting.
That's it! With that bit of code, your STM32L4 will automatically reset itself after the specified period of inactivity.
Best Practices for Using Watchdog Timers
Now that you know the "how", let's look briefly at some best practices for using watchdog timers.
First off, make sure you're setting an appropriate timeout value. Choose a
value long enough to accommodate the longest task in your loop()
method, but
short enough to detect problems quickly.
You'll also want to test, test, and test again! It can't hurt to simulate different system hangs or extra-long delays to verify that the watchdog resets the system as expected. Also, for critical systems, think through how the watchdog is going to behave during deep sleep or extended low-power modes.
Using this watchdog library in particular, you may find it useful use the
watchdog.isEnabled();
method that simply returns a bool
to tell you whether
the watchdog timer is enabled or not.
Finally, the following block of code added to your setup()
method allows you
to identify whether or not the previous system reset was initiated by a
watchdog timer:
if(__HAL_RCC_GET_FLAG(RCC_FLAG_IWDGRST)) {
//watchdog caused reset
}
else {
//watchdog did not cause reset
}
__HAL_RCC_CLEAR_RESET_FLAGS(); // clears reset flags
Wrapping Up
Implementing a watchdog timer is one way to help ensure the reliability of embedded systems. While each platform - ESP32, STM32, and Nordic nRF - has its own set of APIs and configurations, we wanted to provide a quick and easy path to using the popular Blues Swan STM32L4-based host. Hopefully the example code provided here helps you get started with watchdog timers on the Swan, allowing your system to recover as gracefully as possible.
Happy coding, and may your systems run smoothly! π