分区表


文章目录

  • 分区表
  • 1. esp32 flash结构
  • 1.1 flash 物理组成
  • 1.2 flash 内部结构
  • 1.3 esp32启动过程
  • 2. 分区表
  • 2.1 分区表的组成
  • 2.2 分区表的定义
  • 2.2.1 Name字段
  • 2.2.2 Type字段
  • 2.2.3 SubType字段
  • 2.2.4 offset和size
  • 2.2.5 flags
  • 2.3 系统分区表的查看
  • 2.4 分区表的更换
  • 2.4.1 使用内置分区表
  • 2.4.2 使用自定义的分区表
  • 3. 参考资料


1. esp32 flash结构

1.1 flash 物理组成

   esp32的falsh可以分为三部分:

  • 内部flash: 内部flash是esp32芯片自带的flash,空间大小是448k
  • 主系统falsh: 一般esp32模组都带了一个flash芯片作为主系统flash,通过spi总线进行访问。这个主falsh芯片是用来存放系统数据、代码等东西的,如wroom模组上带了4M的主系统flash。不过,esp32 configmenu默认设置主系统flash是2M,需要手动进行调整,最大可以达到16M。主系统flash芯片一般来说是必须的。
  • 外部flash: 除了主系统flash外,还可以通过spi的其他总线扩展外部flash。这个flash如果有需要,可以自己增加。

1.2 flash 内部结构

   flash从结构上来看,包括BootLoader分区表用户数据(包括代码和存储数据)三部分。

   比如我们看下面实际的一张flash内存表

esp32外置flash的大小 esp32 flash大小_数据

  flash从0x8000以前的区域,都是bootloader,用于esp32的启动

  flash在0x8000处烧写一张分区表(partition Table),该分区长度为0xC00字节,最多可以保存95条分区表条目。分区表定义了后面数据段的用途

   分区表后面的数据都属于用户数据,用来存放用户的代码和数据。该部分具体包含什么功能区,由分区表决定。可能包含以下内容:

  • Factory: 属于代码区域(app)。存放的是从串口下载来的固件程序。
  • OTA_0-15:属于代码区域(app)。该区域存放的是通过隔空下载的方式存储的程序。使用OTA下载功能,flash中至少开辟两个OTA区域(比如OTA_0和OTA_1)。因为OTA下载的时候,不会修改factory区域中的代码,而是将代码在OTA_0和OTA_1之间交替烧写。在没有OTA区域的时候,程序会执行factory区域的代码,有了OTA之后,会使用OTA的代码,通过OTA data区域来确定从哪个区域加载代码。
  • NVS: 属于数据区域(data)。数据以键值对的方式在这段空间进行存储。如果启动了wifi功能,wifi的数据会存储在这个地方。用户也可自己存储键值对类型的数据
  • OTA data: 属于数据区域(data)。存放的是与OTA功能有关的数据,比如记录这次烧写的是哪个OTA,下次往哪个OTA烧写。
  • Phy data: 属于数据区域(data)。存放的是PHY初始化数据
  • Core dump:core dump分区用于查找系统崩溃时的软件错误,系统崩溃的时候会将调试信息写入到Flash中保存以便开发者对崩溃原因进行分析。
  • SPIFFS: 属于数据区域(data)。是一种文件系统。
  • Fatfs: 属于数据区域(data)。是一种文件系统。
  • user data: 属于数据区域(data)。是未被使用的区域,可以通过直接读写内存地址的方式进行访问和使用

1.3 esp32启动过程

  提到了flash区域,顺便说一下esp32的启动过程

  ESP32启动大概分为三个步骤:

  • ESP32内部ROM的引导程序启动,把spi flash是0x1000的bootloader程序加载到RAM中;
  • bootloader启动,读取分区表和主应用程序映像
  • 主程序运行,启动第二个CPU和RTOS程序。

2. 分区表

2.1 分区表的组成

  前文已经提到,分区表主要的作用是用来划分剩余flash空间的功能和大小的。

  分区表在0x8000的位置被烧写,最大长度为0xC00字节,最多能把flash分为95段。分区表数据后还保存着该表的 MD5 校验和,用于验证分区表的完整性。此外,如果芯片使能了安全启动功能,则该分区表后还会保存签名信息。

  在esp32中,分区表是以bin类型的二进制文件进行烧写的。如果想读取这个分区表,可以通过一些方法把bin转换为csv进行阅读,具体方法后文会讲。

2.2 分区表的定义

  分区表含有六个字段。包括Name,Type,SubType、Offset、Size、Flags,如默认的分区表定义如下:

# 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,
2.2.1 Name字段

  Name 字段可以是任何有意义的名称,但不能超过16个字符(之后的内容将被截断)。该字段对 ESP32 并不是特别重要。

2.2.2 Type字段

  Type 字段可以指定为 app (0x00)(代码类型) 或者 data (0x01)(数据类型),也可以直接使用数字0-254(或者十六进制 0x00-0xFE)。注意,0x00-0x3F 不得使用(预留给 esp-idf 的核心功能)。

  如果应用程序需要以ESP-IDF尚未支持的格式存储数据,请在0x40-0xFE内添加一个自定义分区类型。

