Watchdog - reset esp32 if stuck more than 120 seconds

ESP32 Core 3.0.0: Help with Watchdog Timer

I need help making my ESP32 restart if the loop function doesn't call the reset watchdog for 2 minutes.

I found the following code in a tutorial, but it's not working. I'm getting the following error:

C:\Users\q\Documents\Arduino\test\test.ino: In function 'void setup()':
C:\Users\q\Documents\Arduino\test\test.ino:98:21: error: invalid conversion from 'int' to 'const esp_task_wdt_config_t*' [-fpermissive]
98 | esp_task_wdt_init(120, true);
| ^~~
| |
| int
C:\Users\q\Documents\Arduino\test\test.ino:98:20: error: too many arguments to function 'esp_err_t esp_task_wdt_init(const esp_task_wdt_config_t*)'
98 | esp_task_wdt_init(120, true);
| ~^
In file included from C:\Users\q\Documents\Arduino\test\test.ino:20:
C:\Users\q\AppData\Local\Arduino15\packages\esp32\tools\esp32-arduino-libs\idf-release_v5.1-442a798083/esp32/include/esp_system/include/esp_task_wdt.h:47:11: note: declared here
47 | esp_err_t esp_task_wdt_init(const esp_task_wdt_config_t *config);
| ^
~~~~~~~~~~

exit status 1

Compilation error: invalid conversion from 'int' to 'const esp_task_wdt_config_t*' [-fpermissive]

#include <esp_task_wdt.h>

