ESP8266

ESP8266 分区表介绍

来源:这里

概述
每片 ESP8266 的 Flash 可以包含多个应用程序以及多种不同类型的数据(如校准数据、文件系统、参数存储等)。因此,需要在 Flash 的 0x8000(默认偏移地址)处烧写一张分区表,分区表的长度为 0xC00(即 3 KB,最多可以保存 95 条分区表条目)。分区表数据后还保存着此表的 MD5 校验和,用于验证分区表的完整性。此外,如果芯片使能了安全启动功能,则分区表后还会保存签名信息

分区表中的每个条目都包括以下几个部分:Name(标签)、Type(app、data 等)、SubType 以及在 Flash 中的偏移量(分区的加载地址)

在使用分区表时,最简单的方法就是 make menuconfig(项目配置菜单),并在 CONFIG_PARTITION_TABLE_TYPE 下选择一个预定义的分区表:

“Single factory app, no OTA”
“Factory app, two OTA definitions”
以上两种选项,出厂应用程序均将被烧录至 Flash 的 0x10000 处。此时,运行 make partition_table ,即可打印当前使用分区表的信息摘要

内置分区表
以下为 “Single factory app, no OTA” 选项的分区表信息摘要:

# Espressif ESP8266 Partition Table
# Name,   Type, SubType, Offset,  Size
nvs,      data, nvs,     0x9000,  0x6000
phy_init, data, phy,     0xf000,  0x1000
factory,  app,  factory, 0x10000, 0xF0000
 

Flash 的 0x10000 处存放一个标记为 factory 的二进制应用程序,且 bootloader(启动加载器)将默认加载这个应用程序;
分区表中还定义了两个数据区域,分别用于存储 NVS 库专用分区和 PHY 初始化数据;
以下为 “Factory app, two OTA definitions” 选项的分区表信息摘要:

# Espressif ESP8266 Partition Table
# Name,   Type, SubType, Offset,   Size
nvs,      data, nvs,     0x9000,   0x4000
otadata,  data, ota,     0xd000,   0x2000
phy_init, data, phy,     0xf000,   0x1000
ota_0,    0,    ota_0,   0x10000,  0xF0000
ota_1,    0,    ota_1,   0x110000, 0xF0000
 

分区表中定义了两个应用程序分区,分区的类型都被设置为 0 (app)。其中,ota_0 位于 0x10000 处,ota_1 位于 0x110000 处;
新增了一个名为 otadata 的数据分区,用于保存 OTA 升级时需要的数据。bootloader 会查询此分区的数据,以判断应从哪个 OTA 应用程序分区加载程序。如果 otadata 分区为空,则默认执行 ota_0;
创建自定义分区表
如果在 menuconfig 中选择了 “Custom partition table CSV”,则还需输入分区表的 CSV 文件名(在项目文件夹中)。CSV 文件可以根据需要,描述任意数量的分区信息

CSV 文件的格式与上述摘要中打印的格式相同,但在 CSV 文件中并非所有字段都是必需的。如以下是一个自定义的 OTA 分区表的 CSV 文件:

# 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,  0xF0000
ota_1,    app,  ota_1,   0x110000, 0xF0000
 

字段之间的空格会被忽略,任何以 # 开头的行(注释)也会被忽略;
CSV 文件中的每个非注释行均为一个分区定义;
只需提供第一个分区的 Offset 字段,其余分区的 Offset 字段可以为空。gen_esp32part.py 工具会根据前一分区的 Offset 字段填充其余分区;
Name 字段
Name 字段可以是任何有意义的名称,但不能超过 16 个字符(之后的内容将被截断)。Name 字段对 ESP8266 并不是特别重要

Type 字段
Type 字段可以指定为 app (0) 或 data (1),也可以直接使用数字 0-254(或十六进制 0x00-0xFE)。注意,0x00-0x3F 不得使用(预留给 ESP8266_RTOS_SDK 的核心功能)

如果应用程序需要保存数据,则需要在 0x40-0xFE 内添加一个自定义分区类型

注意,bootloader 将忽略 app (0) 和 data (1) 以外的其他分区类型

SubType 字段
SubType 字段长度为 8 bit,内容与具体 Type 有关

目前,ESP8266_RTOS_SDK 仅仅规定了 app 和 data 的 SubType 字段

