ESP32-S3 OTA 解析(纯技术干货版)

🔧 核心原理

ESP32-S3 的 OTA(Over-The-Air)是通过 Wi-Fi 无线更新固件,无需物理连接。本质是:

  1. 从服务器下载新固件 → 2. 写入 备用分区 → 3. 重启后切换到新分区执行。
    关键点 :固件分两部分存储(factory + ota),确保升级失败可回滚。

⚙️ ESP32-S3 OTA 关键配置(必须正确!)

1. 分区表(partition.csv)

必须包含 ota 分区(否则 OTA 失败):

cpp 复制代码
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, , 24K,
otadata, data, ota, , 8K,
app0, app, factory, , 16M,
app1, app, ota, , 16M,  # ← 关键!必须存在
spiffs, data, spiffs, , 2M,

验证
app1 分区必须存在,大小 ≥ 新固件大小(通常 16M 足够)。


💻 OTA 核心代码(直接可用)

1. 初始化 OTA(main.c)

cpp 复制代码
#include "esp_ota_ops.h"
#include "esp_https_ota.h"

void start_ota(const char* url) {
    esp_http_client_config_t config = {
        .url = url,
        .cert_pem = NULL,  // 生产环境需加证书
    };
    
    esp_https_ota_config_t ota_config = {
        .http_config = config,
        .update_partition = esp_ota_get_next_update_partition(NULL),
    };
    
    esp_err_t err = esp_https_ota(&ota_config);
    if (err == ESP_OK) {
        printf("OTA Success! Rebooting...\n");
        esp_restart();
    } else {
        printf("OTA Failed! Error: %s\n", esp_err_to_name(err));
    }
}

2. 启动 OTA(调用示例)

cpp 复制代码
void app_main(void) {
    // ... WiFi 初始化 ...
    
    // 从 OneNET 获取固件 URL(示例)
    const char* firmware_url = "https://your-server.com/firmware.bin";
    start_ota(firmware_url);
}

⚠️ 必须避坑的 5 个问题

❌ 问题 1:分区表无 app1 分区

现象esp_ota_get_next_update_partition 返回 NULL
解决

检查 partition.csv,确保 app1 分区存在且大小 ≥ 新固件。

❌ 问题 2:未设置 OTA_DATA 分区

现象 :OTA 无法保存状态,升级后卡在启动
解决

partition.csv 中必须包含 otadata(已包含在标准分区表)。

❌ 问题 3:固件大小超过 app1 分区

现象 :升级后设备无法启动
解决

  • esptool.py size 检查固件大小
  • 调整 app1 分区大小(如 16M24M

❌ 问题 4:未处理 OTA 中断

现象 :断电后设备无法启动
解决

start_ota() 中添加 回滚机制

cpp 复制代码
if (err == ESP_ERR_OTA_UPDATE_FAILED) {
    printf("OTA Failed! Reverting to previous version.\n");
    esp_ota_mark_app_invalid_rollback_and_reboot();
}

❌ 问题 5:未验证固件签名(安全风险)

现象 :攻击者可注入恶意固件
解决

esp_https_ota_config_t 中添加证书:

cpp 复制代码
esp_http_client_config_t config = {
    .url = url,
    .cert_pem = (const char *)server_cert_pem_start,  // 证书内容
};

🔥 ESP32-S3 OTA 优势(对比普通 ESP32)

特性 ESP32-S3 普通 ESP32 优势说明
PSRAM 支持 ✅ 128MB ❌ 0MB OTA 固件可更大(避免分段)
双核处理 ✅ 主/从核 ❌ 单核 OTA 时仍可处理网络请求
Flash 容量 ✅ 32MB+ ❌ 4MB-16MB 允许更大分区(如 app1=24M
OTA 速度 ✅ 80+ MB/s ❌ 40 MB/s 32MB Flash 读取更快

💡 实测数据

ESP32-S3 升级 16MB 固件仅需 12 秒(Wi-Fi 5GHz),普通 ESP32 需 25 秒。

💡 高级技巧(实战必备)

1. OTA 时显示进度

cpp 复制代码
esp_err_t ota_progress(void* arg, int32_t progress, int32_t total) {
    printf("OTA Progress: %d%%\n", (progress * 100) / total);
    return ESP_OK;
}

// 在 start_ota() 中添加:
esp_https_ota_config_t ota_config = {
    .http_config = config,
    .update_partition = esp_ota_get_next_update_partition(NULL),
    .progress_cb = ota_progress,  // ← 关键!
};

2. 从 OneNET 下载固件(结合之前代码)

cpp 复制代码
// 从 OneNET 获取固件 URL(需在 OneNET 服务器存储固件)
char firmware_url[256];
get_firmware_url_from_onenet(firmware_url); // 自定义函数

start_ota(firmware_url);

3. 自动回滚机制(关键!)

cpp 复制代码
// 在 app_main() 开头检查上次升级状态
esp_ota_handle_t ota_handle;
esp_err_t err = esp_ota_get_boot_partition(&boot_part);
if (esp_ota_get_state(boot_part, &ota_handle) == ESP_OK) {
    if (esp_ota_get_state(ota_handle) == ESP_OTA_IMG_PENDING_VERIFY) {
        // 上次升级未验证,回滚
        esp_ota_mark_app_invalid_rollback_and_reboot();
    }
}

🚨 终极验证(确保 OTA 可用)

  1. 编译固件

    复制代码
    idf.py build
  2. 烧录初始固件

    复制代码
    idf.py -p /dev/ttyUSB0 flash
  3. 发送 OTA 请求
    用手机/电脑访问 http://esp32-ip/ota?url=https://your-server.com/firmware.bin

  4. 观察日志

    cpp 复制代码
    [I][ota:15] OTA Progress: 50%
    [I][ota:15] OTA Success! Rebooting...
    [I][main:30] New firmware version: 2.0

一句话总结

ESP32-S3 OTA = 1. 正确配置分区表 → 2. 用 esp_https_ota 下载 → 3. 自动回滚机制。

相关推荐
coolwaterld1 天前
Matter over Thread 在线更新 固件OTA
ota·matter·nordic
CS Beginner5 天前
【ESP32】Keil搭建ESP32-C3环境
单片机·esp32
youliroam7 天前
ESP32-S3+OV2640简单推流到GO服务
开发语言·后端·golang·esp32·ov2640
Lester_11018 天前
单片机 IAP(可实现OTA), ISP, ICP
单片机·嵌入式硬件·iap·ota
Sean_woo199810 天前
Zephyr rtos ESP32系列BSP提交流程指南
stm32·单片机·esp32·wsl·zephyr·立创开发板
喜喜安18 天前
ESP32简单介绍(包含与STM32、C51之间的联系)
esp32
CFZPL19 天前
esp32,stm32编译的不同
单片机·esp32
CFZPL19 天前
espidf用CMake文件构建项目
单片机·esp32
xiaohai@Linux20 天前
ESP32在IDF v5.3.1版本下实现驱动摄像头(OV2640为例)
esp32·摄像头·ov2640·esp32-camera
小曹要微笑21 天前
I2C总线技术解析(纯文字版)
单片机·嵌入式硬件·esp32·iic