ESP32学习四-自定义分区表

1、简介

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

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

ESP32学习四-自定义分区表_第1张图片

ESP32学习四-自定义分区表_第2张图片

ESP32学习四-自定义分区表_第3张图片

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

二、无OTA分区

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

         ESP32学习四-自定义分区表_第4张图片

# 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分区

        ESP32学习四-自定义分区表_第5张图片

# 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

ESP32学习四-自定义分区表_第6张图片

         3.修改链接CSV链接名。

ESP32学习四-自定义分区表_第7张图片

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

ESP32学习四-自定义分区表_第8张图片

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

ESP32学习四-自定义分区表_第9张图片

        5.退出保存。

 ESP32学习四-自定义分区表_第10张图片

         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.重新编译

ESP32学习四-自定义分区表_第11张图片

五、自定义分区表详解

        如果在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编译系统并不会自动完成该操作)。

ESP32学习四-自定义分区表_第12张图片

         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]);
}

        结果:

ESP32学习四-自定义分区表_第13张图片

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

ESP32学习四-自定义分区表_第14张图片

 

七、如何查看分区表

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

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

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

ESP32学习四-自定义分区表_第15张图片

         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学习四-自定义分区表_第16张图片

         

        官方参考文档:

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

你可能感兴趣的:(ubuntu,esp32,分区表)