分区表,主要是用来对 ESP32 外挂的 SPI FLASH 进行区域划分的一个表格,通过一个表格,可以根据多个不同的功能,将 SPI Flash 划分为不同的区域,方便开发者存储数据。本章,来了解一下 ESP32 分区表。

本章将分为如下几个小节:
1、什么是分区表
2、分区表作用
3、分区表结构
4、分区表类型
5、分区表API函数

1、什么是分区表?

        ESP32的分区表(Partition Table)是管理片上Flash存储空间的核心机制,其作用相当于Flash存储空间的"地图",决定了不同功能模块在Flash中的布局和访问规则。

        分区表部分的介绍可以参考乐鑫ESP-IDF编程指南中的分区表部分

2、分区表作用

2.1 物理存储空间划分​
  • ​定义存储布局​​:将Flash划分为多个逻辑分区(如bootloader、应用程序、数据区等);
  • ​地址分配​​:明确每个分区的起始地址(offset)和大小(size),避免空间冲突;
  • ​示例​​:
# Name,   Type, SubType, Offset,  Size
bootloader, 0x00, 0x00,  0x1000,  0x7000  # Bootloader区
nvs,        data, nvs,    0x9000,  0x4000  # NVS存储区
app,        app,  factory,0x10000, 1M      # 主应用程序区
2.2 多应用程序管理​

​支持OTA升级​​:通过定义多个OTA分区(如ota_0/ota_1)实现:

const esp_partition_t *update_part = esp_ota_get_next_update_partition(NULL);
  • 版本回滚​​:当新版本出现问题时,可切换回旧版本分区;

  • ​A/B测试​​:同时部署不同版本固件进行测试。

2.3 数据安全与隔离​
  • ​加密分区​​:通过encrypted标志指定需要加密的分区。
nvs, data, nvs, 0x9000, 0x4000, encrypted
  • 访问控制​​:限制不同分区读写权限(如只读工厂分区);

  • ​关键数据保护​​:隔离系统数据(NVS)和用户数据(FATFS)。

2.4 系统功能扩展​
  • ​文件系统支持​​:为SPIFFS/FATFS分配专用存储空间。
storage, data, fat,  , 512K
2.5 启动流程控制​
  • ​引导加载程序​​:Bootloader根据分区表决定加载哪个应用程序;

  • ​启动验证​​:通过校验分区MD5确保完整性;

  • ​故障恢复​​:定义工厂恢复分区作为保底启动选项。

2.6 资源优化​
  • ​动态调整​​:根据不同型号ESP32的Flash大小灵活调整分区;

  • ​空间复用​​:OTA分区可临时作为数据缓存区使用;

  • ​内存映射​​:支持将分区映射到内存直接访问(MMAP)。

esp_partition_mmap(part, 0, size, ESP_PARTITION_MMAP_DATA, &ptr, &handle);

典型应用场景示例​:

​OTA升级系统​​:

otadata,  data, ota,     0xd000,  0x2000  # 记录OTA状态
ota_0,    app,  ota_0,   0x10000, 1M      # 版本A
ota_1,    app,  ota_1,   0x110000,1M      # 版本B

​数据采集设备​​:

sensor_cfg, data, 0x40,  0x10000, 16K    # 传感器配置
log_data,   data, 0x41,  0x14000, 64K    # 日志存储

注意事项​

  • ​地址对齐​​:分区起始地址和大小必须4KB对齐

  • ​空间预留​​:建议保留≥10%的未分配空间

  • ​安全设计​​:关键分区应启用加密和写保护

3、分区表的结构

3.1 分区表地址介绍

        ESP32 的分区表中,0x0000 - 0x9000地址范围是系统关键区域的保留空间,包含 Bootloader 和分区表等核心组件。以下是该地址范围的详细说明:

地址 描述 大小 作用 注意事项
0x0000 Bootloader 头部信息 4KB 存储 Bootloader 的元数据,包括 Flash 加密密钥、芯片兼容性标志等。

1. 该区域由 ESP-IDF 自动管理,开发者无需手动修改;

2. 若启用 Flash 加密,此区域会被加密,但 Bootloader 会先解密再执行。

0x1000 Bootloader 代码区 28KB

存储 Bootloader 的可执行代码,负责:

1. 初始化硬件(CPU 时钟、SPI Flash、串口等);

2. 从 0x8000读取分区表;

3. 根据分区表加载应用程序或进入 OTA 流程。

