A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32/api-guides/partition-tables.html below:

Website Navigation


分区表 - ESP32 - — ESP-IDF 编程指南 latest 文档

分区表

[English]

概述

每片 ESP32 的 flash 可以包含多个应用程序,以及多种不同类型的数据(例如校准数据、文件系统数据、参数存储数据等)。因此,我们在 flash 的 默认偏移地址 0x8000 处烧写一张分区表。

分区表的长度为 0xC00 字节,最多可以保存 95 条分区表条目。MD5 校验和附加在分区表之后,用于在运行时验证分区表的完整性。分区表占据了整个 flash 扇区,大小为 0x1000 (4 KB)。因此,它后面的任何分区至少需要位于(默认偏移地址) + 0x1000 处。

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

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

在以上两种选项中,出厂应用程序均将被烧录至 flash 的 0x10000 偏移地址处。这时,运行 idf.py partition-table,即可以打印当前使用分区表的信息摘要。

内置分区表

以下是 "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,
创建自定义分区表

如果在 menuconfig 中选择了 "Custom partition table CSV",则还需要输入该分区表的 CSV 文件在项目中的路径。CSV 文件可以根据需要,描述任意数量的分区信息。

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

# 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,    ,         1M
ota_1,    app,  ota_1,    ,         1M
nvs_key,  data, nvs_keys, ,        0x1000

下面是一个包含引导加载程序和分区表分区的 CSV 分区表示例:

# ESP-IDF Partition Table
# Name,           Type,            SubType,  Offset,  Size,     Flags
bootloader,       bootloader,      primary,  N/A,     N/A,
partition_table,  partition_table, primary,  N/A,     N/A,
nvs,              data,            nvs,      ,        0x6000,
phy_init,         data,            phy,      ,        0x1000,
factory,          app,             factory,  ,        1M,
recoveryBloader,  bootloader,      recovery, N/A,     N/A,

gen_esp32part.py 工具将根据所选的 Kconfig 选项将每个 N/A 替换为适当的值:引导加载程序的偏移地址为 0x1000,分区表的偏移地址见 CONFIG_PARTITION_TABLE_OFFSET。

Name 字段

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

Type 字段

Type 字段可以指定为名称或数字 0~254(或者十六进制 0x00-0xFE)。注意,不得使用预留给 ESP-IDF 核心功能的 0x00-0x3F。

关于 app 和 data 分区的枚举定义,请参考 esp_partition_type_t。

如果用 C++ 编写,那么指定一个应用程序定义的分区类型,需要在 esp_partition_type_t 中使用整数,从而与 分区 API 一起使用。例如:

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 两种分区类型的子类型含义。

参考 esp_partition_subtype_t,以了解 ESP-IDF 定义的全部子类型列表,包括:

额外分区 SubType 字段

组件可以通过设置 EXTRA_PARTITION_SUBTYPES 属性来定义额外的分区子类型。 EXTRA_PARTITION_SUBTYPES 是一个 CMake 列表,其中的每个条目由字符串组成,以逗号为分隔,格式为 <type>, <subtype>, <value>。构建系统通过该属性会自动添加额外的子类型,并在 esp_partition_subtype_t 中插入名为 ESP_PARTITION_SUBTYPE_<type>_<subtype> 的字段。项目可以使用这个子类型来定义分区表 CSV 文件中的分区,并使用 esp_partition_subtype_t 中的新字段。

偏移地址 (Offset) 和大小 (Size) 字段

备注

如果你希望分区表中各个分区的偏移地址是相对于分区表本身的位置 (由 CONFIG_PARTITION_TABLE_OFFSET 指定),请将分区表(CSV 文件)中所有分区的偏移字段都留空。这样,在更改分区表的偏移地址时,留空的分区偏移地址会自动做出相应的改变。而如果你在某个分区采用了固定的偏移值,就可能与分区表发生冲突,导致报错。

Flags 字段

目前支持 encrypted 和 readonly 标记:

备注

无论是否设置 Flags 字段,当启用了 flash 加密 功能时,以下类型的分区将始终保持加密状态。

备注

在任何写入模式下 (w、w+、a、a+、r+),尝试通过 C 文件 I/O API 打开文件 (fopen) 的操作都将失败并返回 NULL。除 O_RDONLY 外,open 与任何标志一同使用都将失败并返回 -1,全局变量 errno 也将设置为 EROFS。上述情况同样适用于通过其他 POSIX 系统调用函数执行写入或擦除的操作。在只读分区上,以读写模式打开 NVS 的句柄将失败并返回 ESP_ERR_NOT_ALLOWED 错误代码,使用 esp_partition 或 spi_flash 等较低级别的 API 进行写入操作也将返回 ESP_ERR_NOT_ALLOWED 错误代码。

可以使用冒号连接不同的标记,来同时指定多个标记,如 encrypted:readonly。

生成二进制分区表

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

如果你在项目配置菜单(idf.py menuconfig)中设置了分区表 CSV 文件的名称,然后构建项目或执行 idf.py partition-table。这时,转换将在编译过程中自动完成。

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

python gen_esp32part.py input_partitions.csv binary_partitions.bin

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

python gen_esp32part.py binary_partitions.bin input_partitions.csv

在标准输出 (stdout) 上,打印二进制分区表的内容(运行 idf.py partition-table 时展示的信息摘要也是这样生成的):

