分区表是什么?

分区表是ESP32用来管理其闪存空间的一种数据结构。它定义了闪存中各个区域(分区)的用途和大小。分区表的作用类似于硬盘上的分区表,告诉系统每个部分是用来存储什么的。

在ESP32中,分区表是一个二进制文件,通常命名为 partitions.csvpartitions.bin。开发时使用的是 .csv 文件(可读文本格式),编译后会被转换为 .bin 文件并烧录到闪存中。

默认使用的分区表

分区表存储的数据

分区表中的每一行定义了一个分区,每个分区包含以下信息:

  1. Name:分区的名字,用于标识该分区,比如 app0nvs 等。
  2. Type:分区的类型,表示分区的用途,常见的类型包括:
    • app:应用程序代码。
    • data:数据存储,如 NVS、文件系统等。
    • ota:OTA 更新相关数据。
    • custom:自定义分区。
  3. SubType:子类型,进一步细化分区的用途,例如:
    • 对于 app 类型,子类型可以是 factory(出厂固件)、ota_0ota_1 等。
    • 对于 data 类型,子类型可以是 nvs(非易失性存储)、spiffs(文件系统)等。
  4. Offset:分区在闪存中的起始地址(偏移量)。如果留空,编译器会自动分配。
  5. Size:分区的大小,单位通常是字节或KB/MB。
  6. Flags:标志位,目前很少用到,通常为空。
字段解释
  1. nvs:存储非易失性数据(Non-Volatile Storage),如 Wi-Fi 配置。

  2. phy_init:存储射频初始化数据。

  3. factory:出厂固件的应用程序代码。

  4. ota_0 和 ota_1:用于 OTA 更新的应用程序代码。(在有ota功能的分区表中)

  5. spiffs:存储文件系统数据。

分区表存储的位置

默认情况下,分区表位于 ESP32 闪存的固定位置,偏移地址为 0x8000。也就是说,分区表从闪存地址 0x8000 开始存储。

  • 闪存布局示例
    0x00000: Bootloader
    0x08000: Partition Table
    0x10000: Factory App (or OTA_0)
    

如何在程序中找到分区表

分区表由一个 CSV 文件定义。你可以在项目目录下的 partitions.csv 文件中找到它。

ESP-IDF 提供了一些默认的分区表配置,如果你没有在项目中自定义分区表,系统会使用默认的分区表。这种情况下,.csv 文件不会出现在你的项目目录中,而是直接从 ESP-IDF 的内部路径加载。

自定义分区表

如果你要自定义分区表,
首先在项目目录下使用命令进入ESP32配置界面

idf.py menuconfig

**进入Partition Table **
menuconfig

选择分区表
在这里插入图片描述
在这里插入图片描述
可以看到,ESP默认使用的分区表为Single factory app
这个分区表文件的路径为:
esp32/esp-idf/components/partition_table/partitions_singleapp.csv

选择第四项:自定义分区
在这里插入图片描述
输入你的分区表文件名,这里我设置为partitions_user.csv,回车确认。

按 s 保存->回车确认->按q退出配置

找到esp-idf中的partitions_singleapp.csv文件内容,复制到项目的partitions_user.csv文件中
在这里插入图片描述
注意:partitions_user.csv一定要在项目的顶层目录中

添加自定义的分区
在这里插入图片描述

这样就完成了自定义分区,接下来对这个分区进行读写操作实验

#include <stdio.h>
#include "esp_partition.h"
#include "esp_log.h"
#include <string.h>

/* 定义分区类型 */
#define USER_PARTITION_TYPE     0x40
#define USER_PARTITION_SUBTYPE  0x01

static const esp_partition_t*   partition_prt = NULL;

void app_main(void)
{
    partition_prt = esp_partition_find_first(USER_PARTITION_TYPE, USER_PARTITION_SUBTYPE, NULL);//第三个参数是分区标签,用不到给NULL
    /*
    esp_partition_find:找到所有符合条件的分区,返回一个“迭代器”(指针),可以通过迭代器遍历所有符合条件的分区
    esp_partition_find_first:直接找到第一个符合条件的分区,返回指向该分区的指针
    */
   if(partition_prt == NULL)
   {
        ESP_LOGI("partition", "Can't find partition");
        return;
   }

   esp_partition_erase_range(partition_prt, 0, 0x1000);

   const char *test_string = "this is for test partition";
   esp_partition_write(partition_prt, 0, test_string, strlen(test_string));

   char read_buf[64];
   memset(read_buf, 0, sizeof(read_buf));
   esp_partition_read(partition_prt, 0, read_buf, strlen(test_string));

   ESP_LOGI("partition", "read partition data:%s", read_buf);

   return;
}

在这里插入图片描述

总结

  • 分区表定义了 ESP32 闪存的布局,帮助系统管理不同的数据类型。
  • 分区表存储在闪存的固定位置(默认 0x8000),通常通过 partitions.csv 文件配置。
  • 每个分区有名称、类型、子类型、偏移地址和大小等属性。
  • 在程序中,可以通过 ESP-IDF 的 API 动态读取和操作分区表。

通过理解分区表,你可以更好地规划闪存空间,优化资源利用,并实现复杂的固件更新功能(如 OTA)。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