若自定义 Bootloader 超过 28KB,需调整分区表偏移,但需确保与 ESP-IDF 兼容。
0x8000 分区表(Partition Table)区域 4KB

存储二进制格式的分区表,定义 Flash 的逻辑划分(如应用程序、数据分区的偏移和大小)。

内容:

1. 每个分区条目占 32 字节,包含名称、类型、子类型、偏移、大小和标志;

2. 可通过 esptool.py读取和解析。

1. 固定 4KB(即使实际内容不足 4KB 也会占用完整 Sector);

2. 分区表默认由 partitions.csv文件编译生成,开发者需确保 CSV 配置正确。

0x9000 用户分区起始地址 - 标记第一个用户自定义分区的开始(如 nvs分区) 后续分区的偏移地址必须从 0x9000开始,且按 4KB 对齐

关键注意事项​:

  • 禁止手动修改​​:0x0000 - 0x9000的内容由系统自动管理,错误写入可能导致设备无法启动(需重新烧录 Bootloader 和分区表);
  • 地址冲突风险​​:若扩展 Bootloader 或调整分区表偏移,需确保不与后续分区重叠;
  • 加密影响​​:启用 Flash 加密后,0x0000 - 0x9000的内容会被加密,但 Bootloader 能自动解密。

典型配置示例​:

下面配置示例中,0x9000之后的地址由开发者根据需求灵活分配,但需遵循 4KB 对齐规则:

# ESP-IDF Partition Table
# Name,   Type, SubType, Offset,  Size,   Flags
nvs,      data, nvs,     0x9000,  0x6000,
phy_init, data, phy,     0xf000,  0x1000,
factory,  app,  factory, 0x10000, 1M,

通过下图展示每一部分在FALSH中分布:

3.2 分区表(0x8000 - 0x9000)介绍

        地址(0x8000 - 0x9000)保存的是文件partitions.csv的内容,是用户自定义的各分区配置的大小和位置;

        ESP32的分区表主要有两种格式,一种是.csv格式,它方便开发人员进行更改和设置各个子
分区的偏移与空间大小,;另一种则是用于烧录设备的.bin 文件格式。在系统编译时,系统会将.csv 文件转化为.bin 文件格式的分区表。下面展示了基础例程的分区表文件的内容。

# ESP-IDF Partition Table
# Name,     Type, SubType, Offset,   Size,    Flags
  nvs,      data, nvs,     0x9000,   0x6000,   ,
  phy_init, data, phy,     0xf000,   0x1000,   ,
  factory,  app,  factory, 0x10000,  0x1F0000, ,
  vfs,      data, fat,     0x200000, 0xA00000, ,
  storage,  data, spiffs,  0xc00000, 0x400000, ,

        以上基础例程展示了 ESP32的多个子分区及其功能。其中:

  • nvs:子分区是专为开发者设计的非易失性存储(NVS)设备区域;

  • phy_init :子分区用于存放 PHY 初始化数据,确保每个设备都能单独配置其 PHY;

  • factory:子分区则专门用于存储应用程序区域;

  • vfs:子分区作为虚拟文件系统的存储区域;

  • storage :子分区则是自定义的 SPIFFS 文件系统区域。这些子分区共同构成了 ESP32 的分区结构,满足了不同功能的需求。

字段说明:
      每一个子分区都由以下几个部分组成:

  • name:子分区名称。 该字段对 ESP32-S3 并不是特别重要。

  • Type:子分区的存储类型。 设置子分区的存储格式, app (0x00) 和 data (0x01);

  • SubType: 进一步描述或分类分区表的条目。 如果这个子分区 Type 为 app,则 SubType只能设置 factory、 ota_0、 ota_15 和 test;如果这个子分区 Type 为 data,则 SubType 只能设置 ota、 phy、 nvs 和 nvs_keys;

  • Offset:偏移地址。 编译地址必须是 4KB 的倍数;

  • Size:大小。 子分区的大小;

  • Flags:标志位, 一般不设置该字段。

注意:二进制格式的分区表中含有一个 MD5 校验和。这个 MD5 校验和是根据分区表内容计算的,可在设备启动阶段,用于验证分区表的完整性。

3.3 分区表查看方法

