|
|
@@ -5,11 +5,9 @@
|
|
|
概述
|
|
|
----
|
|
|
|
|
|
-每片 {IDF_TARGET_NAME} 的 flash 可以包含多个应用程序,以及多种不同类型的数据(例如校准数据、文件系统数据、参数存储器数据等)。因此,我们需要引入分区表的概念。
|
|
|
+每片 {IDF_TARGET_NAME} 的 flash 可以包含多个应用程序,以及多种不同类型的数据(例如校准数据、文件系统数据、参数存储数据等)。因此,我们在 flash 的 :ref:`默认偏移地址 <CONFIG_PARTITION_TABLE_OFFSET>` 0x8000 处烧写一张分区表。
|
|
|
|
|
|
-.. only:: esp32
|
|
|
-
|
|
|
- 具体来说,{IDF_TARGET_NAME} 在 flash 的 :ref:`默认偏移地址 <CONFIG_PARTITION_TABLE_OFFSET>` 0x8000 处烧写一张分区表。该分区表的长度为 0xC00 字节(最多可以保存 95 条分区表条目)。分区表数据后还保存着该表的 MD5 校验和,用于验证分区表的完整性。此外,如果芯片使能了 :doc:`安全启动 </security/secure-boot-v2>` 功能,则该分区表后还会保存签名信息。
|
|
|
+分区表的长度为 0xC00 字节(最多可以保存 95 条分区表条目)。分区表数据后还保存着该表的 MD5 校验和,用于验证分区表的完整性。此外,如果芯片使能了 :doc:`安全启动 </security/secure-boot-v2>` 功能,则该分区表后还会保存签名信息。
|
|
|
|
|
|
分区表中的每个条目都包括以下几个部分:Name(标签)、Type(app、data 等)、SubType 以及在 flash 中的偏移量(分区的加载地址)。
|
|
|
|
|
|
@@ -23,8 +21,7 @@
|
|
|
内置分区表
|
|
|
------------
|
|
|
|
|
|
-以下是 "Single factory app, no OTA" 选项的分区表信息摘要:
|
|
|
-
|
|
|
+以下是 "Single factory app, no OTA" 选项的分区表信息摘要::
|
|
|
|
|
|
# ESP-IDF Partition Table
|
|
|
# Name, Type, SubType, Offset, Size, Flags
|
|
|
@@ -32,19 +29,19 @@
|
|
|
phy_init, data, phy, 0xf000, 0x1000,
|
|
|
factory, app, factory, 0x10000, 1M,
|
|
|
|
|
|
-- flash 的 0x10000 (64KB) 偏移地址处存放一个标记为 "factory" 的二进制应用程序,且启动加载器将默认加载这个应用程序。
|
|
|
+- flash 的 0x10000 (64 KB) 偏移地址处存放一个标记为 "factory" 的二进制应用程序,且启动加载器将默认加载这个应用程序。
|
|
|
- 分区表中还定义了两个数据区域,分别用于存储 NVS 库专用分区和 PHY 初始化数据。
|
|
|
|
|
|
-以下是 "Factory app, two OTA definitions" 选项的分区表信息摘要:
|
|
|
+以下是 "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,
|
|
|
+ # 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,
|
|
|
|
|
|
- 分区表中定义了三个应用程序分区,这三个分区的类型都被设置为 “app”,但具体 app 类型不同。其中,位于 0x10000 偏移地址处的为出厂应用程序(factory),其余两个为 OTA 应用程序(ota_0,ota_1)。
|
|
|
- 新增了一个名为 “otadata” 的数据分区,用于保存 OTA 升级时需要的数据。启动加载器会查询该分区的数据,以判断该从哪个 OTA 应用程序分区加载程序。如果 “otadata” 分区为空,则会执行出厂程序。
|
|
|
@@ -54,7 +51,7 @@
|
|
|
|
|
|
如果在 ``menuconfig`` 中选择了 “Custom partition table CSV”,则还需要输入该分区表的 CSV 文件在项目中的路径。CSV 文件可以根据需要,描述任意数量的分区信息。
|
|
|
|
|
|
-CSV 文件的格式与上面摘要中打印的格式相同,但是在 CSV 文件中并非所有字段都是必需的。例如下面是一个自定义的 OTA 分区表的 CSV 文件:
|
|
|
+CSV 文件的格式与上面摘要中打印的格式相同,但是在 CSV 文件中并非所有字段都是必需的。例如下面是一个自定义的 OTA 分区表的 CSV 文件::
|
|
|
|
|
|
# Name, Type, SubType, Offset, Size, Flags
|
|
|
nvs, data, nvs, 0x9000, 0x4000
|
|
|
@@ -77,47 +74,61 @@ Name 字段可以是任何有意义的名称,但不能超过 16 个字符(
|
|
|
Type 字段
|
|
|
~~~~~~~~~
|
|
|
|
|
|
-Type 字段可以指定为 app (0) 或者 data (1),也可以直接使用数字 0-254(或者十六进制 0x00-0xFE)。注意,0x00-0x3F 不得使用(预留给 esp-idf 的核心功能)。
|
|
|
+Type 字段可以指定为 app (0x00) 或者 data (0x01),也可以直接使用数字 0-254(或者十六进制 0x00-0xFE)。注意,0x00-0x3F 不得使用(预留给 esp-idf 的核心功能)。
|
|
|
|
|
|
-如果您的应用程序需要保存数据,请在 0x40-0xFE 内添加一个自定义分区类型。
|
|
|
+如果您的应用程序需要以 ESP-IDF 尚未支持的格式存储数据,请在 0x40-0xFE 内添加一个自定义分区类型。
|
|
|
|
|
|
-注意,启动加载器将忽略 app (0) 和 data (1) 以外的其他分区类型。
|
|
|
+参考 :cpp:type:`esp_partition_type_t` 关于 ``app``和 ``data`` 分区的枚举定义。
|
|
|
|
|
|
+如果用 C++ 编写,那么指定一个应用程序定义的分区类型,需要在 :cpp:type:`esp_partition_type_t` 中使用整数,从而与 :ref:`分区 API<api-reference-partition-table>` 一起使用。例如::
|
|
|
+
|
|
|
+ static const esp_partition_type_t APP_PARTITION_TYPE_A = (esp_partition_type_t)0x40;
|
|
|
+
|
|
|
+注意,启动加载器将忽略 ``app`` (0x00) 和 ``data`` (0x01) 以外的其他分区类型。
|
|
|
|
|
|
SubType 字段
|
|
|
~~~~~~~~~~~~
|
|
|
|
|
|
-SubType 字段长度为 8 bit,内容与具体 Type 有关。目前,esp-idf 仅仅规定了 “app” 和 “data” 两种子类型。
|
|
|
+SubType 字段长度为 8 bit,内容与具体分区 Type 有关。目前,esp-idf 仅仅规定了 “app” 和 “data” 两种分区类型的子类型含义。
|
|
|
+
|
|
|
+参考 :cpp:type:`esp_partition_subtype_t`,以了解 ESP-IDF 定义的全部子类型列表,包括:
|
|
|
|
|
|
-* 当 Type 定义为 ``app`` 时,SubType 字段可以指定为 factory (0),ota_0 (0x10) ... ota_15 (0x1F) 或者 test (0x20)。
|
|
|
+* 当 Type 定义为 ``app`` 时,SubType 字段可以指定为 ``factory`` (0x00)、 ``ota_0`` (0x10) … ``ota_15`` (0x1F) 或者 ``test`` (0x20)。
|
|
|
|
|
|
- - factory (0) 是默认的 app 分区。启动加载器将默认加载该应用程序。但如果存在类型为 data/ota 分区,则启动加载器将加载 data/ota 分区中的数据,进而判断启动哪个 OTA 镜像文件。
|
|
|
+ - ``factory`` (0x00) 是默认的 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)。更多详细信息,请参考 :doc:`OTA 文档 </api-reference/system/ota>` 。
|
|
|
- - test (0x2) 为预留 app 子类型,用于工厂测试流程。如果没有其他有效 app 分区,test 将作为备选启动分区使用。也可以在每次启动时配置启动加载器读取 GPIO,如果 GPIO 被拉低则启动该分区。详细信息请查阅 :ref:`bootloader_boot_from_test_firmware`。
|
|
|
+ - ota_0 (0x10) … ota_15 (0x1F) 为 OTA 应用程序分区,启动加载器将根据 OTA 数据分区中的数据来决定加载哪个 OTA 应用程序分区中的程序。在使用 OTA 功能时,应用程序应至少拥有 2 个 OTA 应用程序分区(``ota_0`` 和 ``ota_1``)。更多详细信息,请参考 :doc:`OTA 文档 </api-reference/system/ota>` 。
|
|
|
+ - ``test`` (0x20) 为预留的子类型,用于工厂测试流程。如果没有其他有效 app 分区,test 将作为备选启动分区使用。也可以配置启动加载器在每次启动时读取 GPIO,如果 GPIO 被拉低则启动该分区。详细信息请查阅 :ref:`bootloader_boot_from_test_firmware`。
|
|
|
|
|
|
-* 当 Type 定义为 ``data`` 时,SubType 字段可以指定为 ota (0),phy (1),nvs (2) 或者 nvs_keys (4)。
|
|
|
+* 当 Type 定义为 ``data`` 时,SubType 字段可以指定为 ``ota`` (0x00)、``phy`` (0x01)、``nvs`` (0x02)、``nvs_keys`` (0x04) 或者其他组件特定的子类型(请参考 :cpp:type:`子类型枚举 <esp_partition_subtype_t>`).
|
|
|
|
|
|
- - ota (0) 即 :ref:`OTA 数据分区 <ota_data_partition>` ,用于存储当前所选的 OTA 应用程序的信息。这个分区的大小需要设定为 0x2000。更多详细信息,请参考 :doc:`OTA 文档 <../api-reference/system/ota>` 。
|
|
|
- - phy (1) 分区用于存放 PHY 初始化数据,从而保证可以为每个设备单独配置 PHY,而非必须采用固件中的统一 PHY 初始化数据。
|
|
|
+ - ``ota`` (0) 即 :ref:`OTA 数据分区 <ota_data_partition>` ,用于存储当前所选的 OTA 应用程序的信息。这个分区的大小需要设定为 0x2000。更多详细信息,请参考 :doc:`OTA 文档 <../api-reference/system/ota>` 。
|
|
|
+ - ``phy`` (1) 分区用于存放 PHY 初始化数据,从而保证可以为每个设备单独配置 PHY,而非必须采用固件中的统一 PHY 初始化数据。
|
|
|
|
|
|
- 默认配置下,phy 分区并不启用,而是直接将 phy 初始化数据编译至应用程序中,从而节省分区表空间(直接将此分区删掉)。
|
|
|
- 如果需要从此分区加载 phy 初始化数据,请打开项目配置菜单(``idf.py menuconfig``),并且使能 :ref:`CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION` 选项。此时,您还需要手动将 phy 初始化数据烧至设备 flash(esp-idf 编译系统并不会自动完成该操作)。
|
|
|
- - nvs (2) 是专门给 :doc:`非易失性存储 (NVS) API <../api-reference/storage/nvs_flash>` 使用的分区。
|
|
|
+ - ``nvs`` (2) 是专门给 :doc:`非易失性存储 (NVS) API <../api-reference/storage/nvs_flash>` 使用的分区。
|
|
|
|
|
|
- 用于存储每台设备的 PHY 校准数据(注意,并不是 PHY 初始化数据)。
|
|
|
- - 用于存储 Wi-Fi 数据(如果使用了 :cpp:func:`esp_wifi_set_storage(WIFI_STORAGE_FLASH) <esp_wifi_set_storage>` 初始化函数)。
|
|
|
+ - 用于存储 Wi-Fi 数据(如果使用了 :doc:`esp_wifi_set_storage(WIFI_STORAGE_FLASH) <../api-reference/network/esp_wifi>` 初始化函数)。
|
|
|
- NVS API 还可以用于其他应用程序数据。
|
|
|
- 强烈建议您应为 NVS 分区分配至少 0x3000 字节空间。
|
|
|
- 如果使用 NVS API 存储大量数据,请增加 NVS 分区的大小(默认是 0x6000 字节)。
|
|
|
- - nvs_keys (4) 是 NVS 秘钥分区。详细信息,请参考 :doc:`非易失性存储 (NVS) API <../api-reference/storage/nvs_flash>` 文档。
|
|
|
+ - ``nvs_keys`` (4) 是 NVS 秘钥分区。详细信息,请参考 :doc:`非易失性存储 (NVS) API <../api-reference/storage/nvs_flash>` 文档。
|
|
|
|
|
|
- 用于存储加密密钥(如果启用了 `NVS 加密` 功能)。
|
|
|
- 此分区应至少设定为 4096 字节。
|
|
|
|
|
|
-其它数据子类型已预留给 esp-idf 未来使用。
|
|
|
+ - ESP-IDF 还支持其它预定义的子类型用于数据存储,包括 :doc:`FAT 文件系统 </api-reference/storage/fatfs>` (:cpp:enumerator:`ESP_PARTITION_SUBTYPE_DATA_FAT`), :doc:`SPIFFS </api-reference/storage/spiffs>` (:cpp:enumerator:`ESP_PARTITION_SUBTYPE_DATA_SPIFFS`) 等。
|
|
|
+
|
|
|
+ 其它数据子类型已预留给 esp-idf 未来使用。
|
|
|
+
|
|
|
+* 如果分区类型是由应用程序定义的任意值(0x40-0xFE),那么 ``subtype`` 字段可以是由应用程序选择的任何值(0x00-0xFE)。
|
|
|
+
|
|
|
+请注意如果用 C++ 编写,应用程序定义的子类型值需要转换为 :cpp:type:`esp_partition_type_t`,从而与 :ref:`分区 API<api-reference-partition-table>` 一起使用。
|
|
|
|
|
|
Offset 和 Size 字段
|
|
|
~~~~~~~~~~~~~~~~~~~
|
|
|
@@ -133,7 +144,7 @@ app 分区的大小和偏移地址可以采用十进制数、以 0x 为前缀的
|
|
|
Flags 字段
|
|
|
~~~~~~~~~~
|
|
|
|
|
|
-当前仅支持 ``encrypted`` 标记。如果 Flags 字段设置为 ``encrypted``,且已启用 :doc:`Flash Encryption </security/flash-encryption>` 功能,则该分区将会被加密。
|
|
|
+当前仅支持 ``encrypted`` 标记。如果 Flags 字段设置为 ``encrypted``,且已启用 :doc:`Flash 加密 </security/flash-encryption>` 功能,则该分区将会被加密。
|
|
|
|
|
|
.. note::
|
|
|
|
|
|
@@ -142,19 +153,19 @@ Flags 字段
|
|
|
生成二进制分区表
|
|
|
----------------
|
|
|
|
|
|
-烧写到 ESP32 中的分区表采用二进制格式,而不是 CSV 文件本身。此时,:component_file:`partition_table/gen_esp32part.py` 工具可以实现 CSV 和二进制文件之间的转换。
|
|
|
+烧写到 {IDF_TARGET_NAME} 中的分区表采用二进制格式,而不是 CSV 文件本身。此时,:component_file:`partition_table/gen_esp32part.py` 工具可以实现 CSV 和二进制文件之间的转换。
|
|
|
|
|
|
如果您在项目配置菜单(``idf.py menuconfig``)中设置了分区表 CSV 文件的名称,然后构建项目或执行 ``idf.py partition_table``。这时,转换将在编译过程中自动完成。
|
|
|
|
|
|
-手动将 CSV 文件转换为二进制文件:
|
|
|
+手动将 CSV 文件转换为二进制文件::
|
|
|
|
|
|
python gen_esp32part.py input_partitions.csv binary_partitions.bin
|
|
|
|
|
|
-手动将二进制文件转换为 CSV 文件:
|
|
|
+手动将二进制文件转换为 CSV 文件::
|
|
|
|
|
|
python gen_esp32part.py binary_partitions.bin input_partitions.csv
|
|
|
|
|
|
-在标准输出(stdout)上,打印二进制分区表的内容(在运行 ``idf.py partition_table`` 时,我们正是这样打印上文展示的信息摘要的):
|
|
|
+在标准输出(stdout)上,打印二进制分区表的内容(运行 ``idf.py partition_table`` 时展示的信息摘要也是这样生成的)::
|
|
|
|
|
|
python gen_esp32part.py binary_partitions.bin
|
|
|
|
|
|
@@ -163,7 +174,7 @@ MD5 校验和
|
|
|
|
|
|
二进制格式的分区表中含有一个 MD5 校验和。这个 MD5 校验和是根据分区表内容计算的,可在设备启动阶段,用于验证分区表的完整性。
|
|
|
|
|
|
-注意,一些版本较老的启动加载器无法支持 MD5 校验,如果发现 MD5 校验和则将报错 ``invalid magic number 0xebeb``。此时,用户可通过 ``gen_esp32part.py`` 的 ``--disable-md5sum`` 选项或者 ``menuconfig`` 的 :ref:`CONFIG_PARTITION_TABLE_MD5` 选项关闭 MD5 校验。
|
|
|
+注意,一些版本较老的启动加载器无法支持 MD5 校验,如果发现 MD5 校验和则将报错 ``invalid magic number 0xebeb``。此时,用户可通过 ``gen_esp32part.py`` 的 ``--disable-md5sum`` 选项或者 :ref:`CONFIG_PARTITION_TABLE_MD5` 选项关闭 MD5 校验。
|
|
|
|
|
|
烧写分区表
|
|
|
----------
|
|
|
@@ -175,7 +186,7 @@ MD5 校验和
|
|
|
|
|
|
.. note::
|
|
|
|
|
|
- 分区表的更新并不会擦除根据之前分区表存储的数据。此时,您可以使用 ``idf.py erase_flash`` 命令或者 ``esptool.py erase_flash`` 命令来擦除 flash 中的所有内容。
|
|
|
+ 分区表的更新并不会擦除根据旧分区表存储的数据。此时,您可以使用 ``idf.py erase_flash`` 命令或者 ``esptool.py erase_flash`` 命令来擦除 flash 中的所有内容。
|
|
|
|
|
|
|
|
|
分区工具 (parttool.py)
|
|
|
@@ -186,7 +197,7 @@ MD5 校验和
|
|
|
- 读取分区,将内容存储到文件中 (read_partition)
|
|
|
- 将文件中的内容写至分区 (write_partition)
|
|
|
- 擦除分区 (erase_partition)
|
|
|
- - 检索特定分区的偏移和大小等信息 (get_partition_info)
|
|
|
+ - 检索特定分区的名称、偏移、大小和 flag(“加密”) 标志等信息 (get_partition_info)
|
|
|
|
|
|
用户若想通过编程方式完成相关操作,可从另一个 Python 脚本导入并使用分区工具,或者从 Shell 脚本调用分区工具。前者可使用工具的 Python API,后者可使用命令行界面。
|
|
|
|
|
|
@@ -271,6 +282,4 @@ Python API
|
|
|
# 显示子命令的描述
|
|
|
parttool.py [subcommand] --help
|
|
|
|
|
|
-
|
|
|
.. _secure boot: security/secure-boot-v1.rst
|
|
|
-
|