ESP32 各型号远程 OTA 分区表建议与实战说明
ESP32 各型号远程 OTA 分区表建议与实战说明
1. OTA 分区表核心概念
ESP32 系列做远程 OTA,核心不是看“ESP32、ESP32-S3、ESP32-C3”这些名字,而是看 Flash 容量、固件大小、是否需要文件系统、是否需要回滚保护。
ESP-IDF 的分区表默认烧录在 Flash 的 0x8000 地址,占用一个完整 4KB 扇区;普通 App 默认从 0x10000 开始。分区表每一项包含 Name、Type、SubType、Offset、Size、Flags 等字段。([Espressif Systems][1])
OTA 项目通常至少需要:
otadata, data, ota
ota_0, app, ota_0
ota_1, app, ota_1
其中 otadata 用来记录当前应该启动哪个 OTA 分区;ota_0 和 ota_1 是两个 App 槽位,设备运行其中一个分区时,可以把新固件写入另一个分区。ESP-IDF/Arduino-ESP32 文档都说明,基础 OTA 一般需要两个 OTA App 分区和一个 OTA data 分区。([Espressif Systems][1])
2. 各型号 OTA 分区表推荐
说明:同一套分区表格式适用于 ESP32、ESP32-S2、ESP32-S3、ESP32-C3、ESP32-C6、ESP32-H2 等 ESP-IDF 支持的芯片。真正影响分区表的是 Flash 大小。
| 芯片型号 | 常见 Flash | 推荐 OTA 分区方案 | 建议 |
|---|---|---|---|
| ESP32 / ESP32-WROOM / ESP32-WROVER | 4MB / 8MB / 16MB | 4MB 基础 OTA 或 8MB 平衡 OTA | 普通 WiFi 设备 4MB 可用;带 HTTPS、Web 配置页、日志建议 8MB |
| ESP32-S2 | 4MB / 8MB / 16MB | 4MB 或 8MB OTA | 只有 WiFi,无蓝牙;USB 相关项目建议 8MB 起 |
| ESP32-S3 | 8MB / 16MB 常见 | 8MB 或 16MB OTA | 摄像头、语音、LVGL、AI、Web 资源建议 16MB |
| ESP32-C2 | 2MB / 4MB | 2MB 勉强 OTA,推荐 4MB | 2MB 只能做极简 OTA,不建议放复杂 HTTPS 固件 |
| ESP32-C3 | 4MB / 8MB | 4MB 基础 OTA | 小型 IoT、传感器、开关类设备很适合 |
| ESP32-C5 | 8MB 常见 | 8MB OTA | 新项目建议 ESP-IDF;多协议功能建议预留更大 App 分区 |
| ESP32-C6 | 4MB / 8MB / 16MB | 8MB 或 16MB OTA | WiFi 6、BLE、Thread、Zigbee 项目建议 8MB 起;乐鑫模块页列出 C6 WROOM 有 4/8/16MB 规格。([Espressif Systems][2]) |
| ESP32-H2 | 4MB / 8MB | 4MB 或 8MB OTA | H2 主要是 BLE/Thread/Zigbee,不自带 WiFi,远程 OTA 通常依赖网关 |
| ESP32-P4 | 16MB / 32MB 常见外部 Flash | 16MB 或 32MB OTA | P4 偏 HMI、视觉、边缘计算,建议大 Flash |
3. 分区表选择原则
3.1 远程 OTA 最少要两个 App 分区
OTA 的基本逻辑是:
当前运行 ota_0
下载新固件到 ota_1
校验成功
修改 otadata
重启进入 ota_1
下一次更新再写回 ota_0
所以远程 OTA 不建议只有一个 App 分区。一个 App 分区只能串口升级,或者做非常复杂的临时下载方案,不适合普通远程 OTA。
3.2 建议去掉 factory 分区
ESP-IDF 默认 OTA 表经常是:
factory
ota_0
ota_1
但是 factory 分区不会被 OTA 更新。官方文档也说明,如果想节省 Flash,可以去掉 factory 分区,直接使用 ota_0 作为默认应用分区。
推荐新项目使用:
ota_0
ota_1
而不是:
factory
ota_0
ota_1
原因是 4MB Flash 很紧张,去掉 factory 可以让两个 OTA 分区更大。
3.3 App 分区必须够大
判断方法:
单个 OTA 分区大小 > 当前 firmware.bin 大小 + 未来增长空间
例如:
当前固件 1.1MB
建议单个 OTA 分区至少 1.5MB
更推荐 2MB 以上
如果你的固件包含:
HTTPS OTA
蓝牙
WiFi 配网
WebServer
LVGL
摄像头
音频
证书
字体
图片资源
就不要用太小的 1MB App 分区。
4. 推荐分区表一:2MB Flash 极限 OTA
适合:
ESP32-C2 2MB
极简传感器
无复杂 Web
无大资源
固件小于 900KB
不推荐:
HTTPS 很复杂
BLE + WiFi + 大量库
WebServer
文件系统
LVGL
摄像头
文件名建议:
partitions_ota_2mb.csv
# ESP-IDF Partition Table
# 适用场景:2MB Flash 极限 OTA
# 注意:2MB 做 OTA 非常紧张,只适合极简固件
# Name, Type, SubType, Offset, Size, Flags
# NVS:保存 WiFi、参数、设备配置
nvs, data, nvs, 0x9000, 0x3000,
# OTA 选择信息:固定 8KB
otadata, data, ota, 0xC000, 0x2000,
# PHY 校准数据:一般保留 4KB
phy_init, data, phy, 0xE000, 0x1000,
# 第一个 OTA App 分区:960KB
ota_0, app, ota_0, 0x10000, 0xF0000,
# 第二个 OTA App 分区:960KB
ota_1, app, ota_1, 0x100000, 0xF0000,
# 崩溃转储,可选;如果固件太大,可以删除
coredump, data, coredump,0x1F0000, 0x10000,
5. 推荐分区表二:4MB Flash 基础 OTA
适合:
ESP32-WROOM-32 4MB
ESP32-C3 4MB
ESP32-S2 4MB
ESP32-C6 4MB
普通 WiFi 远程升级项目
特点:
两个 App 分区接近 1.8MB
适合普通 OTA
不放 SPIFFS / LittleFS
文件名建议:
partitions_ota_4mb_basic.csv
# ESP-IDF Partition Table
# 适用场景:4MB Flash,最大化 App 空间
# Name, Type, SubType, Offset, Size, Flags
# NVS:保存 WiFi、设备配置、Token 等
nvs, data, nvs, 0x9000, 0x5000,
# OTA 选择信息:必须有,固定 8KB
otadata, data, ota, 0xE000, 0x2000,
# 第一个 OTA App 分区,约 1.8125MB
ota_0, app, ota_0, 0x10000, 0x1D0000,
# 第二个 OTA App 分区,约 1.8125MB
ota_1, app, ota_1, 0x1E0000, 0x1D0000,
# 崩溃转储:用于保存 panic 信息,调试阶段建议保留
coredump, data, coredump,0x3B0000, 0x10000,
# 预留参数区:可以保存设备 SN、出厂参数、校准数据
factory_param,data,nvs, 0x3C0000, 0x40000,
如果你的固件超过 1.8MB,这个方案就不够了,建议换 8MB Flash。
6. 推荐分区表三:4MB Flash 带文件系统 OTA
适合:
需要少量网页资源
需要存日志
需要 LittleFS / SPIFFS
固件控制在 1.5MB 以内
文件名建议:
partitions_ota_4mb_storage.csv
# ESP-IDF Partition Table
# 适用场景:4MB Flash,同时需要 OTA 和文件系统
# 缺点:App 分区比 basic 方案小
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, 0xE000, 0x2000,
# 每个 App 分区 1.5MB
ota_0, app, ota_0, 0x10000, 0x180000,
ota_1, app, ota_1, 0x190000, 0x180000,
# 文件系统区,约 896KB
spiffs, data, spiffs, 0x310000, 0xE0000,
# 崩溃转储,64KB
coredump, data, coredump,0x3F0000, 0x10000,
如果是 ESP-IDF 新项目,也可以把 spiffs 改成 fat,具体看你用 SPIFFS、LittleFS 还是 FATFS。
7. 推荐分区表四:8MB Flash 平衡 OTA
适合:
ESP32-S3 8MB
ESP32-C6 8MB
ESP32-C5 8MB
ESP32-WROVER 8MB
需要 HTTPS OTA
需要 Web 配置页
需要日志、图片、证书、资源文件
Arduino-ESP32 官方示例中也给出了 8MB OTA + Storage 的常见布局,例如两个约 2MB App 分区加文件系统。([Espressif Systems][3])
这里给一个更偏向 ESP-IDF 项目的 8MB 平衡方案:
文件名建议:
partitions_ota_8mb.csv
# ESP-IDF Partition Table
# 适用场景:8MB Flash,推荐大多数正式 OTA 项目使用
# Name, Type, SubType, Offset, Size, Flags
# NVS:32KB,用于 WiFi、配置、Token
nvs, data, nvs, 0x9000, 0x5000,
# OTA 选择信息:8KB
otadata, data, ota, 0xE000, 0x2000,
# App0:3.1875MB
ota_0, app, ota_0, 0x10000, 0x330000,
# App1:3.1875MB
ota_1, app, ota_1, 0x340000, 0x330000,
# 文件系统:约 1.5625MB
spiffs, data, spiffs, 0x670000, 0x180000,
# 崩溃转储:64KB
coredump, data, coredump,0x7F0000, 0x10000,
这个方案比较适合:
WiFi + MQTT
HTTPS OTA
BLE 配网
WebServer
传感器数据缓存
小型 UI 资源
8. 推荐分区表五:16MB Flash 大型 OTA
适合:
ESP32-S3-N16R8
ESP32-S3 摄像头项目
LVGL 项目
大字体
图片资源
离线网页
音频提示
复杂 Web 面板
文件名建议:
partitions_ota_16mb.csv
# ESP-IDF Partition Table
# 适用场景:16MB Flash,大型 OTA 项目
# Name, Type, SubType, Offset, Size, Flags
# NVS:64KB
nvs, data, nvs, 0x9000, 0x7000,
# OTA 选择信息:8KB
otadata, data, ota, 0x10000, 0x2000,
# 为了 App 分区 64KB 对齐,这里预留一小段
reserved, data, 0x40, 0x12000, 0xE000,
# App0:6MB
ota_0, app, ota_0, 0x20000, 0x600000,
# App1:6MB
ota_1, app, ota_1, 0x620000, 0x600000,
# 文件系统:约 3.75MB
spiffs, data, spiffs, 0xC20000, 0x3D0000,
# 崩溃转储:64KB
coredump, data, coredump,0xFF0000, 0x10000,
注意:如果你不想手动计算偏移,也可以把 App 之后的 Offset 留空,让工具自动对齐。ESP-IDF 文档说明,CSV 中 Offset 留空时,gen_esp32part.py 会根据前一个分区和对齐要求自动计算;App 分区偏移需要 64KB 对齐。
9. 推荐分区表六:16MB 自动偏移写法
这种写法更安全,不容易算错地址。
# ESP-IDF Partition Table
# 自动偏移版本:推荐给不想手算地址的项目
# 注意:第一个分区建议保留 0x9000
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x7000,
otadata, data, ota, , 0x2000,
phy_init, data, phy, , 0x1000,
# App 分区 Offset 留空,工具会自动 64KB 对齐
ota_0, app, ota_0, , 6M,
ota_1, app, ota_1, , 6M,
# 文件系统区
spiffs, data, spiffs, , 0x3C0000,
# 崩溃转储
coredump, data, coredump,, 0x10000,
10. 为什么不建议 1MB + 1MB OTA?
ESP-IDF 默认示例中常见:
factory, 1M
ota_0, 1M
ota_1, 1M
这个表适合早期简单项目,但现在很多项目很容易超过 1MB,例如:
WiFi
BLE
HTTPS
MQTT
JSON
证书
NVS
WebServer
日志
OTA 回滚
如果固件超过分区大小,编译时会报类似:
app partition is too small
或者烧录后无法正常启动。
所以实际项目建议:
4MB Flash:每个 OTA App 至少 1.5MB
8MB Flash:每个 OTA App 建议 2MB ~ 3.2MB
16MB Flash:每个 OTA App 建议 4MB ~ 6MB
11. ESP-IDF 具体怎么配置 OTA 分区表
11.1 创建 CSV 文件
在项目根目录创建:
partitions_ota.csv
例如:
your_project/
├── CMakeLists.txt
├── main/
│ └── main.c
├── partitions_ota.csv
└── sdkconfig
11.2 menuconfig 配置
执行:
idf.py menuconfig
进入:
Partition Table
选择:
Custom partition table CSV
然后填写:
partitions_ota.csv
再进入:
Serial flasher config
确认 Flash 大小:
4MB / 8MB / 16MB
Flash 大小必须和你的开发板真实 Flash 一致,否则会出现分区超出 Flash 的问题。
11.3 查看分区表
执行:
idf.py partition-table
它会输出最终生成的分区布局。
ESP-IDF 构建系统会检查 App 是否能放入可用 App 分区,如果固件太大,会在构建阶段报错或警告。([Espressif Systems][1])
11.4 第一次烧录
如果你改过分区表,建议先擦除整片 Flash:
idf.py -p COM3 erase-flash
然后烧录:
idf.py -p COM3 flash monitor
Linux / macOS 示例:
idf.py -p /dev/ttyUSB0 erase-flash
idf.py -p /dev/ttyUSB0 flash monitor
12. ESP-IDF 远程 HTTPS OTA 代码框架
12.1 CMakeLists.txt 加依赖
idf_component_register(
SRCS "main.c"
INCLUDE_DIRS "."
REQUIRES esp_https_ota esp_http_client app_update
)
12.2 简化 OTA 代码
#include "esp_https_ota.h"
#include "esp_log.h"
#include "esp_system.h"
#define OTA_URL "https://your-server.com/firmware.bin"
static const char *TAG = "OTA";
extern const char server_cert_pem_start[] asm("_binary_server_cert_pem_start");
void start_https_ota(void)
{
esp_http_client_config_t http_config = {
.url = OTA_URL,
.cert_pem = server_cert_pem_start,
};
esp_https_ota_config_t ota_config = {
.http_config = &http_config,
};
ESP_LOGI(TAG, "Starting OTA from: %s", OTA_URL);
esp_err_t ret = esp_https_ota(&ota_config);
if (ret == ESP_OK) {
ESP_LOGI(TAG, "OTA success, restarting...");
esp_restart();
} else {
ESP_LOGE(TAG, "OTA failed: %s", esp_err_to_name(ret));
}
}
esp_https_ota() 会建立 HTTPS 连接、读取固件、写入 OTA 分区并完成 OTA 流程;成功后需要调用 esp_restart() 重启进入新固件。
13. OTA 回滚建议
正式产品建议开启:
CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
开启后,新固件第一次启动时需要主动确认自己可用:
#include "esp_ota_ops.h"
void app_confirm_if_pending(void)
{
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) {
// 这里可以检查 WiFi、传感器、配置、任务是否正常
bool ok = true;
if (ok) {
esp_ota_mark_app_valid_cancel_rollback();
} else {
esp_ota_mark_app_invalid_rollback_and_reboot();
}
}
}
}
ESP-IDF 的回滚机制会在新 App 第一次启动后等待确认;如果没有确认且发生重启,Bootloader 会把它标记为失败并回滚到上一个可用 OTA 分区。
建议在 app_main() 前期调用:
void app_main(void)
{
app_confirm_if_pending();
// 后续初始化 WiFi、MQTT、业务逻辑
}
14. Arduino / PlatformIO 怎么用自定义 OTA 分区表
14.1 Arduino IDE
在 .ino 同级目录放:
partitions.csv
Arduino-ESP32 文档说明,可以在草图同目录创建 partitions.csv,构建系统会使用这个自定义分区表。
示例目录:
MyOtaProject/
├── MyOtaProject.ino
└── partitions.csv
4MB OTA 示例:
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, 0xE000, 0x2000,
app0, app, ota_0, 0x10000, 0x1D0000,
app1, app, ota_1, 0x1E0000,0x1D0000,
spiffs, data, spiffs, 0x3B0000,0x50000,
14.2 PlatformIO
在项目根目录放:
partitions_ota.csv
然后修改:
[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
board_build.partitions = partitions_ota.csv
board_upload.flash_size = 4MB
ESP32-S3 示例:
[env:esp32-s3-devkitc-1]
platform = espressif32
board = esp32-s3-devkitc-1
framework = arduino
board_build.partitions = partitions_ota_8mb.csv
board_upload.flash_size = 8MB
15. 分区表注释写法建议
CSV 文件中推荐这样写注释:
# 这是注释
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x5000,
不建议这样写:
nvs, data, nvs, 0x9000, 0x5000, # 保存 WiFi
原因是不同构建环境对行尾中文注释兼容性不一定一致。最稳妥的方式是:
# NVS:保存 WiFi、Token、设备参数
nvs, data, nvs, 0x9000, 0x5000,
16. 常见错误和解决办法
16.1 固件太大
错误现象:
app partition is too small
解决:
1. 换 8MB 或 16MB Flash
2. 增大 ota_0 / ota_1
3. 删除 factory 分区
4. 减少 SPIFFS / LittleFS 空间
5. 关闭不必要组件
16.2 OTA 成功但重启后还是旧版本
可能原因:
1. 没有 otadata 分区
2. OTA 写入后没有设置 boot partition
3. 没有 esp_restart()
4. 分区表不是 OTA 分区表
5. 实际运行的是 factory 分区
如果用 esp_https_ota(),成功后它会处理切换逻辑,但仍然需要你调用:
esp_restart();
16.3 改了分区表后运行异常
解决:
idf.py erase-flash
idf.py flash monitor
原因是旧分区数据还残留在 Flash 里。ESP-IDF 文档也提醒,更新分区表不会自动擦除旧数据,必要时要整片擦除。
16.4 4MB Flash 放不下 HTTPS OTA
HTTPS OTA 需要 TLS、证书、HTTP Client、OTA 组件,固件会明显变大。
建议:
ESP32-C3 / ESP32 普通项目:4MB 勉强够
ESP32-S3 / C6 / 复杂项目:建议 8MB 起
带 UI / 摄像头 / Web 资源:建议 16MB
16.5 开启 Flash Encryption 后 OTA 失败
注意事项:
1. app 分区会被自动加密
2. otadata 也会被加密
3. OTA 写入必须走 ESP-IDF OTA API
4. 不要自己乱写 Flash 偏移
ESP-IDF 文档说明,开启 Flash Encryption 后,Bootloader、分区表、otadata、所有 app 分区等会默认加密。
17. 我的实际推荐
17.1 新手 / 普通项目
ESP32 / ESP32-C3 / ESP32-S2
Flash:4MB
分区表:4MB basic OTA
推荐:
partitions_ota_4mb_basic.csv
17.2 正式联网产品
ESP32 / ESP32-S3 / ESP32-C3 / ESP32-C6
Flash:8MB
分区表:8MB balanced OTA
推荐:
partitions_ota_8mb.csv
17.3 摄像头 / 屏幕 / LVGL / 复杂项目
ESP32-S3
Flash:16MB
PSRAM:8MB
分区表:16MB large OTA
推荐:
partitions_ota_16mb.csv
17.4 ESP32-H2 / Zigbee / Thread 设备
ESP32-H2
Flash:4MB 或 8MB
OTA 方式:通常通过网关或 BLE / Thread 传输
分区表:4MB basic OTA 或 8MB OTA
注意:ESP32-H2 不适合直接做 WiFi HTTPS OTA,因为它本身不是 WiFi 芯片。
18. 最终建议总结
如果你不知道怎么选,直接按下面来:
2MB Flash:不建议 OTA,除非极简固件
4MB Flash:可以 OTA,但不要放太多资源
8MB Flash:最推荐,正式项目够用
16MB Flash:ESP32-S3 / UI / 摄像头 / 大资源项目首选
最推荐的通用方案:
ESP32-C3 / ESP32:4MB basic OTA
ESP32-S3 / ESP32-C6:8MB OTA 起步
ESP32-S3 + 屏幕 / 摄像头:16MB OTA
不要盲目使用默认:
factory + ota_0 + ota_1
更推荐:
ota_0 + ota_1
这样 OTA 分区更大,后期不容易因为固件变大而爆分区。
更多推荐


所有评论(0)