ESP32学习四-自定义分区表

1、简介

        ESP32-WROOM-32集成了4MB SPI FLASH。对应的,也会对这4MB FLAHS进行分区处理。在编译esp32程序时,通过make menuconfig -> Partition Table可以设置三种分区。

  •         工厂程序(无OTA分区)
  •         工厂程序(双OTA分区)
  •         用于自定义分区

         对于不同的模式,分区情况也不同。

二、无OTA分区

        通常无OTA分区,分区比较简单,其中并不会划分OTA的区域出来,那么久有更多的空间空余出来。

         

# Espressif ESP32 Partition Table
    Name,    Type,    SubType,    Offset,    Size, Flags
    nvs,     data,    nvs,        0x9000,    24K,
    phy_init,data,    phy,        0xf000,    4K,
    factory, app,    factory,     0x10000,   1M,

三、双OTA分区

        

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

 四、自定义分区

        该分区就根据用户自定义来划分。

        1.先拷贝一个.csv文件到工程的根目录下。文件名可自定义,建议与工程名保持一样

$ tree

.
├── main
│   ├── CMakeLists.txt
│   └── Hello.cpp
├── CMakeLists.txt
└── 工程名.csv	  #这个文件

        2.在终端输入make menuconfig。然后选择partition Table

         3.修改链接CSV链接名。

         将名字修改与拷贝到根目录下的.csv文件同名。选择“OK”。

         4.选择分区表类型为自定义。

        5.退出保存。

 

         6.修改csv文件内容为自定义分区

# Espressif ESP32 Partition Table
# Name, Type, SubType, Offset, Size, Flags
nvs,      data, nvs,     0x9000,  0x4000
otadata,  data, ota,     0xd000,  0x2000
phy_init, data, phy,     0xf000,  0x1000
fw1, app,  ota_0, 	 0x10000, 0xF0000
fw2, app,  ota_1,	 0x100000,0xF0000

        7.重新编译

五、自定义分区表详解

        如果在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文件中的每个非注释行均为一个分区定义

        每个分区的Offset字段可以为空gen_esp32part.py工具会从分区表位置的后面开始自动计算并填充该分区的偏移地址,同时确保每个分区的偏移地址正确对齐。

        

        Name 字段

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

        Type 字段

        Type字段可以指定为app(0x00)或者data(0x01),也可以直接使用数字0-254(或0x00-0xFE)。

        注:0x00-0x3F不得使用预留给esp-idf的核心功能)。

        如果应用程序需要以ESP-IDF尚未支持的格式存储数据,请在0x40-0xFE内添加一个自定义分区类型。(可以参考esp_partition_type_t,关于app和data分区的枚举定义)。

        SubType字段

        SubType字段长度为8bit,内容与具体分区Type有关。目前,esp-idf仅仅规定了“app”“data”两种分区类型的子类型含义。(参考esp_partition_subtype_t,以了解ESP-IDF定义的全部子类型列表)。

        当Type定义为app时,SubType字段可以指定为factory(0x00)ota_0(0x10)....ota_15(0x1f)或者test(0x20)

        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)。

        test(0x20)为预留的子类型,用于工厂测试流程。如果没有其他有效app分区,test将作为备选启动分区使用。也可以配置启动加载器在每次启动时读取GPIO,如果GPIO被拉低则启动该分区。

        当Type定义为data时,SubType字段可以指定为ota(0x00)phy(0x01)nvs(0x02)nvs_keys(0x04)或者其他组件特定的子类型

        ota(0x00) 即OTA数据分区,用于存储当前所选的OTA应用程序的信息。这个分区的大小需要设定为0x2000

        phy(0x01) 分区用于存放PHY初始化数据,从而保证可以为每个设备单独配置PHY,而非必须采用固件中的统一PHY初始化数据。

  •                 默认配置下,phy分区并不启用,而是直接将phy初始化数据编译至应用程序中,从而节省分区表空间(直接将次分区删掉)
  •                 如果需要从次分区加载phy初始化数据,请打开项目配置菜单(idf.py menuconfig),并且使能Component config/PHY/Use a partition to store PHY init data选项。此时,还需要手动将phy初始化数据烧至设备flash(esp-idf编译系统并不会自动完成该操作)。

         nvs(0x02)是专门给非易失性存储(NVS)API使用的分区

  •                 用于存储每台设备的PHY校准数据(注意,并不是PHY初始化数据)。
  •                 用于存储WIFI数据(如果使用了esp_wifi_set_storage(WIFI_STORAGE_FLASH)初始化函数)。
  •                 NVS API还可以用于其他应用程序数据。
  •                 强烈建议应为NVS分区分配至少0x3000字节空间
  •                 如果使用NVS API存储大量数据,请增加NVS分区的大小(默认是0x6000字节)。

        nvs_keys(0x04)是NVS密钥分区

  •                 用于存储加密密钥(如果启用了NVS加密功能)
  •                 此分区应至少设定为4086字节

        ESP_IDF还支持其他预定义的子类型用于数据存储,包括 FAT 文件系统 (ESP_PARTITION_SUBTYPE_DATA_FAT), SPIFFS (ESP_PARTITION_SUBTYPE_DATA_SPIFFS) 等。

        如果分区类型是由应用程序定义的任意值(0x40-0xFE),那么subtype字段可以由应用程序选择的任何值(0x00-0xFE)

        Offset和Size字段

        若分区的偏移地址为空,则会紧跟着前一个分区之后开始;若为首个分区,则将紧跟着分区表开始

        app分区的偏移地址必须要与0x10000(64K)对齐,如果将偏移字段留空,gen_esp32part.py工具会自动计算得到一个满足对齐要求的偏移地址。如果app分区的偏移地址没有与0x10000(64K)对齐,则该工具会报错

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

        如果希望允许分区表中的分区采用任意起始偏移量,请将分区表中所有分区的偏移字段都留空。注意,此时,如果更改了分区表中任意分区的偏移地址,则其他分区的偏移地址也会跟着改变。这种情况下,如果之前还设定了某个分区采用固定偏移地址,则可能造成分区表冲突,从而导致报错。

        Flags字段

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

        注:app分区始终会被加密,不管Flags字段是否设置

   

