feat: Add v0.3 OTA updates — dual partition, esp-ota tool, rollback
Dual OTA partition table (ota_0/ota_1, 1920 KB each) on 4MB flash. Firmware gains OTA command, LED_OTA double-blink, version in STATUS, and automatic rollback validation. Pi-side esp-ota tool serves firmware via HTTP and orchestrates the update flow. esp-fleet gains ota subcommand.
This commit is contained in:
@@ -30,6 +30,9 @@
|
||||
#include "esp_now.h"
|
||||
#include "esp_timer.h"
|
||||
#include "esp_task_wdt.h"
|
||||
#include "esp_ota_ops.h"
|
||||
#include "esp_https_ota.h"
|
||||
#include "esp_http_client.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "mdns.h"
|
||||
|
||||
@@ -65,6 +68,7 @@ typedef enum {
|
||||
LED_SLOW_BLINK,
|
||||
LED_FAST_BLINK,
|
||||
LED_SOLID,
|
||||
LED_OTA,
|
||||
} led_mode_t;
|
||||
|
||||
/* --- Globals --- */
|
||||
@@ -74,6 +78,7 @@ static esp_ping_handle_t s_ping_handle = NULL;
|
||||
static volatile led_mode_t s_led_mode = LED_OFF;
|
||||
static volatile int64_t s_last_csi_time = 0;
|
||||
static volatile int64_t s_identify_end_time = 0;
|
||||
static volatile bool s_ota_in_progress = false;
|
||||
|
||||
/* UDP socket for CSI data transmission */
|
||||
static int s_udp_socket = -1;
|
||||
@@ -181,6 +186,18 @@ static void led_task(void *arg)
|
||||
led_on = true;
|
||||
vTaskDelay(pdMS_TO_TICKS(200));
|
||||
break;
|
||||
case LED_OTA:
|
||||
/* Double-blink: on-off-on-off-pause */
|
||||
gpio_set_level(LED_GPIO, 1);
|
||||
vTaskDelay(pdMS_TO_TICKS(80));
|
||||
gpio_set_level(LED_GPIO, 0);
|
||||
vTaskDelay(pdMS_TO_TICKS(80));
|
||||
gpio_set_level(LED_GPIO, 1);
|
||||
vTaskDelay(pdMS_TO_TICKS(80));
|
||||
gpio_set_level(LED_GPIO, 0);
|
||||
vTaskDelay(pdMS_TO_TICKS(500));
|
||||
led_on = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -375,6 +392,41 @@ static esp_err_t wifi_ping_router_start(void)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/* --- OTA --- */
|
||||
|
||||
static void ota_task(void *arg)
|
||||
{
|
||||
char *url = (char *)arg;
|
||||
ESP_LOGI(TAG, "OTA: downloading from %s", url);
|
||||
|
||||
s_led_mode = LED_OTA;
|
||||
|
||||
esp_http_client_config_t http_cfg = {
|
||||
.url = url,
|
||||
.timeout_ms = 30000,
|
||||
};
|
||||
|
||||
esp_https_ota_config_t ota_cfg = {
|
||||
.http_config = &http_cfg,
|
||||
};
|
||||
|
||||
esp_err_t err = esp_https_ota(&ota_cfg);
|
||||
free(url);
|
||||
|
||||
if (err == ESP_OK) {
|
||||
ESP_LOGI(TAG, "OTA: success, rebooting...");
|
||||
s_led_mode = LED_SOLID;
|
||||
vTaskDelay(pdMS_TO_TICKS(500));
|
||||
esp_restart();
|
||||
} else {
|
||||
ESP_LOGE(TAG, "OTA: failed: %s", esp_err_to_name(err));
|
||||
s_led_mode = LED_SLOW_BLINK;
|
||||
s_ota_in_progress = false;
|
||||
}
|
||||
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
/* --- Command handler --- */
|
||||
|
||||
static void reboot_after_delay(void *arg)
|
||||
@@ -414,6 +466,8 @@ static int cmd_handle(const char *cmd, char *reply, size_t reply_size)
|
||||
rssi = ap.rssi;
|
||||
}
|
||||
|
||||
const esp_app_desc_t *app_desc = esp_app_get_description();
|
||||
|
||||
char uptime_str[32];
|
||||
if (days > 0) {
|
||||
snprintf(uptime_str, sizeof(uptime_str), "%dd%dh%dm", days, hours, mins);
|
||||
@@ -424,9 +478,9 @@ static int cmd_handle(const char *cmd, char *reply, size_t reply_size)
|
||||
}
|
||||
|
||||
snprintf(reply, reply_size,
|
||||
"OK STATUS uptime=%s heap=%lu rssi=%d tx_power=%d rate=%d hostname=%s",
|
||||
"OK STATUS uptime=%s heap=%lu rssi=%d tx_power=%d rate=%d hostname=%s version=%s",
|
||||
uptime_str, (unsigned long)heap, rssi, (int)s_tx_power_dbm,
|
||||
s_send_frequency, CONFIG_CSI_HOSTNAME);
|
||||
s_send_frequency, CONFIG_CSI_HOSTNAME, app_desc->version);
|
||||
return strlen(reply);
|
||||
}
|
||||
|
||||
@@ -458,6 +512,28 @@ static int cmd_handle(const char *cmd, char *reply, size_t reply_size)
|
||||
return strlen(reply);
|
||||
}
|
||||
|
||||
/* OTA <url> */
|
||||
if (strncmp(cmd, "OTA ", 4) == 0) {
|
||||
const char *url = cmd + 4;
|
||||
if (strncmp(url, "http://", 7) != 0) {
|
||||
snprintf(reply, reply_size, "ERR OTA url must start with http://");
|
||||
return strlen(reply);
|
||||
}
|
||||
if (s_ota_in_progress) {
|
||||
snprintf(reply, reply_size, "ERR OTA already in progress");
|
||||
return strlen(reply);
|
||||
}
|
||||
char *url_copy = strdup(url);
|
||||
if (!url_copy) {
|
||||
snprintf(reply, reply_size, "ERR OTA out of memory");
|
||||
return strlen(reply);
|
||||
}
|
||||
s_ota_in_progress = true;
|
||||
xTaskCreate(ota_task, "ota_task", 8192, url_copy, 5, NULL);
|
||||
snprintf(reply, reply_size, "OK OTA started");
|
||||
return strlen(reply);
|
||||
}
|
||||
|
||||
snprintf(reply, reply_size, "ERR UNKNOWN");
|
||||
return strlen(reply);
|
||||
}
|
||||
@@ -563,4 +639,14 @@ void app_main()
|
||||
wifi_ping_router_start();
|
||||
|
||||
xTaskCreate(cmd_task, "cmd_task", 4096, NULL, 5, NULL);
|
||||
|
||||
/* OTA rollback: mark firmware valid if we got this far */
|
||||
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) {
|
||||
ESP_LOGI(TAG, "OTA: marking firmware valid (rollback cancelled)");
|
||||
esp_ota_mark_app_valid_cancel_rollback();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
6
get-started/csi_recv_router/partitions.csv
Normal file
6
get-started/csi_recv_router/partitions.csv
Normal file
@@ -0,0 +1,6 @@
|
||||
# Name, Type, SubType, Offset, Size
|
||||
nvs, data, nvs, 0x9000, 0x4000
|
||||
otadata, data, ota, 0xd000, 0x2000
|
||||
phy_init, data, phy, 0xf000, 0x1000
|
||||
ota_0, app, ota_0, 0x10000, 0x1E0000
|
||||
ota_1, app, ota_1, 0x1F0000, 0x1E0000
|
||||
|
@@ -49,3 +49,16 @@ CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=32
|
||||
#
|
||||
CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240=y
|
||||
CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ=240
|
||||
|
||||
#
|
||||
# Flash & Partitions (4MB flash, dual OTA)
|
||||
#
|
||||
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
|
||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
||||
|
||||
#
|
||||
# OTA Updates
|
||||
#
|
||||
CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE=y
|
||||
CONFIG_ESP_HTTPS_OTA_ALLOW_HTTP=y
|
||||
|
||||
Reference in New Issue
Block a user