From 213e3e998a54c8ed1a8975c94e0401810c05656e Mon Sep 17 00:00:00 2001 From: Daniel Poelzleithner Date: Thu, 5 May 2022 11:24:41 +0000 Subject: [PATCH 1/2] Enable ESP watchdog by default Use the ESP watchdog to detect hanging ESP and reset the firmware. Can be disable by defining WLED_WATCHDOG_TIMOUT 0 Default timeout is 3 seconds on ESP32 and 8 seconds on ESP2688 --- wled00/wled.cpp | 25 +++++++++++++++++++++++++ wled00/wled.h | 7 +++++++ 2 files changed, 32 insertions(+) diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 54c723c80..a4204732c 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -276,6 +276,15 @@ void WLED::loop() loops++; #endif // WLED_DEBUG toki.resetTick(); + +#if WLED_WATCHDOG_TIMEOUT > 0 + // we finished our mainloop, reset the watchdog timer + #ifdef ARDUINO_ARCH_ESP32 + esp_task_wdt_reset(); + #else + ESP.wdtFeed(); + #endif +#endif } void WLED::setup() @@ -302,6 +311,22 @@ void WLED::setup() DEBUG_PRINT(F("heap ")); DEBUG_PRINTLN(ESP.getFreeHeap()); +#if WLED_WATCHDOG_TIMEOUT > 0 +#ifdef ARDUINO_ARCH_ESP32 + esp_err_t watchdog = esp_task_wdt_init(WLED_WATCHDOG_TIMEOUT, true); + DEBUG_PRINT(F("Enable watchdog ")); + if (watchdog == ESP_OK) { + DEBUG_PRINTLN(F(" OK")); + } else { + DEBUG_PRINTLN(watchdog); + } + esp_task_wdt_add(NULL); +#else + // any timeout possible ? + ESP.wdtEnable(WLED_WATCHDOG_TIMEOUT * 1000); +#endif +#endif + #if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM) if (psramFound()) { // GPIO16/GPIO17 reserved for SPI RAM diff --git a/wled00/wled.h b/wled00/wled.h index 6dabdd0b5..2267f2764 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -49,6 +49,12 @@ // filesystem specific debugging //#define WLED_DEBUG_FS +#ifndef WLED_WATCHDOG_TIMEOUT + // 3 seconds should be enough to detect a lockup + // define WLED_WATCHDOG_TIMEOUT=0 to disable watchdog + #define WLED_WATCHDOG_TIMEOUT 3 +#endif + //optionally disable brownout detector on ESP32. //This is generally a terrible idea, but improves boot success on boards with a 3.3v regulator + cap setup that can't provide 400mA peaks //#define WLED_DISABLE_BROWNOUT_DET @@ -78,6 +84,7 @@ #else #include #endif + #include "esp_task_wdt.h" #endif #include "src/dependencies/network/Network.h" From 26fa38d052fe7434848d9f4a919feae039c618b8 Mon Sep 17 00:00:00 2001 From: Daniel Poelzleithner Date: Mon, 23 May 2022 22:30:13 +0000 Subject: [PATCH 2/2] Watchdog: disable watchdog while OTA is running --- wled00/wled.cpp | 50 +++++++++++++++++++++++++++++------------- wled00/wled.h | 2 ++ wled00/wled_server.cpp | 2 ++ 3 files changed, 39 insertions(+), 15 deletions(-) diff --git a/wled00/wled.cpp b/wled00/wled.cpp index a4204732c..d15cd3544 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -287,6 +287,35 @@ void WLED::loop() #endif } +void WLED::enableWatchdog() { +#if WLED_WATCHDOG_TIMEOUT > 0 +#ifdef ARDUINO_ARCH_ESP32 + esp_err_t watchdog = esp_task_wdt_init(WLED_WATCHDOG_TIMEOUT, true); + DEBUG_PRINT(F("Watchdog enabled: ")); + if (watchdog == ESP_OK) { + DEBUG_PRINTLN(F("OK")); + } else { + DEBUG_PRINTLN(watchdog); + return; + } + esp_task_wdt_add(NULL); +#else + ESP.wdtEnable(WLED_WATCHDOG_TIMEOUT * 1000); +#endif +#endif +} + +void WLED::disableWatchdog() { +#if WLED_WATCHDOG_TIMEOUT > 0 +DEBUG_PRINTLN(F("Watchdog: disabled")); +#ifdef ARDUINO_ARCH_ESP32 + esp_task_wdt_delete(NULL); +#else + ESP.wdtDisable(); +#endif +#endif +} + void WLED::setup() { #if defined(ARDUINO_ARCH_ESP32) && defined(WLED_DISABLE_BROWNOUT_DET) @@ -311,21 +340,7 @@ void WLED::setup() DEBUG_PRINT(F("heap ")); DEBUG_PRINTLN(ESP.getFreeHeap()); -#if WLED_WATCHDOG_TIMEOUT > 0 -#ifdef ARDUINO_ARCH_ESP32 - esp_err_t watchdog = esp_task_wdt_init(WLED_WATCHDOG_TIMEOUT, true); - DEBUG_PRINT(F("Enable watchdog ")); - if (watchdog == ESP_OK) { - DEBUG_PRINTLN(F(" OK")); - } else { - DEBUG_PRINTLN(watchdog); - } - esp_task_wdt_add(NULL); -#else - // any timeout possible ? - ESP.wdtEnable(WLED_WATCHDOG_TIMEOUT * 1000); -#endif -#endif + enableWatchdog(); #if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM) if (psramFound()) { @@ -426,8 +441,13 @@ void WLED::setup() #ifdef ESP8266 wifi_set_sleep_type(NONE_SLEEP_T); #endif + WLED::instance().disableWatchdog(); DEBUG_PRINTLN(F("Start ArduinoOTA")); }); + ArduinoOTA.onError([](ota_error_t error) { + // reenable watchdog on failed update + WLED::instance().enableWatchdog(); + }); if (strlen(cmDNS) > 0) ArduinoOTA.setHostname(cmDNS); } diff --git a/wled00/wled.h b/wled00/wled.h index 2267f2764..1a10199d0 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -703,5 +703,7 @@ public: void initConnection(); void initInterfaces(); void handleStatusLED(); + void enableWatchdog(); + void disableWatchdog(); }; #endif // WLED_H diff --git a/wled00/wled_server.cpp b/wled00/wled_server.cpp index c4cd09806..d9a58b11b 100644 --- a/wled00/wled_server.cpp +++ b/wled00/wled_server.cpp @@ -203,6 +203,7 @@ void initServer() },[](AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final){ if(!index){ DEBUG_PRINTLN(F("OTA Update Start")); + WLED::instance().disableWatchdog(); #ifdef ESP8266 Update.runAsync(true); #endif @@ -214,6 +215,7 @@ void initServer() DEBUG_PRINTLN(F("Update Success")); } else { DEBUG_PRINTLN(F("Update Failed")); + WLED::instance().enableWatchdog(); } } });