六、自定义分区表代码实例

        针对自定义分区表的内容,可以参考如下代码进行操作:

        示例代码中,Type为0x40,Subtype为0x00的自定义分区。

int8_t test_custom_partition()
{
    const esp_partition_t *find_partition = NULL;
    find_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA,ESP_PARTITION_SUBTYPE_DATA_FAT,"fat");
    if(find_partition == NULL)
    {
        printf("[PARTITION]:find partition error!!!\r\n");
    }
    printf("fat partition address:0x%x\r\n",find_partition->address);

    uint8_t temp_data[1024] = {0};
    if(esp_partition_read(find_partition,0,temp_data,sizeof(temp_data)) != ESP_OK)
    {
        printf("fat partition read error\r\n");
        return;
    }
    printf("fat partition read success:%x%x%x%x%x\r\n",temp_data[0],temp_data[1],temp_data[2],temp_data[3],temp_data[4]);

    if(esp_partition_erase_range(find_partition,0,0x1000) != ESP_OK) //擦除必须4K对齐
    {
        printf("fat partition erase error\r\n");
        return;
    }

    printf("fat partition erase success\r\n");
    memset((void *)temp_data,0,sizeof(temp_data));

    uint8_t temp_w_data[6] = {0x31,0x32,0x33,0x34,0x35};

    if(esp_partition_write(find_partition,0,temp_w_data,strlen((void *)temp_w_data)) != ESP_OK)
    {
        printf("fat partition write error\r\n");
        return;
    }

    printf("fat partition write success\r\n");

    if(esp_partition_read(find_partition,0,temp_data,sizeof(temp_data)) != ESP_OK)
    {
        printf("fat partition read error\r\n");
        return;
    }
    printf("fat partition read success:%x%x%x%x%x\r\n",temp_data[0],temp_data[1],temp_data[2],temp_data[3],temp_data[4]);
}

        结果:

         读取到的fat地址与我们自定义的fat的位置是相同的,且读写正常。

 

七、如何查看分区表

        分清楚了上面三种分区表类型之后,那么问题来了。如何查看当前工程下的分区表。

        在简介中我们说过,可以通过make menuconfig指令来设置分区类型。那设置完之后,如何查看呢?有两种方式可以查看。

        1.通过idf.py build的编译打印信息来查看。

         2.通过软件,将分区表的bin文件转换成csv文件来查看。

        正如我们前面文章说过的,编译结束后,会在build/partition_table/文件夹下生成partition-table.bin文件。该文件中存储了分区表信息。而SDK中也提供了工具允许我们将这个bin文件转成cvs文件来阅读。可以通过esp-idf/components/partition_table/gen_esp32part.py工具来转换。

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

python gen_esp32part.py input_partitions.csv binary_partitions.bin

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

