From ba4a361d6459dec0cccaacbaa5a9aef00fde840f Mon Sep 17 00:00:00 2001 From: Justin Mitchell Date: Fri, 1 May 2026 19:15:15 -0400 Subject: [PATCH] fix: OTA update on x3 and progress bar on x4 and x3 (#1805) Co-authored-by: Justin Mitchell <1875695+itsthisjustin@users.noreply.github.com> --- platformio.ini | 2 +- src/activities/settings/OtaUpdateActivity.cpp | 22 +++++++++++++------ src/network/OtaUpdater.cpp | 7 ++---- src/network/OtaUpdater.h | 8 +++---- src/platform/skip_efuse_blk_check.c | 11 ++++++++++ 5 files changed, 32 insertions(+), 18 deletions(-) create mode 100644 src/platform/skip_efuse_blk_check.c diff --git a/platformio.ini b/platformio.ini index 189ff8d9..9d14b714 100644 --- a/platformio.ini +++ b/platformio.ini @@ -36,7 +36,7 @@ build_flags = # Default is (320*4+1)*2=2562, we need more for larger images -DPNG_MAX_BUFFERED_PIXELS=16416 -Wno-bidi-chars - -Wl,--wrap=panic_print_backtrace,--wrap=panic_abort + -Wl,--wrap=panic_print_backtrace,--wrap=panic_abort,--wrap=bootloader_common_check_efuse_blk_validity -fno-exceptions build_unflags = diff --git a/src/activities/settings/OtaUpdateActivity.cpp b/src/activities/settings/OtaUpdateActivity.cpp index c661a618..7bf1a444 100644 --- a/src/activities/settings/OtaUpdateActivity.cpp +++ b/src/activities/settings/OtaUpdateActivity.cpp @@ -139,11 +139,6 @@ void OtaUpdateActivity::render(RenderLock&&) { } void OtaUpdateActivity::loop() { - // TODO @ngxson : refactor this logic later - if (updater.getRender()) { - requestUpdate(); - } - if (state == WAITING_CONFIRMATION) { if (mappedInput.wasPressed(MappedInputManager::Button::Confirm)) { LOG_DBG("OTA", "New update available, starting download..."); @@ -152,7 +147,14 @@ void OtaUpdateActivity::loop() { state = UPDATE_IN_PROGRESS; } requestUpdateAndWait(); - const auto res = updater.installUpdate(); + const auto res = updater.installUpdate( + [](void* ctx) { + // immediate=true notifies the render task directly. The default deferred path only + // sets a flag consumed at the end of ActivityManager::loop(), which never runs while + // installUpdate() blocks this task. + static_cast(ctx)->requestUpdate(true); + }, + this); if (res != OtaUpdater::OK) { LOG_DBG("OTA", "Update failed: %d", res); @@ -168,7 +170,13 @@ void OtaUpdateActivity::loop() { RenderLock lock(*this); state = FINISHED; } - requestUpdate(); + requestUpdateAndWait(); + // Hold the completion screen briefly so the user sees it, then restart. + delay(3000); + { + RenderLock lock(*this); + state = SHUTTING_DOWN; + } } if (mappedInput.wasPressed(MappedInputManager::Button::Back)) { diff --git a/src/network/OtaUpdater.cpp b/src/network/OtaUpdater.cpp index 69f7e478..4f742559 100644 --- a/src/network/OtaUpdater.cpp +++ b/src/network/OtaUpdater.cpp @@ -200,15 +200,13 @@ bool OtaUpdater::isUpdateNewer() const { const std::string& OtaUpdater::getLatestVersion() const { return latestVersion; } -OtaUpdater::OtaUpdaterError OtaUpdater::installUpdate() { +OtaUpdater::OtaUpdaterError OtaUpdater::installUpdate(ProgressCallback onProgress, void* ctx) { if (!isUpdateNewer()) { return UPDATE_OLDER_ERROR; } esp_https_ota_handle_t ota_handle = NULL; esp_err_t esp_err; - /* Signal for OtaUpdateActivity */ - render = false; esp_http_client_config_t client_config = { .url = otaUrl.c_str(), @@ -241,8 +239,7 @@ OtaUpdater::OtaUpdaterError OtaUpdater::installUpdate() { do { esp_err = esp_https_ota_perform(ota_handle); processedSize = esp_https_ota_get_image_len_read(ota_handle); - /* Sent signal to OtaUpdateActivity */ - render = true; + if (onProgress) onProgress(ctx); delay(100); // TODO: should we replace this with something better? } while (esp_err == ESP_ERR_HTTPS_OTA_IN_PROGRESS); diff --git a/src/network/OtaUpdater.h b/src/network/OtaUpdater.h index 24e04cf5..c3a17431 100644 --- a/src/network/OtaUpdater.h +++ b/src/network/OtaUpdater.h @@ -1,6 +1,5 @@ #pragma once -#include #include class OtaUpdater { @@ -10,9 +9,10 @@ class OtaUpdater { size_t otaSize = 0; size_t processedSize = 0; size_t totalSize = 0; - bool render = false; public: + using ProgressCallback = void (*)(void* ctx); + enum OtaUpdaterError { OK = 0, NO_UPDATE, @@ -29,11 +29,9 @@ class OtaUpdater { size_t getTotalSize() const { return totalSize; } - bool getRender() const { return render; } - OtaUpdater() = default; bool isUpdateNewer() const; const std::string& getLatestVersion() const; OtaUpdaterError checkForUpdate(); - OtaUpdaterError installUpdate(); + OtaUpdaterError installUpdate(ProgressCallback onProgress = nullptr, void* ctx = nullptr); }; diff --git a/src/platform/skip_efuse_blk_check.c b/src/platform/skip_efuse_blk_check.c new file mode 100644 index 00000000..12a6f8da --- /dev/null +++ b/src/platform/skip_efuse_blk_check.c @@ -0,0 +1,11 @@ +// Override the prebuilt libbootloader_support.a implementation. +// The X3's validation code misreads the new image's esp_app_desc_t through a +// misaligned bootloader_mmap pointer, producing garbage eFuse block revision +// values that fail the check. Safe to skip: the eFuse block revision gate is +// a manufacturing concern, not a runtime safety issue. +#include +esp_err_t __wrap_bootloader_common_check_efuse_blk_validity(uint32_t min_rev_full, uint32_t max_rev_full) { + (void)min_rev_full; + (void)max_rev_full; + return ESP_OK; +}