The ESP32 operating system supports a task-based watchdog timer (TWDT) that checks to ensure tasks (or any select section of code) that subscribes to the task watchdog is being periodically run. If not, then after a pre-specified period of time, the device automatically reboots.
Typically, it is only the background IDLE processes that subscribe to the TWDT, but by default the Arduino-ESP32 library does NOT enable the IDLE task watchdog for single-core chips (ESP32-S2, C3, and C6) and only enables the IDLE task watchdog associated with Core-0 for dual-core chips (ESP32 and ESP32-S3). The Arduino-ESP32 library default is to set the TWDT timeout to 5 seconds.
Based on these defaults, if the your sketch hangs, or otherwise goes into an infinite loop, the device will be frozen indefinitely until you manually reset it or cycle the power.
Fortunately, you can add an optional watchdog to the TWDT that specifically checks to ensure all needed HomeSpan tasks and functions are running as expected. To do so, simply call the homeSpan method enableWatchdog(uint16_t nSeconds) near the top of the setup() portion of your sketch. Once enabled, the TWDT will time-out and automatically reboot the device after nSeconds unless the HomeSpan watchdog has been reset. HomeSpan resets its watchdog automatically upon reaching the very end of the HomeSpan poll() function. As long as the end of the poll() function is reached every nSeconds seconds, the TWDT will be silent. But if the poll() function hangs, or another process blocks the poll() function from even being called, the TWDT will trigger after nSeconds seconds and the device will reboot.
By setting nSeconds to a time that is sufficiently long to allow all of your setup process to run (perhaps 10-20 seconds), you can be assured that if any of the HomeSpan process are caught in an infinite loop, the device will reboot on its own. This is particularly helpful when used in conjunction with OTA Rollbacks since you can configure things such that if you upload a new sketch via OTA and it hangs on start-up, it will reboot after a short period of time and rollback to the prior working version of the sketch. See the HomeSpan OTA page for details on how to enable rollbacks.
If for whatever reason you need to perform a function within the HomeSpan framework that will prevent the poll() task from running for an extended period of time (i.e. longer than nSeconds) you can call homeSpan.disableWatchdog() to temporarily disable the HomeSpan watchdog and prevent a reboot. Then simply call homeSpan.enableWatchdog(nSeconds) once again when your function is complete to re-enable the HomeSpan watchdog. See the HomeSpan API Reference for details on the enableWatchdog() and disableWatchdog() methods.
-
Internally, HomeSpan calls the homeSpan
resetWatchdog()method to reset its watchdog at the end of thepoll()function. HomeSpan also embeds calls toresetWatchdog()at the end of any other HomeSpan function that, by design, temporarily blocks thepoll()function, such as when HomeSpan is waiting for you to type your WiFi Credentials into the Serial Monitor, when you've used the Control Button to place HomeSpan into Command Mode, or when you've started the HomeSpan Setup Access Point. These extra embedded calls toresetWatchdog()ensure the TWDT will not trigger while these other functions are running, but the TWDT will indeed trigger and reboot the device if those functions themselves hang. -
The
resetWatchdog()method serves two purposes: it resets the HomeSpan watchdog (if it is enabled) and it callsvTaskDelay(1)(regardless of whether or not the HomeSpan watchdog is enabled). The call tovTaskDelayallows HomeSpan to yield for 1 ms so that other separate tasks with the same or lower priority (such as the IDLE tasks) get an opportunity to run. -
The homeSpan
resetWatchdog()method is public and you can call it yourself from within your sketch if needed. For example, if your sketch runs the HomeSpanpoll()function by callinghomeSpan.poll()from within the main Arduinoloop()and you add code into theloop()that takes more than nSeconds seconds to run, you should either callhomeSpan.disableWatchdog()before that code is run, or repeatedly callresetWatchdog()from within your long-running code at a point that is only reached if your code is running correctly, but will not be called if your code hangs. This effectively allows the TWDT to monitor your long-running code and trigger a reboot if it hangs. -
If instead of calling
homeSpan.poll()from within the Arduinoloop()your sketch callshomeSpan.autoPoll()at the end of the Arduinosetup()function to launch HomeSpan polling in a separately-running task, then the HomeSpan polling task will be unaffected by delays in any code you may add to the Arduinoloop(). -
However, even if you use
homeSpan.autoPoll()to run HomeSpan polling in its own task, you still need to make sure you don't add any long-running code to the Arduinosetup()function that delays the initial launch of polling by more than nSeconds seconds from the point you callhomeSpan.enableWatchdog(nSeconds). If you do add any initializaiton code to the Arduinosetup()function that takes a long time to run, you can either wait to callenableWatchdog(nSeconds)until after that code completes, or even better you can still callenableWatchdog(nSeconds)at the top of the Arduinosetup()function and then periodicially callresetWatchdog()from within your long-running code. This ensures the HomeSpan watchdog will trigger a reboot after nSeconds seconds if your code hangs. -
Note that to avoid triggerring the HomeSpan watchdog, the HomeSpan
poll()function needs to reach its end every nSeconds seconds. This means you need to make sure thepoll()function does not get delayed running any code you use to implement HomeSpan Service structures (e.g., the SpanService constructor, theupdate(),button(), andloop()methods, etc.) or any code you use to implement HomeSpan callbacks. Similar to above, if you do need to add code to a Service structure or callback that takes a long time to run, make sure to periodically callhomeSpan.resetWatchdog()within that code so it is properly protected by the HomeSpan watchdog. -
Enabling the HomeSpan watchdog only protects your sketch from hanging indefinitely by triggering a reboot after nSeconds seconds if the watchdog is not reset. But the HomeSpan watchdog does nothing to create any sort of "heartbeat" to keep alive connections to HomeKit or your Home App if your sketch contains long delays that do not trigger the watchdog. This means that even with HomeSpan watchdog protection enabled, delays that prevent the HomeSpan
poll()function from running in a timely fashion will cause HomeKit to display the dreaded "No Response" message in your Home App. -
The HomeSpan watchdog is implemented as part of the ESP32's task watchdog timer, which is completely separate from the ESP32's interrupt watchdog timer (IWDT) used by various operating system functions.
↩️ Back to the Welcome page