3.3.1 执行环境要求​

  • ​硬件连接​​:ESP32 需通过 USB 与电脑连接(如 CP2102/CH340 串口芯片)。

  • ​软件依赖​​:

    • 已安装 Python(建议 3.7+)

    • 已安装 esptool.py(ESP-IDF 自带或通过 pip install esptool安装)

    • 串口驱动已正确安装(可在设备管理器中确认端口号,如 COM3或 /dev/ttyUSB0

3.3.2 执行命令详解​

esptool.py --port <PORT> read_flash 0x8000 0x1000 partitions.bin

参数说明​​:

  • --port <PORT>:替换为 ESP32 的实际串口号(如 COM3或 /dev/ttyUSB0)。

  • read_flash:读取 Flash 数据的子命令。

  • 0x8000:起始地址(分区表固定位置)。

  • 0x1000:读取大小(4KB,覆盖整个分区表区域)。

  • partitions.bin:输出的二进制文件名(可自定义)。

3.3.3 操作步骤

Windows 示例​​(以 COM4为例,具体以自己实验环境分的为准):

  • 打开 ​命令提示符(CMD)​​ 或 ​​PowerShell​​,进入到安装路径D:\D\SoftWareInstall\Espressif\frameworks\esp-idf-v5.4.2,注意这个路径以自己安装为准,执行脚本export.bat。

  • 执行上面脚本后就进入 ESP-IDF 环境:

进入路径及执行脚本:

D:\D\SoftWareInstall\Espressif\frameworks\esp-idf-v5.4.2
export.bat

脚本执行结果:

使用 esptool.py 读取并解析:

esptool.py --port COM4 read_flash 0x8000 0x1000 partitions.bin

执行成功会显示如下:

生成的文件 partitions.bin可用工具解析:

python ./components/partition_table/gen_esp32part.py partitions.bin

输出如下:

4、分区表的类型

        分区表(partitions.csv文件结构)的类型具有四种,如下表所示:

分区表类型 描述
Single factory app no OTA 小型的应用程序,但没有 OTA 升级区域
Single factory app (large) no OTA 大型的应用程序,但没有 OTA 升级区域
Factory app two OTA definitions  大型的应用程序,且具备两个OTA升级区域
Two large size OTA partitions Flash划分为两个主要用于OTA(空中升级)的分区。常见于支持双分区OTA的场景。
Custom partition table CSV 自定义分区表
4.1 分区表类型配置

具体是在menuconfig中配置:

4.2 分区表5种模式介绍

下面介绍ESP32 分区表配置中​​5 种模式:

1)Single factory app, no OTA​

特点​​:最简单的分区布局,仅包含一个不可更新的出厂应用,适用于不需要 OTA 升级的稳定设备。

​适用场景​​:量产固件、一次性烧录设备(如工业控制器)。

# Name,     Type, SubType, Offset,  Size
nvs,        data, nvs,     0x9000,  0x4000
phy_init,   data, phy,     0xd000,  0x1000
factory,    app,  factory, 0x10000, 1M     # 固定应用分区

​关键点​​:

  • 无 OTA 分区,无法远程更新固件

  • 所有空间分配给 factory分区(1MB)

  • 需通过串口重新烧录更新固件、

2)​​Single factory app (large), no OTA​

特点​​:扩大应用分区占用空间,适合需要更多 Flash 资源的应用。

​适用场景​​:图形界面(LVGL)、音视频处理等大容量固件。

# Name,     Type, SubType, Offset,  Size
nvs,        data, nvs,     0x9000,  0x4000
phy_init,   data, phy,     0xd000,  0x1000
factory,    app,  factory, 0x10000, 2M     # 更大的应用分区

关键点​​:

  • 应用分区扩展至 2MB(需 Flash ≥ 4MB)

  • 牺牲了未来 OTA 的可能性

3)Factory app, two OTA definitions​

特点​​:标准 OTA 升级方案,保留出厂备份和双 OTA 分区。

​适用场景​​:需要可靠远程更新的设备(如智能家居设备)。

# Name,     Type, SubType, Offset,  Size
nvs,        data, nvs,     0x9000,  0x4000
otadata,    data, ota,     0xd000,  0x2000  # OTA 状态存储
phy_init,   data, phy,     0xf000,  0x1000
factory,    app,  factory, 0x10000, 1M      # 出厂备份
ota_0,      app,  ota_0,   0x110000,1M      # OTA 分区 A
ota_1,      app,  ota_1,   0x210000,1M      # OTA 分区 B

关键点​​:

  • otadata分区记录当前激活的 OTA 分区

  • 更新流程:

esp_ota_set_boot_partition(ota_1); // 切换至 ota_1
  • 保留 factory分区作为恢复手段

4)​​Two large size OTA partitions​

​特点​​:为 OTA 分区分配更大空间,适合资源密集型应用。

