B4R Code Snippet [ESP32] WatchDog

Module name 'esp32wdt':
Private Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'Public variables can be accessed from all modules.
    Private timWDTfeeder As Timer
End Sub

Sub Start(timeout_millis As Int)
    Dim gap As Int = 50
    '---------hardware WDT-----------
    If timeout_millis < gap Then
        timeout_millis = timeout_millis + gap
    End If
    timWDTfeeder.Initialize("timWDTfeeder_Tick", (Min(500, (timeout_millis/2)))
    'timWDTfeeder.Enabled=True    'comment this line to test rebooting MCU !!!
    RunNative("setup", (timeout_millis/1000))
End Sub

Sub Stop
    RunNative("wdt_stop", Null)
    timWDTfeeder.Enabled = False
    Log("Watchdog is disalarmed")
End Sub

Private Sub timWDTfeeder_Tick
    RunNative("wdt_reset", Null)
    Log("Watchdog is fed up")
End Sub

#if c
#include <esp_task_wdt.h>

void setup(B4R::Object* o) {
  Serial.println("Configuring WDT...");  
  esp_reset_reason_t reason = esp_reset_reason();
    if ((reason == ESP_RST_INT_WDT)) Serial.println("Was restarted due to ESP_RST_INT_WDT");
    if ((reason == ESP_RST_TASK_WDT)) Serial.println("Was restarted due to ESP_RST_TASK_WDT");
    if ((reason == ESP_RST_WDT)) Serial.println("Was restarted due to ESP_RST_WDT"); 
  
  esp_task_wdt_init(o->toLong(), true); //enable panic so ESP32 restarts
  esp_task_wdt_add(NULL); //add current thread to WDT watch
}

void wdt_reset(B4R::Object* o) {
    //Serial.println("Resetting WDT...");
    esp_task_wdt_reset();
}

void wdt_stop(B4R::Object* o) {
    Serial.println("WDT is stopped");
    esp_task_wdt_delete(NULL);
    esp_task_wdt_deinit();
}
#End If

Result resetting loop:
mode:DIO, clock div:1
load:0x3fff0030,len:1344
load:0x40078000,len:13964
load:0x40080400,len:3600
entry 0x400805f0
AppStart
Configuring WDT...
E (6116) task_wdt: Task watchdog got triggered. The following tasks did not reset the watchdog in time:
E (6116) task_wdt:  - loopTask (CPU 1)
E (6116) task_wdt: Tasks currently running:
E (6116) task_wdt: CPU 0: IDLE
E (6116) task_wdt: CPU 1: loopTask
E (6116) task_wdt: Aborting.
abort() was called at PC 0x400d8d71 on core 0
Backtrace: 0x40083349:0x3ffbe9cc |<-CORRUPTED
ELF file SHA256: 6bc82a9473af7e00
Rebooting...
ets Jun  8 2016 00:22:57
rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0030,len:1344
load:0x40078000,len:13964
load:0x40080400,len:3600
entry 0x400805f0
AppStart
Configuring WDT...
 
Last edited:

peacemaker

Expert
Licensed User
Longtime User
Updated Inline-C in module 'esp32wdt.bas' for SDK 3.0.5:
Private Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'Public variables can be accessed from all modules.
    Private timWDTfeeder As Timer
End Sub

Sub Start(timeout_millis As UInt)
    Dim gap As Int = 50
    '---------hardware WDT-----------
    If timeout_millis < gap Then
        timeout_millis = timeout_millis + gap
    End If
    timWDTfeeder.Initialize("timWDTfeeder_Tick", (Min(500, (timeout_millis/2))))
    timWDTfeeder.Enabled=True    'comment this line to test rebooting MCU !!!
    RunNative("setup_wdt", (timeout_millis))
End Sub

Sub Stop
    RunNative("wdt_stop", Null)
    timWDTfeeder.Enabled = False
    Log("Watchdog is disalarmed")
End Sub

Private Sub timWDTfeeder_Tick
    RunNative("wdt_reset", Null)
    Log("Watchdog is fed up")
End Sub

#if c
#include <esp_task_wdt.h>
esp_err_t ESP32_ERROR;
void setup_wdt(B4R::Object* o) {
  Serial.println("Configuring WDT...");
  esp_reset_reason_t reason = esp_reset_reason();
    if ((reason == ESP_RST_INT_WDT)) Serial.println("Was restarted due to ESP_RST_INT_WDT");
    if ((reason == ESP_RST_TASK_WDT)) Serial.println("Was restarted due to ESP_RST_TASK_WDT");
    if ((reason == ESP_RST_WDT)) Serial.println("Was restarted due to ESP_RST_WDT");
 
    esp_task_wdt_deinit();
  // setup of watchdog
  esp_task_wdt_config_t wdt_config = {
    .timeout_ms = o->toLong(),  // millisecs
    .idle_core_mask = (1 << portNUM_PROCESSORS) - 1,  // bit mask of cores
    .trigger_panic = true  // panic to reboot ESP32
  };
  ESP32_ERROR = esp_task_wdt_init(&wdt_config);
  Serial.println("Last Reset : " + String(esp_err_to_name(ESP32_ERROR)));
  esp_task_wdt_add(NULL); //add current thread to WDT watch
}

void wdt_reset(B4R::Object* o) {
    //Serial.println("Resetting WDT...");
    esp_task_wdt_reset();
    delay(3);
}

void wdt_stop(B4R::Object* o) {
    Serial.println("WDT is stopped");
    esp_task_wdt_delete(NULL);
    esp_task_wdt_deinit();
}
#End If
 
Last edited:

peacemaker

Expert
Licensed User
Longtime User
New version,universal for ESP32-family and old esp8266:

module name: espwdt:
Private Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'Public variables can be accessed from all modules.
    Private timWDTfeeder As Timer
    Private IsESP32 As Boolean    'ignore
End Sub

Sub Start(timeout_millis As ULong)
    Dim gap As Int = 50
    '---------hardware WDT-----------
    If timeout_millis < gap Then
        timeout_millis = timeout_millis + gap
    End If
    
    ' Determine the microcontroller type
    GetDeviceType
    
    If IsESP32 Then
        ' For ESP32, use half the timeout, but no more than 5000 ms
        timWDTfeeder.Initialize("timWDTfeeder_Tick", (Min(5000, (timeout_millis/2))))
    Else
        ' For ESP8266, use a fixed interval of 3000 ms
        timWDTfeeder.Initialize("timWDTfeeder_Tick", 3000)
    End If
    
    timWDTfeeder.Enabled = True    'comment this line to test rebooting MCU !!!
    RunNative("setup_wdt", (timeout_millis))
End Sub

Sub Stop
    RunNative("wdt_stop", Null)
    timWDTfeeder.Enabled = False
    Log("Watchdog is disalarmed")
End Sub

Private Sub timWDTfeeder_Tick
    RunNative("reset_wdt", Null)
    'Log("Watchdog is fed up")
End Sub

' Function to determine the device type
Private Sub GetDeviceType
    RunNative("get_device_type", Null)
End Sub

#if c
#ifdef ESP32
#include <esp_task_wdt.h>
esp_err_t ESP32_ERROR;
#endif

// Common functions for all platforms
void get_device_type(B4R::Object* o) {
#ifdef ESP32
    b4r_espwdt::_isesp32 = (byte)1;
#elif defined(ESP8266)
    b4r_espwdt::_isesp32 = (byte)0;
#endif
}

void setup_wdt(B4R::Object* o) {
#ifdef ESP32
    // Code for ESP32 - original functionality preserved
    Serial.println("Configuring WDT for ESP32..."); 
    
    // Get the reason for the last reset (commented out as in the original)
    //esp_reset_reason_t reason = esp_reset_reason();
    //If ((reason == ESP_RST_INT_WDT)) Serial.println("Was restarted due to ESP_RST_INT_WDT");
    //If ((reason == ESP_RST_TASK_WDT)) Serial.println("Was restarted due to ESP_RST_TASK_WDT");
    //If ((reason == ESP_RST_WDT)) Serial.println("Was restarted due to ESP_RST_WDT");
    
    esp_task_wdt_deinit();
    
    // Watchdog setup - original configuration preserved
    esp_task_wdt_config_t wdt_config = {
        .timeout_ms = o->toLong(),  // millisec
        .idle_core_mask = (1 << portNUM_PROCESSORS) - 1,  // Bit mask of cores
        .trigger_panic = true  // panic to reboot ESP32
    };
    
    ESP32_ERROR = esp_task_wdt_init(&wdt_config);
    Serial.println("Last Reset : " + String(esp_err_to_name(ESP32_ERROR)));
    esp_task_wdt_add(NULL); // add current thread to WDT watch
    Serial.println("WDT is configured for ESP32");
    
#elif defined(ESP8266)
    // Code for ESP8266 using ESP.wdt functions
    Serial.println("Configuring WDT for ESP8266...");
    ESP.wdtDisable(); // Disable WDT
    // On ESP8266, use hardware WDT with a fixed timeout (3000ms)
    ESP.wdtEnable(3000); // Enable WDT with a 3-second timeout
    Serial.println("WDT is configured for ESP8266 (3s timeout)");
    
#endif
}

void reset_wdt(B4R::Object* o) {
#ifdef ESP32
    // Code for ESP32 - original functionality preserved
    //Serial.println("Resetting WDT...");
    esp_task_wdt_reset();
    delay(3);
#elif defined(ESP8266)
    // Code for ESP8266 using ESP.wdtFeed
    ESP.wdtFeed(); // Reset WDT
    delay(3);
#endif
}

void wdt_stop(B4R::Object* o) {
#ifdef ESP32
    // Code for ESP32 - original functionality preserved
    Serial.println("WDT is stopped for ESP32");
    esp_task_wdt_delete(NULL);
    esp_task_wdt_deinit();
#elif defined(ESP8266)
    // Code for ESP8266 using ESP.wdtDisable
    Serial.println("WDT is stopped for ESP8266");
    ESP.wdtDisable(); // Disable WDT
#endif
}
#End If
 
Top