From 9db6a44809efed555e15e5b9c75e2a753338200f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 10 Nov 2025 06:39:00 +0000 Subject: [PATCH 1/4] Initial plan From 6fe7fb677c62de109fae7e2b628518a1c712a2dc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 10 Nov 2025 06:49:02 +0000 Subject: [PATCH 2/4] Fix ESP32-C3 OTA update issue by adding ESP-IDF OTA validation Co-authored-by: DedeHai <6280424+DedeHai@users.noreply.github.com> --- wled00/wled.cpp | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/wled00/wled.cpp b/wled00/wled.cpp index b40289be21..fc1d520b5d 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -12,6 +12,10 @@ #include "soc/rtc_cntl_reg.h" #endif +#ifdef ARDUINO_ARCH_ESP32 +#include +#endif + extern "C" void usePWMFixedNMI(); /* @@ -548,6 +552,36 @@ void WLED::setup() const uint32_t seed32 = hw_random(); random16_set_seed((uint16_t)seed32); +#ifdef ARDUINO_ARCH_ESP32 + // Mark OTA app as valid to prevent automatic rollback by ESP-IDF bootloader + // This is critical for OTA updates from 0.15 to 0.16+ on ESP32-C3 and other ESP32 variants + // Without this call, ESP-IDF 4.4+ will automatically roll back to the previous firmware + // after detecting that the new app hasn't validated itself + const esp_partition_t* running = esp_ota_get_running_partition(); + esp_ota_img_states_t ota_state; + if (esp_ota_get_state_partition(running, &ota_state) == ESP_OK) { + DEBUG_PRINTF_P(PSTR("OTA partition state: %d\n"), ota_state); + if (ota_state == ESP_OTA_IMG_PENDING_VERIFY) { + DEBUG_PRINTLN(F("Marking OTA app as valid (preventing rollback)")); + if (esp_ota_mark_app_valid_cancel_rollback() == ESP_OK) { + DEBUG_PRINTLN(F("OTA app marked as valid successfully")); + } else { + DEBUG_PRINTLN(F("Failed to mark OTA app as valid")); + } + } else if (ota_state == ESP_OTA_IMG_VALID) { + DEBUG_PRINTLN(F("OTA app already marked as valid")); + } else if (ota_state == ESP_OTA_IMG_INVALID) { + DEBUG_PRINTLN(F("WARNING: OTA app marked as INVALID")); + } else if (ota_state == ESP_OTA_IMG_ABORTED) { + DEBUG_PRINTLN(F("WARNING: OTA app marked as ABORTED")); + } else { + DEBUG_PRINTLN(F("OTA app in undefined state")); + } + } else { + DEBUG_PRINTLN(F("Failed to get OTA partition state")); + } +#endif + #if WLED_WATCHDOG_TIMEOUT > 0 enableWatchdog(); #endif From d04c9dc90aec199f88a63392313f5a2c59ced810 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 10 Nov 2025 06:50:50 +0000 Subject: [PATCH 3/4] Complete ESP32-C3 OTA update fix implementation Co-authored-by: DedeHai <6280424+DedeHai@users.noreply.github.com> --- _codeql_detected_source_root | 1 + 1 file changed, 1 insertion(+) create mode 120000 _codeql_detected_source_root diff --git a/_codeql_detected_source_root b/_codeql_detected_source_root new file mode 120000 index 0000000000..945c9b46d6 --- /dev/null +++ b/_codeql_detected_source_root @@ -0,0 +1 @@ +. \ No newline at end of file From aaad22acc6d4fa834ca1a1a900d7ef0cce9909d4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 10 Nov 2025 07:17:42 +0000 Subject: [PATCH 4/4] Move OTA validation earlier and add IDF version logging for debugging Co-authored-by: DedeHai <6280424+DedeHai@users.noreply.github.com> --- _codeql_detected_source_root | 1 - wled00/wled.cpp | 50 +++++++++++++++--------------------- 2 files changed, 20 insertions(+), 31 deletions(-) delete mode 120000 _codeql_detected_source_root diff --git a/_codeql_detected_source_root b/_codeql_detected_source_root deleted file mode 120000 index 945c9b46d6..0000000000 --- a/_codeql_detected_source_root +++ /dev/null @@ -1 +0,0 @@ -. \ No newline at end of file diff --git a/wled00/wled.cpp b/wled00/wled.cpp index fc1d520b5d..2f3755b359 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -365,6 +365,26 @@ void WLED::setup() DEBUG_PRINTF_P(PSTR("---WLED %s %u INIT---\n"), versionString, VERSION); DEBUG_PRINTLN(); #ifdef ARDUINO_ARCH_ESP32 + // Mark OTA app as valid IMMEDIATELY to prevent automatic rollback by ESP-IDF bootloader + // This MUST happen as early as possible, before any potential crashes + // Critical for OTA updates from 0.15 to 0.16+ on ESP32-C3 and other ESP32 variants + const esp_partition_t* running = esp_ota_get_running_partition(); + esp_ota_img_states_t ota_state; + if (esp_ota_get_state_partition(running, &ota_state) == ESP_OK) { + if (ota_state == ESP_OTA_IMG_PENDING_VERIFY) { + DEBUG_PRINTLN(F("*** OTA UPDATE DETECTED - Marking app as valid to prevent rollback ***")); + if (esp_ota_mark_app_valid_cancel_rollback() == ESP_OK) { + DEBUG_PRINTLN(F("OTA app marked valid successfully")); + } else { + DEBUG_PRINTLN(F("WARNING: Failed to mark OTA app as valid!")); + } + } + } + + // Check IDF version for compatibility warnings + const char* idf_ver = esp_get_idf_version(); + DEBUG_PRINTF_P(PSTR("ESP-IDF version: %s\n"), idf_ver); + DEBUG_PRINTF_P(PSTR("esp32 %s\n"), ESP.getSdkVersion()); #if defined(ESP_ARDUINO_VERSION) DEBUG_PRINTF_P(PSTR("arduino-esp32 v%d.%d.%d\n"), int(ESP_ARDUINO_VERSION_MAJOR), int(ESP_ARDUINO_VERSION_MINOR), int(ESP_ARDUINO_VERSION_PATCH)); // available since v2.0.0 @@ -552,36 +572,6 @@ void WLED::setup() const uint32_t seed32 = hw_random(); random16_set_seed((uint16_t)seed32); -#ifdef ARDUINO_ARCH_ESP32 - // Mark OTA app as valid to prevent automatic rollback by ESP-IDF bootloader - // This is critical for OTA updates from 0.15 to 0.16+ on ESP32-C3 and other ESP32 variants - // Without this call, ESP-IDF 4.4+ will automatically roll back to the previous firmware - // after detecting that the new app hasn't validated itself - const esp_partition_t* running = esp_ota_get_running_partition(); - esp_ota_img_states_t ota_state; - if (esp_ota_get_state_partition(running, &ota_state) == ESP_OK) { - DEBUG_PRINTF_P(PSTR("OTA partition state: %d\n"), ota_state); - if (ota_state == ESP_OTA_IMG_PENDING_VERIFY) { - DEBUG_PRINTLN(F("Marking OTA app as valid (preventing rollback)")); - if (esp_ota_mark_app_valid_cancel_rollback() == ESP_OK) { - DEBUG_PRINTLN(F("OTA app marked as valid successfully")); - } else { - DEBUG_PRINTLN(F("Failed to mark OTA app as valid")); - } - } else if (ota_state == ESP_OTA_IMG_VALID) { - DEBUG_PRINTLN(F("OTA app already marked as valid")); - } else if (ota_state == ESP_OTA_IMG_INVALID) { - DEBUG_PRINTLN(F("WARNING: OTA app marked as INVALID")); - } else if (ota_state == ESP_OTA_IMG_ABORTED) { - DEBUG_PRINTLN(F("WARNING: OTA app marked as ABORTED")); - } else { - DEBUG_PRINTLN(F("OTA app in undefined state")); - } - } else { - DEBUG_PRINTLN(F("Failed to get OTA partition state")); - } -#endif - #if WLED_WATCHDOG_TIMEOUT > 0 enableWatchdog(); #endif