​适用场景​​:需要 OTA 且固件较大的场景(如 AI 模型更新)。

# 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, 2M      # 大容量 OTA A
ota_1,      app,  ota_1,   0x210000,2M      # 大容量 OTA B

关键点​​:

  • 每个 OTA 分区 2MB,需 Flash ≥ 4MB

  • 删除了 factory分区以腾出空间

  • 需确保 OTA 包压缩率(如 LZMA)以适配网络传输

5)Custom partition table CSV​

​特点​​:完全自定义分区,支持特殊需求(如多文件系统、加密分区)。

​适用场景​​:复杂存储需求的设备(如数据记录仪)。

# Name,      Type, SubType, Offset,   Size,  Flags
nvs,         data, nvs,     0x9000,   0x4000
cfg,         data, 0x99,    0xd000,   0x2000, encrypted  # 自定义加密配置区
audio,       data, fat,     0xf000,   0x50000            # SPIFFS 文件系统
main_app,    app,  factory, 0x5f000,  1M
ota_0,       app,  ota_0,   ,         1M                 # 自动计算偏移

关键点​​:

  • 自定义 SubType(如 0x99)需在代码中通过 esp_partition_find_first访问

  • encrypted标志需启用 Flash 加密

  • 未指定 Offset的分区会自动接续前一分区

如何选择分区方案?​

方案

Flash 需求

OTA 支持

适用阶段

Single factory

≥ 2MB

量产稳定固件

Large factory

≥ 4MB

资源密集型固件

Two OTA

≥ 4MB

常规产品

Large OTA

≥ 8MB

大固件 OTA

Custom CSV

按需分配

可选

特殊存储需求

注意:所有方案均需保证分区 ​​不重叠​​ 且 ​​4KB 对齐​​。实际开发中建议优先测试 OTA 流程的可靠性。

5、分区表 API 函数

        esp_partition 组件是 ESP-IDF 中用于管理 ESP32 及其系列芯片上 flash 分区的一个关键组件。它提供了一组高层次的 API 函数,允许开发者方便地访问和操作定义在分区表中的各个分区。这些高层次的 API 函数为开发者提供了简洁和易用的接口,以进行诸如读取、写入、擦除分区内容等操作。 这些函数可在 components/esp_partition/include/esp_partition.h 路径下找到这些分区表 API 函数。

  • esp_partition_find 函数

该函数查找子分区,该函数原型如下所示:

const esp_partition_t *esp_partition_find_first(esp_partition_type_t type,
esp_partition_subtype_t subtype,
const char *label)

该函数的形参描述如下表所示:

参数 子分区类型 描述
type ESP_PARTITION_TYPE_APP 应用程序分区类型
ESP_PARTITION_TYPE_DATA 数据分区类型
ESP_PARTITION_TYPE_ANY 搜索随意类型分区
subtype 子类型(请看 esp_partition_subtype_t 结构体)
label 子分区名称

该函数返回值如下:
NULL:未找到子分区。 esp_partition_t 指针:返回子分区。

  • esp_partition_read 函数

该函数用于读取子分区的某个地址的数据,该函数原型如下所示:

esp_err_t esp_partition_read( const esp_partition_t* partition,
size_t src_offset, void* dst, size_t size)

该函数的形参描述如下表所示:

参数 描述
partition 分区结构指针
src_offset 读取数据的地址
dst 存储数据的指针
size 读取数据大小

该函数返回值如下:
ESP_OK: 读取成功。其他: 失败。

  • esp_partition_write 函数

该函数用于写入子分区的某个地址的数据,该函数原型如下所示:

esp_err_t esp_partition_write( const esp_partition_t* partition,
size_t dst_offset,
void* src, size_t size)

该函数的形参描述如下表所示:

参数 描述
partition 分区结构指针
dst_offset 写入数据的地址
src 写入数据
size 写入数据大小

该函数返回值如下:
ESP_OK:读取成功。其他:失败。

  • esp_partition_range 函数

该函数用于擦除子分区的某个地址的数据,该函数原型如下所示:

esp_err_t esp_partition_erase_range(const esp_partition_t *partition,
size_t offset, size_t size)

该函数的形参描述如下表所示:

参数 描述
partition 分区结构指针
offset 擦除数据的地址
size 擦除数据大小

该函数返回值如下:
ESP_OK:读取成功。其他:失败。
        上述列举的函数是访问和操作分区表时较为常用的 API 函数。若需进一步了解或学习其他剩余的分区表 API 函数,可查阅 esp_partition.h 头文件。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