python gen_esp32part.py binary_partitions.bin input_partitions.csv

        转换后,我们就能在工程的partition_table文件夹下看到csv文件了。

        点击打开后,就能看到分区表情况了。

         

        官方参考文档:

分区表 - ESP32 - — ESP-IDF 编程指南 release-v5.0 文档

jichu@AO:~/esp32/lvgl_display$ idf.py build Executing action: all (aliases: build) Running ninja in directory /home/jichu/esp32/lvgl_display/build Executing "ninja all"... [1/1587] cd /home/jichu/esp32/lvgl_dis...esp-idf/tools/cmake/scripts/fail.cmake FAILED: esp-idf/partition_table/CMakeFiles/partition-table cd /home/jichu/esp32/lvgl_display/build/esp-idf/partition_table && /usr/bin/cmake -E echo "Partition table CSV /home/jichu/esp32/lvgl_display/partitions.csv does not exist." && /usr/bin/cmake -E echo "Either change partition table in menuconfig or create this input file." && /usr/bin/cmake -E remove /home/jichu/esp32/lvgl_display/build/esp-idf/partition_table/mkCpy.cmake && /usr/bin/cmake -E env "FAIL_MESSAGE=Failing the build (see errors on lines above)" /usr/bin/cmake -P /home/jichu/esp32/esp-idf/tools/cmake/scripts/fail.cmake Partition table CSV /home/jichu/esp32/lvgl_display/partitions.csv does not exist. Either change partition table in menuconfig or create this input file. CMake Error at /home/jichu/esp32/esp-idf/tools/cmake/scripts/fail.cmake:3 (message): Failing the build (see errors on lines above) [2/1587] Generating ../../partition_table/partition-table.bin FAILED: partition_table/partition-table.bin cd /home/jichu/esp32/lvgl_display/build/esp-idf/partition_table && /home/jichu/.espressif/python_env/idf5.2_py3.8_env/bin/python /home/jichu/esp32/esp-idf/components/partition_table/gen_esp32part.py -q --offset 0x8000 --flash-size 2MB -- /home/jichu/esp32/lvgl_display/partitions.csv /home/jichu/esp32/lvgl_display/build/partition_table/partition-table.bin && /usr/bin/cmake -E echo "Partition table binary generated. Contents:" && /usr/bin/cmake -E echo "*******************************************************************************" && /home/jichu/.espressif/python_env/idf5.2_py3.8_env/bin/python /home/jichu/esp32/esp-idf/components/partition_table/gen_esp32part.py -q --offset 0x8000 --flash-size 2MB -- /home/jichu/esp32/lvgl_display/build/partition_table/partition-table.bin && /usr/bin/cmake -E echo "*******************************************************************************" Partitions tables occupies 3.6MB of flash (3751936 bytes) which does not fit in configured flash size 2MB. Change the flash size in menuconfig under the 'Serial Flasher Config' menu. [3/1587] Generating memory.ld linker script... ninja: build stopped: subcommand failed. ninja failed with exit code 1, output of the command is in the /home/jichu/esp32/lvgl_display/build/log/idf_py_stderr_output_17540 and /home/jichu/esp32/lvgl_display/build/log/idf_py_stdout_output_17540
最新发布
03-14
<think>嗯,用户遇到了构建ESP32项目时的错误,之前已经给出过关于缺少partitions.csv文件的解决方案,但现在用户又遇到了新的问题。首先,我需要仔细阅读用户的新错误日志,看看有什么不同之处。 用户这次的错误信息显示,虽然之前可能已经创建了partitions.csv文件,但现在出现了两个问题:第一个是分区表文件不存在,第二个是分区表占用了3.6MB的闪存,超过了配置的2MB。这可能意味着用户按照之前的建议添加了分区表,但其中的分区大小总和超过了ESP32的闪存容量。 首先,我需要检查用户提供的日志中的具体错误。第一条错误信息显示“Partition table CSV does not exist”,这可能是因为用户虽然创建了文件,但路径不正确,或者文件名有误。不过第二条错误提示分区大小超过闪存容量,这说明文件已经存在,但内容有问题。 这时候,用户可能已经按照之前的指导添加了partitions.csv文件,但可能复制了默认的分区表,例如partitions_singleapp.csv,而该文件的分区大小总和超过了项目配置的闪存大小(2MB)。或者用户手动创建的分区表尺寸设置得太大,导致总和超过限制。 接下来,我需要考虑用户可能的操作步骤:他们可能解决了文件缺失的问题,但未调整分区大小或未正确配置闪存大小。因此,解决方案应该包括检查分区表内容,确保各分区的大小总和不超过2MB,同时确认menuconfig中的闪存配置是否正确。 另外,用户可能在menuconfig中设置了错误的闪存大小,或者没有正确选择自定义分区表文件。需要指导用户通过menuconfig检查“Serial Flasher Config”中的闪存大小,并调整为更大的值,如4MB,或者调整分区表中的分区大小,使其总和在2MB以内。 还可能存在的情况是,用户的分区表中的偏移地址设置不正确,导致分区重叠或超出闪存空间。需要检查每个分区的Offset和Size,确保它们从0x8000开始,逐步增加,且总和不超过0x200000(2MB)。 最后,用户可能需要清理构建缓存并重新构建,以确保所有配置更改生效。同时,提醒用户检查文件权限和路径是否正确,避免其他潜在问题。 总结起来,解决步骤应包括:1. 确认partitions.csv存在且路径正确;2. 检查分区表内容,调整分区大小;3. 配置menuconfig中的闪存大小;4. 清理并重新构建项目。需要以清晰的步骤指导用户逐步排查,确保他们能够理解和操作。</think>你遇到的错误包含两个关键问题,需要依次解决: --- ### **1. 问题分析** #### **(1) 分区表文件路径错误** ``` Partition table CSV /home/jichu/esp32/lvgl_display/partitions.csv does not exist. ``` - **原因**:构建系统找不到 `partitions.csv` 文件,可能是文件未创建或路径错误。 #### **(2) 分区表大小超过Flash配置** ``` Partitions tables occupies 3.6MB of flash (3751936 bytes) which does not fit in configured flash size 2MB. ``` - **原因**:`partitions.csv` 中定义的分区总大小(3.6MB)超过了项目中配置的Flash大小(2MB)。 --- ### **2. 解决方案** #### **步骤1:修复分区表文件路径** 1. **确认 `partitions.csv` 是否存在**: ```bash ls /home/jichu/esp32/lvgl_display/partitions.csv ``` - 如果文件不存在,参考以下模板创建: ```csv # Name, Type, SubType, Offset, Size, Flags nvs, data, nvs, 0x9000, 0x4000 otadata, data, ota, 0xd000, 0x2000 app0, app, ota_0, 0x10000, 0x1A0000 # 注意总大小不要超过2MB spiffs, data, spiffs, 0x1B0000,0x50000 # 调整Size字段 ``` - 如果文件存在,检查路径是否与项目根目录一致。 #### **步骤2:调整分区表大小** 1. **修改 `partitions.csv` 中的分区大小**: - 确保所有分区的 `Offset + Size` 总和不超过 **2MB (0x200000)**。 - 示例调整: ```csv # 调整后总大小不超过2MB nvs, data, nvs, 0x9000, 0x4000 otadata, data, ota, 0xd000, 0x2000 app0, app, ota_0, 0x10000, 0x180000 # 1.5MB spiffs, data, spiffs, 0x190000,0x70000 # 448KB ``` - **验证方法**:`0x10000 + 0x180000 = 0x190000`,`0x190000 + 0x70000 = 0x200000`(正好2MB)。 #### **步骤3:修改Flash大小配置** 1. **通过 `menuconfig` 调整Flash大小**: ```bash idf.py menuconfig ``` - 进入 `Serial Flasher Config` → 将 `Flash Size` 设置为 **4MB**(如果硬件支持)或 **2MB**(需严格匹配分区表总大小)。 - 保存配置并退出。 #### **步骤4:清理并重新构建** ```bash idf.py fullclean idf.py build ``` --- ### **3. 其他注意事项** - **分区表与Flash对齐**:确保分区起始地址 (`Offset`) 按 **0x1000 (4KB)** 对齐。 - **默认分区表参考**: - ESP-IDF 提供的 `partitions_singleapp.csv` 可能更适合小Flash设备,可复制到项目中使用: ```bash cp $IDF_PATH/components/partition_table/partitions_singleapp.csv ./partitions.csv ``` - **调试工具**:使用 `gen_esp32part.py` 手动验证分区表: ```bash python $IDF_PATH/components/partition_table/gen_esp32part.py partitions.csv ``` --- ### **4. 常见问题** - **错误:`Unknown partition subtype`** 检查分区表中 `SubType` 字段是否合法(如 `ota_0`、`spiffs` 等)。 - **错误:`Overlap between partitions`** 确保分区的 `Offset` 和 `Size` 不重叠。 完成上述步骤后,重新构建项目即可解决问题。如果仍有错误,请检查 `build/log` 中的详细日志。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值