diff options
| author | Luke Hoersten <[email protected]> | 2026-06-20 13:03:23 -0500 |
|---|---|---|
| committer | Luke Hoersten <[email protected]> | 2026-06-20 13:03:23 -0500 |
| commit | 175dd50ba2a2a6c8d033a9fd4e91f4823f9e210a (patch) | |
| tree | 2f41235b0a4792822f737953e6fa553383a7bd36 /main/ota.c | |
| parent | 3729f04458e358fab7872b9590d9fdb012f5ddf9 (diff) | |
firmware: OTA firmware updates via POST /firmware + rollback
Streams the raw .bin to the inactive ota_0/ota_1 slot via esp_ota_*, flips otadata, replies 200, reboots after 500 ms. Single-shot guarded by atomic_flag (409 on concurrent). CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE armed: new images boot pending-verify and ota_arm_healthy_timer marks them valid after 30 s of healthy uptime; otherwise the bootloader reverts on next reset. /state gains ota_state.
Diffstat (limited to 'main/ota.c')
| -rw-r--r-- | main/ota.c | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/main/ota.c b/main/ota.c new file mode 100644 index 0000000..3924dca --- /dev/null +++ b/main/ota.c @@ -0,0 +1,52 @@ +#include "ota.h" + +#include "esp_log.h" +#include "esp_ota_ops.h" +#include "esp_partition.h" +#include "esp_timer.h" + +static const char *TAG = "ota"; + +#define OTA_HEALTHY_DELAY_US (30ULL * 1000 * 1000) + +static void healthy_cb(void *arg) +{ + const esp_partition_t *running = esp_ota_get_running_partition(); + esp_ota_img_states_t st; + if (running && esp_ota_get_state_partition(running, &st) == ESP_OK + && st == ESP_OTA_IMG_PENDING_VERIFY) { + if (esp_ota_mark_app_valid_cancel_rollback() == ESP_OK) { + ESP_LOGI(TAG, "image marked valid (rollback cancelled)"); + } else { + ESP_LOGW(TAG, "esp_ota_mark_app_valid_cancel_rollback failed"); + } + } +} + +void ota_arm_healthy_timer(void) +{ + const esp_timer_create_args_t args = { + .callback = &healthy_cb, + .name = "ota_healthy", + }; + esp_timer_handle_t t = NULL; + if (esp_timer_create(&args, &t) != ESP_OK) return; + esp_timer_start_once(t, OTA_HEALTHY_DELAY_US); +} + +const char *ota_running_state_str(void) +{ + const esp_partition_t *running = esp_ota_get_running_partition(); + if (!running) return "unknown"; + esp_ota_img_states_t st; + if (esp_ota_get_state_partition(running, &st) != ESP_OK) return "unknown"; + switch (st) { + case ESP_OTA_IMG_NEW: return "new"; + case ESP_OTA_IMG_PENDING_VERIFY: return "pending-verify"; + case ESP_OTA_IMG_VALID: return "valid"; + case ESP_OTA_IMG_INVALID: return "invalid"; + case ESP_OTA_IMG_ABORTED: return "aborted"; + case ESP_OTA_IMG_UNDEFINED: return "undefined"; + default: return "unknown"; + } +} |