python gen_esp32part.py binary_partitions.bin
分区大小检查

ESP-IDF 构建系统将自动检查生成的二进制文件大小与可用的分区大小是否匹配,如果二进制文件太大,则会构建失败并报错。

目前会对以下二进制文件进行检查:

备注

即使分区大小检查返回错误并导致构建失败,仍然会生成可以烧录的二进制文件(它们对于可用空间来说过大,因此无法正常工作)。

MD5 校验和

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

用户可通过 gen_esp32part.py 的 --disable-md5sum 选项或者 CONFIG_PARTITION_TABLE_MD5 选项关闭 MD5 校验。对于 ESP-IDF v3.1 版本前的引导加载程序,因为它不支持 MD5 校验,所以无法正常启动并报错 invalid magic number 0xebeb,此时用户可以使用此选项关闭 MD5 校验。

烧写分区表

在执行 idf.py partition-table 命令时,手动烧写分区表的命令也将打印在终端上。

备注

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

分区工具 (parttool.py)

partition_table 组件中有分区工具 parttool.py,可以在目标设备上完成分区相关操作。该工具有如下用途:

用户若想通过编程方式完成相关操作,可从另一个 Python 脚本导入并使用分区工具,或者从 Shell 脚本调用分区工具。前者可使用工具的 Python API,后者可使用命令行界面。

Python API

首先请确保已导入 parttool 模块。

import sys
import os

idf_path = os.environ["IDF_PATH"]  # 从环境中获取 IDF_PATH 的值
parttool_dir = os.path.join(idf_path, "components", "partition_table")  # parttool.py 位于 $IDF_PATH/components/partition_table 下

sys.path.append(parttool_dir)  # 使能 Python 寻找 parttool 模块
from parttool import *  # 导入 parttool 模块内的所有名称

要使用分区工具的 Python API,第一步是创建 ParttoolTarget:

# 创建 parttool.py 的目标设备,并将目标设备连接到串行端口 /dev/ttyUSB1
target = ParttoolTarget("/dev/ttyUSB1")

现在,可使用创建的 ParttoolTarget 在目标设备上完成操作:

# 擦除名为 'storage' 的分区
target.erase_partition(PartitionName("storage"))

# 读取类型为 'data'、子类型为 'spiffs' 的分区,保存至文件 'spiffs.bin'
target.read_partition(PartitionType("data", "spiffs"), "spiffs.bin")

# 将 'factory.bin' 文件的内容写至 'factory' 分区
target.write_partition(PartitionName("factory"), "factory.bin")

# 打印默认启动分区的大小
storage = target.get_partition_info(PARTITION_BOOT_DEFAULT)
print(storage.size)

使用 PartitionName、PartitionType 或 PARTITION_BOOT_DEFAULT 指定要操作的分区。顾名思义,这三个参数可以指向拥有特定名称的分区、特定类型和子类型的分区或默认启动分区。

更多关于 Python API 的信息,请查看分区工具的代码注释。

命令行界面

parttool.py 的命令行界面具有如下结构:

parttool.py [command-args] [subcommand] [subcommand-args]

- command-args - 执行主命令 (parttool.py) 所需的实际参数,多与目标设备有关
- subcommand - 要执行的操作
- subcommand-args - 所选操作的实际参数
# 擦除名为 'storage' 的分区
parttool.py --port "/dev/ttyUSB1" erase_partition --partition-name=storage

# 读取类型为 'data'、子类型为 'spiffs' 的分区,保存到 'spiffs.bin' 文件
parttool.py --port "/dev/ttyUSB1" read_partition --partition-type=data --partition-subtype=spiffs --output "spiffs.bin"

# 将 'factory.bin' 文件中的内容写入到 'factory' 分区
parttool.py --port "/dev/ttyUSB1" write_partition --partition-name=factory --input "factory.bin"

# 打印默认启动分区的大小
parttool.py --port "/dev/ttyUSB1" get_partition_info --partition-boot-default --info size

备注

如果设备启用了 Flash Encryption 或 Secure Boot,尝试使用修改 flash 内容的命令(如 erase_partition 或 write_partition)会导致错误。这是因为 esptool.py 的擦除命令会在写入之前先被调用。这个“错误”实际上是一个用来防止设备变砖的安全措施。

A fatal error occurred: Active security features detected, erasing flash is disabled as a safety measure. Use --force to override, please use with caution, otherwise it may brick your device!

要解决此问题,需在运行 esptool.py 时使用 --force 参数。具体而言,parttool.py 提供了 --esptool-erase-args 参数,用来将 --force 参数传递给 esptool.py。

# 擦除名为 'storage' 的分区
# 如果启用了 Flash Encryption 或 Secure Boot,则添加 "--esptool-erase-args=force"
parttool.py --port "/dev/ttyUSB1" --esptool-erase-args=force erase_partition --partition-name=storage

# 将名为 'factory.bin' 的文件内容写入 'factory' 分区
# 如果启用了 Flash Encryption 或 Secure Boot,则添加 "--esptool-erase-args=force"
parttool.py --port "/dev/ttyUSB1" --esptool-erase-args=force write_partition --partition-name=factory --input "factory.bin"

更多信息可用 --help 指令查看:

# 显示可用的子命令和主命令描述
parttool.py --help

# 显示子命令的描述
parttool.py [subcommand] --help

RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4