void setup() {

  esp_task_wdt_init(120, true);


  xTaskCreate(
    task1,       // Task function pointer (the function that defines the task's behavior)
    "Task1",     // A descriptive name for the task
    2000,        // Stack depth in words (e.g., 1000 words for the task's stack)
    NULL,        // Task parameter (can be used to pass data to the task; set to NULL in this example)
    2,           // Task priority higher numbers represent higher priority.
    &taskHandle  // Task handle (used to reference the task)
  );



void loop() {
  esp_task_wdt_reset();  // Reset the watchdog timer to prevent it from triggering
}

void task1(void *parameter) {
  for (;;) { //code here}
}

The watchdog timer defaults to 5 seconds. It applies to all tasks. The documented range for this config value is up to 60 seconds, but 120 appears to work, at least for now.

There's no need to call esp_task_wdt_reset from loop. That is already done in the wrapper in main.cpp that calls setup and loop

as long as you call enableLoopWDT from setup, which both calls esp_task_wdt_add for you and sets that loopTaskWDTEnabled variable to true.

void setup() {
  enableLoopWDT();
}

void loop() {
  for (;;) {}  // don't return
}

This resets every 5 seconds because loop does not return.

entry 0x400805f0
[ 5 seconds later ]
E (10139) task_wdt: Task watchdog got triggered. The following tasks did not reset the watchdog in time:
E (10139) task_wdt:  - loopTask (CPU 1)
E (10139) task_wdt: Tasks currently running:
E (10139) task_wdt: CPU 0: IDLE
E (10139) task_wdt: CPU 1: loopTask
E (10139) task_wdt: Aborting.

Remove the infinite loop and it's fine.

Conversely, you need to call both _add and _reset for your custom tasks, like your task1.

void task1(void *parameter) {
  esp_task_wdt_add(nullptr);
  for (;;) {
    esp_task_wdt_reset();
    // code here
  }
}

If you don't _add, the task is not added to the watch list. And if it is watched, you need to _reset periodically.

You should also consider the priority of your new task. If it is lower than the main loop task, and the loop never yields/delays, then the new task will never start. If the priority is equal, ESP32 will time-slice between them. So when creating the task, you might do

#include <esp_task_wdt.h>

void setup() {
  auto priority = uxTaskPriorityGet(nullptr);
  xTaskCreateUniversal(
    [](void *pvParameters) {
      esp_task_wdt_add(nullptr);
      for (;;) {
        esp_task_wdt_reset();
        // call other function that does actual work here
      }
    },
    "Actual_Work",
    CONFIG_ARDUINO_LOOP_STACK_SIZE, nullptr,
    priority, nullptr, ARDUINO_RUNNING_CORE);
}

void loop () {
}

As for your reported error, arduino-esp32 v3.0.0 is based on ESP-IDF v5.1.4. The latest v2.x is based on ESP-IDF v4.4.7. One of the breaking changes for v5 is the signature for esp_task_wdt_init, which in v4 used to take a uint32_t (which is a lot of seconds) and a bool

/**
  * @brief  Initialize the Task Watchdog Timer (TWDT)
  *
  * This function configures and initializes the TWDT. If the TWDT is already
  * initialized when this function is called, this function will update the
  * TWDT's timeout period and panic configurations instead.
  */
esp_err_t esp_task_wdt_init(uint32_t timeout, bool panic);

but is now -- as the error message said -- a single struct. Furthermore, there is a separate function to reconfigure, with the same argument

esp_err_t esp_task_wdt_reconfigure(const esp_task_wdt_config_t *config);

So you might try (I don't have 3.0.0 installed)

esp_task_wdt_config_t config = {
  .timeout_ms = 120 * 1000,
  .trigger_panic = true,
}
esp_task_wdt_reconfigure(&config);
1 Like

so i just want to be sure that the void loop(){} is not stuck there and sometimes it can take longer since there are some delays there, so 60 seconds or 120 seconds reset is ok .
task1 never stuck and sometimes i suspend it coz i dont use it all the time, thats why i want just void loop to reset the WDT

is this what i should do:


// Define the task handle
TaskHandle_t taskHandle;

void setup() {
  // Reconfigure the watchdog timer with the specified configuration
  esp_task_wdt_config_t config = {
    .timeout_ms = 60* 1000,  //  60 seconds
    .trigger_panic = true,     // Trigger panic if watchdog timer is not reset
  };
  esp_task_wdt_reconfigure(&config);

  // Create task1
  xTaskCreate(
    task1,       // Task function pointer
    "Task1",     // Task name
    2000,        // Stack depth in words
    NULL,        // Task parameter
    2,           // Task priority
    &taskHandle  // Task handle
  );
}

void loop() {
  esp_task_wdt_reset();  // Reset the watchdog timer to prevent it from triggering

  // Your main loop code
  delay(100);  // Example delay to simulate work
}

// Custom task function
void task1(void *parameter) {
  for (;;) {
    digitalWrite(led, HIGH);
    delay(100);
    digitalWrite(led, LOW);
    vTaskDelay(pdMS_TO_TICKS(500));  // Delay the task
  }
}

i tried this code but dont work, i added a delay(120000); to loop but restart was not trigered

You called _reset from loop when you don't need to, and the main loopTask was never added to the watch list.

As I said, I don't have v3.0.0 installed, but for v2

void setup() {
  enableLoopWDT();
}

void loop() {
  delay(6000);
}

that reboots every 5 seconds, while this does not

void setup() {
  enableLoopWDT();
}

void loop() {
  delay(3000);
}

The _reconfigure looks OK; do that first in setup like you have it.

1 Like

so this will work normally

void loop() {
 
  // Your main loop code
  delay(50000);  // Example delay to simulate work
}

and this will trigger a reboot


void loop() {
 
  // Your main loop code
  delay(70000);  // Example delay to simulate work
}

It’s been my experience that with the default configuration, the watchdog on ESP32 Core 1 doesn’t fire unless you go out of your way to make it happen. You can hang a high-priority task, freezing out all others, for as long as you want and yet the watchdog won’t fire ……. as long as the Core 1 interrupts remain enabled. If interrupts are disabled during this period the watchdog will fire but it takes awhile.

Core 0 is a different story. There if you hang a task that prevents the other Core 0 tasks from running, then the watchdog will fire in a few seconds …. even if Core 0 interrupts remain enabled.

Thus, things that I’d look for:

  • OP is using a single-core variant of the ESP32.

  • OP’s code or one of the libraries it uses has changed the default behavior of the Core 1 watchdog.

  • OP’s code or one of the libraries it uses hangs a task on Core 1 with interrupts disabled.

Unless something has changed recently, by default, the task watchdog for core 1 is not enabled.
Changing the timer numbers isn't going to do anything until you actually enable it.

This is setup inside the sdkconfig file specific to each ESP32 variant.

CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=y
# CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1 is not set

You need to pin a task to a specific core to get the behavior you desire.

Hello colleagues! I have solved it, I had to go back to a previous version of the boards manager ESP32 By Espressif Systems... specifically to 2.0.17 and that's it, solved, that error no longer appeared. Greeting!

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.