diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 54c723c8..d15cd354 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -276,6 +276,44 @@ 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::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() @@ -302,6 +340,8 @@ void WLED::setup() DEBUG_PRINT(F("heap ")); DEBUG_PRINTLN(ESP.getFreeHeap()); + enableWatchdog(); + #if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM) if (psramFound()) { // GPIO16/GPIO17 reserved for SPI RAM @@ -401,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 d8e40475..3739cbb0 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" @@ -704,5 +711,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 c4cd0980..d9a58b11 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(); } } });