2.2.3 SubType字段

  SubType 字段长度为 8 bit,内容与具体分区 Type 有关。目前,esp-idf 仅仅规定了 “app” 和 “data” 两种分区类型的子类型含义。

Name

Type

SubType

any value

app

factory

ota_0-15

any value

data

ota data

phy

nvs

spiffs


  当Type定义为app的时候,SubType可以选择factory(0x00)、0ta_0(0x10)…ota_15(0x1F)或test(0x20):

  • factory:是默认的 app 分区。启动加载器将默认加载该应用程序。但如果存在类型为 data/ota 分区,则启动加载器将加载 data/ota 分区中的数据,进而判断启动哪个 OTA 镜像文件。OTA 升级永远都不会更新 factory 分区中的内容.如果您希望在 OTA 项目中预留更多 flash,可以删除 factory 分区,转而使用 ota_0 分区。
  • ota_0 (0x10) … ota_15(0x1F)=为 OTA 应用程序分区,启动加载器将根据 OTA 数据分区中的数据来决定加载哪个 OTA 应用程序分区中的程序。在使用 OTA 功能时,应用程序应至少拥有 2 个 OTA 应用程序分区(ota_0 和 ota_1)
  • test (0x20) 为预留的子类型,用于工厂测试流程。如果没有其他有效 app 分区,test 将作为备选启动分区使用。也可以配置启动加载器在每次启动时读取 GPIO,如果 GPIO 被拉低则启动该分区。

  当Type定义为data的时候,SubType可以选择ota(0x00),phy(0x01),nvs(0x02),nvs_keys(0x04)等

  • ota: 即 OTA 数据分区 ,用于存储当前所选的 OTA 应用程序的信息。这个分区的大小需要设定为 0x2000。
  • phy:存放PHY初始化数据。默认PHY分区不启用,而是把PHY初始化数据编译到应用程序中。如果要从此分区加载PHY初始化数据,请打开项目配置菜单(idf.py menuconfig),并且使能CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION 选项。此时,您还需要手动将 phy 初始化数据烧至设备flash (esp-idf 编译系统并不会自动完成该操作)。
  • nvs :是专门给 非易失性存储 (NVS) API 使用的分区。用于存储phy校准数据、wifi数据和自定义数据。NVS分区至少0x3000字节,如果要存储大量数据,建议增加。默认是0x6000字节
  • nvs_key: NVS秘钥分区。用于存储加密秘钥。此分区至少4096字节
  • 文件系统:可以存放fatspiffs等文件系统

2.2.4 offset和size

  偏移地址是功能分区的起始地址。这个地址要求与0x10000(64k)对齐。

  如果偏移字段留空,gen_esp32part.py 工具会自动计算得到一个满足对齐要求的偏移地址。

  如果 app 分区的偏移地址没有与 0x10000 (64K) 对齐,则该工具会报错。

  app 分区的大小和偏移地址可以采用十进制数、以 0x 为前缀的十六进制数,且支持 K 或 M 的倍数单位(分别代表 1024 和 1024*1024 字节)

2.2.5 flags

  当前仅支持 encrypted 标记。如果 Flags 字段设置为 encrypted,且已启用 Flash 加密 功能,则该分区将会被加密。

2.3 系统分区表的查看

  分区表以二进制文件bin类型的方式进行存储,如果我们想要查看,就要把bin文件转换为csv文件。转换方法如下:

  • 打开esp-idf\components\partition_table 路径,找到gen_esp32part.py

esp32外置flash的大小 esp32 flash大小_嵌入式_02

  • 用命令行输入code. 的方法用vscode打开某个项目,输入命令,即可把当前项目中的分区表变成csv查看。注意,python脚本路径,输入文件和输出文件路径需要自己定义修改,这里只是个例子

python C:\Software\Esp\espidf\components\partition_table\gen_esp32part.py build\partition_table\partition-table.bin C:\Users\30311\Desktop\partition-table.csv

2.4 分区表的更换

  • 输入指令

idf.py menuuconfig

  • 在menuconfig中找到partition table,在此选项中即可进行分区表的更换
2.4.1 使用内置分区表

  前两个选择是内置分区表

Single factory app, no OTA

# 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,

Factory app, two OTA definitions

# ESP-IDF Partition Table
# Name,   Type, SubType, Offset,  Size, Flags
nvs,      data, nvs,     0x9000,  0x4000,
otadata,  data, ota,     0xd000,  0x2000,
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.4.2 使用自定义的分区表

  把自定义的分区表放在项目路径下,在这里吧名字输入进去即可。idf会自动把csv转换为bin文件

esp32外置flash的大小 esp32 flash大小_分区表_03

3. 参考资料

[1] ESP32分区表图解

[2] 玩转ESP32(3):partitiontable使用

[3] 分区表