Public Access
OTA: the firmware rolls itself back; the bootloader doesn't
A deliberately crashing update looped forever on the device: the prebuilt bootloader ignores ESP_OTA_IMG_PENDING_VERIFY despite the app-side rollback config. UpdateService::bootGuard() now runs first in setup(): it counts starts on Probation in NVS and, on the second unconfirmed start, marks the image invalid and reboots into the previous one. Confirming (or the Wi-Fi rollback) resets the counter. ADR 0003 records the limit: a crash in the first milliseconds still needs USB. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
This commit is contained in:
@@ -91,6 +91,19 @@ void UpdateService::start() {
|
||||
if (!task_) xTaskCreate(taskEntry, "update", 8192, this, 1, &task_);
|
||||
}
|
||||
|
||||
void UpdateService::bootGuard(KeyValueStore& store) {
|
||||
esp_ota_img_states_t state;
|
||||
bool probation = esp_ota_get_state_partition(esp_ota_get_running_partition(), &state) == ESP_OK &&
|
||||
state == ESP_OTA_IMG_PENDING_VERIFY;
|
||||
int32_t attempts = 0;
|
||||
store.getInt("ota_attempts", attempts);
|
||||
if (Probation::rollBackAtBoot(probation, attempts)) {
|
||||
store.putInt("ota_attempts", 0);
|
||||
esp_ota_mark_app_invalid_rollback_and_reboot(); // does not return when there's a previous image
|
||||
}
|
||||
store.putInt("ota_attempts", probation ? attempts + 1 : 0);
|
||||
}
|
||||
|
||||
void UpdateService::tick(uint32_t nowMs) {
|
||||
if (!probation_) return;
|
||||
bool wifiConfigured = settings_.getBool(Setting::WifiEnabled) && saved_.count() > 0;
|
||||
@@ -101,10 +114,12 @@ void UpdateService::tick(uint32_t nowMs) {
|
||||
esp_ota_mark_app_valid_cancel_rollback();
|
||||
probation_ = false;
|
||||
store_.putString("ota_pending", "");
|
||||
store_.putInt("ota_attempts", 0);
|
||||
notify(std::string("Updated to ") + versionString(), NotificationLevel::Info);
|
||||
break;
|
||||
case Probation::Verdict::RollBack:
|
||||
// ota_pending still names this version: the previous firmware will report the failure.
|
||||
store_.putInt("ota_attempts", 0);
|
||||
delay(200);
|
||||
esp_ota_mark_app_invalid_rollback_and_reboot();
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user