图7.1.1 基础例程的分区表文件
上图中展示了ESP32的多个子分区及其功能。其中,nvs子分区是专为开发者设计的非易失性存储(NVS)设备区域;phy_init子分区用于存放PHY初始化数据,确保每个设备都能单独配置其PHY;factory子分区则专门用于存储应用程序区域;vfs子分区作为虚拟文件系统的存储区域;而storage子分区则是自定义的SPIFFS文件系统区域。这些子分区共同构成了ESP32的分区结构,满足了不同功能的需求。
三、分区表条目结构
从上图中可以看到,每一个子分区都由以下几个部分组成:
1, name:子分区名称。该字段对 ESP32-S3 并不是特别重要。
2, Type:子分区的存储类型。设置子分区的存储格式,app (0x00) 和 data (0x01)。
3, SubType:进一步描述或分类分区表的条目。如果这个子分区Type为app,则SubType只能设置factory、ota_0、ota_15和test;如果这个子分区Type为data,则SubType只能设置ota、phy、nvs和nvs_keys。
4, Offset:偏移地址。编译地址必须是4KB的倍数
5, Size:大小。子分区的大小
6, Flags:标志位。一般不设置该字段。
四、分区表的类型
分区表的类型具有四种,如下表所示:
分区表类型 | 描述 |
Single factory app no OTA | 小型的应用程序,但没有OTA升级区域 |
Single factory app (large) no OTA | 大型的应用程序,但没有OTA升级区域 |
Factory app two OTA defini tions | 大型的应用程序,且具备两个OTA升级区域 |
Custom partition table CSV | 自定义分区表 |
表7.1.1 分区表的类型
根据上述内容,如果不打算使用OTA升级功能,可以根据项目的大小选择第一种或第二种分区类型。而想要使用OTA升级功能时,应选择第三种分区类型。作者推荐采用最后一种分区类型,因为它允许自定义分区表,能更精确地满足项目工程的需求,从而实现完美的契合。
从上述内容可以了解到,分区表是对flash闪存进行区域划分,以便根据不同的功能需求将flash划分为不同的区域。这些区域可以包括应用、数据等不同类型,例如应用可以进一步细分为Factory程序、OTA程序等,数据则可以包括校准数据、文件系统数据、参数存储数据等。
每个分区都有其特定的作用,开发者可以根据自己的需求进行配置以及修改。这样的设计使得开发者能够更方便地管理和使用flash空间,同时也有助于提高系统的稳定性和安全性。
7.2 分区表API函数
esp_partition 组件是 ESP-IDF中用于管理 ESP32 及其系列芯片上 flash 分区的一个关键组件。它提供了一组高层次的 API 函数,允许开发者方便地访问和操作定义在分区表中的各个分区。这些高层次的 API 函数为开发者提供了简洁和易用的接口,以进行诸如读取、写入、擦除分区内容等操作。这些函数可在components/esp_partition/include/esp_partition.h路径下找到这些分区表API函数。
1,esp_partition_find函数
该函数查找子分区,该函数原型如下所示:
const esp_partition_t *esp_partition_find_first(esp_partition_type_t type,
esp_partition_subtype_t subtype,
const char *label)
该函数的形参描述如下表所示:
参数 | 描述 |
| 子分区类型 |
ESP_PARTITION_TYPE_APP | 应用程序分区类型 |
ESP_PARTITION_TYPE_DATA | 数据分区类型 |
ESP_PARTITION_TYPE_ANY | 搜索随意类型分区 |
subtype | 子类型(请看esp_partition_subtype_t结构体) |
label | 子分区名称 |
表7.2.1 esp_partition_find函数函数描述
该函数返回值如下:
NULL:未找到子分区。esp_partition_t指针:返回子分区。
2,esp_partition_read函数
该函数用于读取子分区的某个地址的数据,该函数原型如下所示:
esp_err_t esp_partition_read( const esp_partition_t* partition,
size_t src_offset,
void* dst, size_t size)
该函数的形参描述如下表所示:
参数 | 描述 |
partition | 分区结构指针 |
src_offset | 读取数据的地址 |
dst | 存储数据的指针 |
size | 读取数据大小 |
表7.2.2 esp_partition_read函数函数描述
该函数返回值如下:
ESP_OK:读取成功。其他:失败。
3,esp_partition_write函数
该函数用于写入子分区的某个地址的数据,该函数原型如下所示:
esp_err_t esp_partition_write( const esp_partition_t* partition,
size_t dst_offset,
void* src, size_t size)
该函数的形参描述如下表所示:
参数 | 描述 |
partition | 分区结构指针 |
dst_offset | 写入数据的地址 |
src | 写入数据 |
size | 写入数据大小 |
表7.2.3 esp_partition_write函数函数描述
该函数返回值如下:
ESP_OK:读取成功。其他:失败。
4,esp_partition_range函数
该函数用于擦除子分区的某个地址的数据,该函数原型如下所示:
esp_err_t esp_partition_erase_range(const esp_partition_t *partition,
size_t offset, size_t size)
该函数的形参描述如下表所示:
参数 | 描述 |
partition | 分区结构指针 |
offset | 擦除数据的地址 |
size | 擦除数据大小 |
表7.2.4 esp_partition_range函数函数描述
该函数返回值如下:
ESP_OK:读取成功。其他:失败。
上述列举的函数是访问和操作分区表时较为常用的API函数。若需进一步了解或学习其他剩余的分区表API函数,可查阅esp_partition.h头文件。
注意:上述函数的使用方法,可打开28_chinese_display实验下的fonts.c文件,我们使用这些函数把GBK字库更新至storage分区表,然后完成了汉字实验。