ESP32 分区表详解:原理、配置与应用
·
ESP32 的分区表(Partition Table)是管理片上闪存(Flash)空间的核心机制,决定了固件、配置数据、文件系统等在 Flash 中的布局。合理的分区设计对系统稳定性、功能扩展性及 OTA 升级至关重要。
一、分区表基本概念
1. Flash 存储结构
ESP32 的 Flash 通常被划分为多个逻辑分区:
- Bootloader:启动加载程序(默认占用 0x0-0x8000 地址)
- 分区表:定义各分区的位置和属性(默认位于 0x8000)
- 应用程序:用户代码(如 factory 分区、OTA 分区)
- NVS:非易失性存储(保存配置参数)
- PHY:WiFi/BLE 物理层校准数据
2. 分区表的作用
- 明确各功能模块在 Flash 中的位置
- 支持多应用共存(如 OTA 升级)
- 隔离系统数据与用户数据
- 优化 Flash 空间利用
二、分区表格式与配置
1. CSV 格式定义
分区表通常以 CSV(逗号分隔值)文件形式定义,例如:
csv
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x6000,
phy_init, data, phy, 0xF000, 0x1000,
factory, app, factory, 0x10000, 1M,
ota_0, app, ota_0, 0x110000,1M,
ota_1, app, ota_1, 0x210000,1M,
2. 字段解析
- Name:分区名称(如
nvs、factory) - Type:分区类型
app:应用程序分区data:数据分区(如 NVS、SPIFFS)
- SubType:细分类型(如
ota_0、spiffs) - Offset:分区起始地址(如
0x10000) - Size:分区大小(支持单位:K、M,如
1M=1048576 字节) - Flags:特殊标志(如
encrypted表示加密分区)
三、常见分区类型与用途
1. 应用程序分区(Type=app)
- factory:出厂固件分区,系统首次启动时加载
- ota_0/ota_1:OTA 升级分区,用于存放新版本固件
- test:测试固件分区,用于验证新功能
2. 数据分区(Type=data)
- nvs:非易失性存储,保存配置参数(如 WiFi 密码)
- phy:WiFi/BLE 物理层校准数据
- spiffs/fatfs:文件系统分区,存储用户文件
- nvs_keys:NVS 加密密钥存储区
3. 特殊分区
- efuse:存储一次性可编程参数(如芯片 ID、安全密钥)
- otadata:OTA 数据分区,记录当前活动分区
四、ESP-IDF 中的分区表配置
1. 默认分区表
ESP-IDF 提供多种预定义分区表模板:
- default_singleapp.csv:单应用分区(无 OTA 支持)
- default_ota.csv:支持 OTA 升级的双分区
- min_spiffs.csv:包含 SPIFFS 文件系统的最小配置
2. 自定义分区表
- 创建
partitions.csv文件 - 在
CMakeLists.txt中指定:cmake
set(PartitionTable "partitions.csv") - 通过
idf.py menuconfig验证配置:plaintext
Partition Table ---> [*] Custom partition table CSV file (partitions.csv) Custom partition table CSV file
五、分区表管理 API
1. 获取分区信息
c
运行
#include "esp_partition.h"
// 根据类型和子类型查找分区
const esp_partition_t *factory_partition = esp_partition_find_first(
ESP_PARTITION_TYPE_APP,
ESP_PARTITION_SUBTYPE_APP_FACTORY,
NULL);
// 根据名称查找分区
const esp_partition_t *nvs_partition = esp_partition_find_first(
ESP_PARTITION_TYPE_DATA,
ESP_PARTITION_SUBTYPE_DATA_NVS,
"nvs");
2. OTA 分区操作
c
运行
#include "esp_ota_ops.h"
// 获取当前运行分区
const esp_partition_t *running = esp_ota_get_running_partition();
// 准备OTA升级
esp_err_t err = esp_ota_begin(ota_partition, OTA_SIZE_UNKNOWN, &ota_handle);
if (err != ESP_OK) {
ESP_LOGE(TAG, "OTA begin failed: %d", err);
return err;
}
// 写入OTA数据
err = esp_ota_write(ota_handle, (const void *)data, size);
// 完成OTA升级
err = esp_ota_end(ota_handle);
六、常见分区表设计模式
1. 单应用模式(无 OTA)
csv
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x6000,
phy_init, data, phy, 0xF000, 0x1000,
factory, app, factory, 0x10000, 2M,
2. OTA 双分区模式
csv
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x6000,
phy_init, data, phy, 0xF000, 0x1000,
otadata, data, ota, 0x10000, 0x2000,
ota_0, app, ota_0, 0x12000, 1M,
ota_1, app, ota_1, 0x112000,1M,
3. 含文件系统的配置
csv
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x6000,
phy_init, data, phy, 0xF000, 0x1000,
factory, app, factory, 0x10000, 1M,
spiffs, data, spiffs, 0x110000,512K,
七、分区表验证与调试
1. 查看当前分区表
bash
idf.py partition_table
输出示例:
plaintext
Name Type SubType Offset Size
--------------------------------------------------
nvs data nvs 0x9000 0x6000
phy_init data phy 0xF000 0x1000
factory app factory 0x10000 0x100000
2. 调试技巧
- 使用
esp_partition_info()获取分区详细信息 - 通过
esp_flash_erase_region()擦除特定分区 - 利用
esptool.py手动查看 / 修改分区表:bash
esptool.py --chip esp32s3 read_flash 0x8000 0x1000 partition_table.bin
八、注意事项与最佳实践
-
分区大小计算
- 应用分区大小需包含
.text、.data、.bss等段的总和 - 使用
idf.py size查看应用占用空间
- 应用分区大小需包含
-
OTA 升级安全
- 双 OTA 分区需确保大小一致
- 升级前验证新固件完整性(如 MD5 校验)
-
NVS 空间规划
- NVS 分区过小会导致配置保存失败
- 建议预留 24KB 以上空间
-
加密支持
- 通过
encrypted标志启用分区加密 - 需在 menuconfig 中开启 Flash 加密选项
- 通过
九、相关资源
合理设计分区表是 ESP32 项目成功的关键一步,需根据应用场景权衡功能需求与 Flash 空间利用。通过灵活配置分区表,可实现安全可靠的 OTA 升级、高效的数据存储及稳定的系统运行。
更多推荐
所有评论(0)