App Subtypes
当 Type 定义为 app 时,SubType 字段可以指定为 ota_0 (0x10), ota_0 (0x11) … ota_15 (0x1F) 或 test (0x20)

ota_0 (0x10) 是默认的 app 分区。bootloader 将默认加载 ota_0,但如果存在类型为 data/ota 的分区,则 bootloader 将加载 data/ota 分区中的数据,进而判断启动哪个 OTA 镜像文件
ota_0 (0x10) … ota_15 (0x1F) 为 OTA 应用程序分区。在使用 OTA 功能时,应用程序应至少拥有 2 个 OTA 应用程序分区(ota_0 和 ota_1)
Data Subtypes
当 Type 定义为 data 时,SubType 字段可以指定为 ota (0),phy (1),nvs (2)

ota (0) 即 OTA 数据分区 ,用于存储当前所选的 OTA 应用程序的信息。这个分区的大小应设定为 0x2000 (8 KB);
phy (1) 分区用于存放 PHY 初始化数据,从而保证可以为每个设备单独配置 PHY,而非必须采用固件中的统一 PHY 初始化数据:
默认配置下,phy 分区并不启用,而是直接将 phy 初始化数据编译至应用程序中,从而节省分区表空间(直接将此分区删掉);
如果需要从此分区加载 phy 初始化数据,make menuconfig 并使能 CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION 选项。此时,还需要手动将 phy 初始化数据烧至设备 flash(ESP8266_RTOS_SDK 编译系统并不会自动完成此操作);
nvs (2) 是专门给非易失性存储 (NVS) API 使用的分区:
NVS 用于存储每台设备的 PHY 校准数据(不是 PHY 初始化数据);
NVS 用于存储 Wi-Fi 数据(如果使用了 esp_wifi_set_storage(WIFI_STORAGE_FLASH) 初始化函数);
NVS API 还可用于其他应用程序数据;
强烈建议在项目中包含一个至少 0x3000 (12 KB) 的 NVS 分区;
如果使用 NVS API 存储大量数据,则需增加 NVS 分区的大小(默认为 0x6000 (24 KB));
其它数据子类型预留给 ESP8266_RTOS_SDK 未来使用

Offset 和 Size 字段
注意,app 分区必须位于一个完整的 1 MB 分区内。否则,应用程序将崩溃

固件的起始地址默认配置为 0x10000,如果需要改变固件的起始地址:

配置如下路径中的数值: menu -> partition table -> select “Custom partition table CSV” -> (0x10000) Factory app partition offset;
配置分区表的 CSV 文件中 ota_1 offset 字段为如上数值,ota_1 offset 字段为镜像数值(ota_2 = ota_1 + 0x100000)
需要输入一个对齐的偏移字段,否则工具会报错;
不要将偏移字段留空,这种情况下,工具会自动对齐 app 分区,可能导致 app 分区重叠。这意味着,app 分区会超出一个完整的 1 MB 分区;
Offset 和 Size 字段可以采用十进制数,以 0x 为前缀的十六进制数或 K 或 M 的倍数(即 1024 B 和 1024*1024 B)

生成二进制分区表
烧写到 ESP8266 中的分区表采用二进制格式,而不是 CSV 文件本身。此时,partition_table/gen_esp32part.py 工具可以实现 CSV 和二进制文件之间的转换

如果您在 make menuconfig 中设置了分区表 CSV 文件名,然后执行 make partition_table,转换将在编译过程中自动完成

手动将 CSV 文件转换为二进制文件:

python gen_esp32part.py --verify input_partitions.csv binary_partitions.bin
手动将二进制文件转换为 CSV 文件:

python gen_esp32part.py --verify binary_partitions.bin input_partitions.csv
在标准输出(stdout)上,打印二进制分区表的内容(在运行 make partition_table 时,也是这样打印信息摘要的):

python gen_esp32part.py binary_partitions.bin
gen_esp32part.py 带了一个可选参数 --verify,这将在转换过程中校验分区表(如检查重叠分区,未对齐分区等)

烧写分区表
make partition_table-flash :使用 esptool.py 工具烧写分区表;
make flash :烧写所有内容,包括分区表;
在执行 make partition_table 命令时,手动烧写分区表的命令也将打印在终端上

注意,分区表的更新并不会擦除根据旧分区表存储的数据。此时,可以使用 make erase_flash 或 esptool.py erase_flash 命令来擦除 Flash 中的所有内容