Make controller input best-effort and harden OTA rollback.

Accel/tap use fire-and-forget ESP-NOW with a 10 ms FreeRTOS-safe cadence, OTA recovers from seq gaps and auto-reboots after success, and bootloader app rollback confirms after a stable boot.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-11-01 22:16:28 +01:00
co-authored by Cursor
parent ae8ef40820
commit 178ab46cec
35 changed files with 236 additions and 79 deletions
+7 -2
View File
@@ -111,8 +111,13 @@ void vCmdDispatcherTask(void *param) {
bool handled = false;
for (int i = 0; i < handler_count; i++) {
if (handlers[i].msg_id == msg.msg_id) {
ESP_LOGI(TAG, "trigger command %s (0x%02x)", message_type_name(msg.msg_id),
(unsigned)msg.msg_id);
if (msg.msg_id == (uint16_t)alox_MessageType_OTA_PAYLOAD) {
ESP_LOGD(TAG, "trigger command %s (0x%02x)",
message_type_name(msg.msg_id), (unsigned)msg.msg_id);
} else {
ESP_LOGI(TAG, "trigger command %s (0x%02x)",
message_type_name(msg.msg_id), (unsigned)msg.msg_id);
}
handlers[i].callback(msg.payload, msg.len);
handled = true;
break;
+7 -1
View File
@@ -2,6 +2,7 @@
#include "led_ring.h"
#include "ota_espnow.h"
#include "ota_uart.h"
#include "pod_reboot.h"
#include "uart_cmd.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
@@ -179,8 +180,10 @@ static void handle_ota_payload(const uint8_t *data, size_t len) {
ota_feed_result_t r = ota_uart_feed_chunk(req_ptr->seq, req_ptr->data.bytes,
req_ptr->data.size);
/* Gap: keep session; host block-retries from the last ACK boundary. */
if (r == OTA_FEED_SEQ_GAP) {
send_ota_failed(16);
ESP_LOGW(TAG, "OTA_PAYLOAD seq gap (got %lu) — waiting for host retry",
(unsigned long)req_ptr->seq);
return;
}
if (r == OTA_FEED_SEQ_DUP) {
@@ -257,6 +260,8 @@ static void ota_distribute_task(void *param) {
led_ring_ota_success();
free(job);
/* Host already got SUCCESS; reboot onto the staged image. */
pod_schedule_restart();
vTaskDelete(NULL);
}
@@ -332,6 +337,7 @@ static void ota_start_espnow_task(void *param) {
response.payload.ota_status.error = 0;
uart_cmd_send(&response, TAG);
led_ring_ota_success();
pod_schedule_restart();
vTaskDelete(NULL);
}