【ESP32-IDF】04-1 存储-分区表

分区表

1. esp32 flash结构

1.1 flash 物理组成

   esp32的falsh可以分为三部分:

  • 内部flash: 内部flash是esp32芯片自带的flash,空间大小是448k
  • 主系统falsh: 一般esp32模组都带了一个flash芯片作为主系统flash,通过spi总线进行访问。这个主falsh芯片是用来存放系统数据、代码等东西的,如wroom模组上带了4M的主系统flash。不过,esp32 configmenu默认设置主系统flash是2M,需要手动进行调整,最大可以达到16M。主系统flash芯片一般来说是必须的。
  • 外部flash: 除了主系统flash外,还可以通过spi的其他总线扩展外部flash。这个flash如果有需要,可以自己增加。

1.2 flash 内部结构

   flash从结构上来看,包括BootLoader分区表用户数据(包括代码和存储数据)三部分。

   比如我们看下面实际的一张flash内存表

【ESP32-IDF】04-1 存储-分区表

  flash从0x8000以前的区域,都是bootloader,用于esp32的启动

  flash在0x8000处烧写一张分区表(partition Table),该分区长度为0xC00字节,最多可以保存95条分区表条目。分区表定义了后面数据段的用途

   分区表后面的数据都属于用户数据,用来存放用户的代码和数据。该部分具体包含什么功能区,由分区表决定。可能包含以下内容:

  • Factory: 属于代码区域(app)。存放的是从串口下载来的固件程序。
  • OTA_0-15:属于代码区域(app)。该区域存放的是通过隔空下载的方式存储的程序。使用OTA下载功能,flash中至少开辟两个OTA区域(比如OTA_0和OTA_1)。因为OTA下载的时候,不会修改factory区域中的代码,而是将代码在OTA_0和OTA_1之间交替烧写。在没有OTA区域的时候,程序会执行factory区域的代码,有了OTA之后,会使用OTA的代码,通过OTA data区域来确定从哪个区域加载代码。
  • NVS: 属于数据区域(data)。数据以键值对的方式在这段空间进行存储。如果启动了wifi功能,wifi的数据会存储在这个地方。用户也可自己存储键值对类型的数据
  • OTA data: 属于数据区域(data)。存放的是与OTA功能有关的数据,比如记录这次烧写的是哪个OTA,下次往哪个OTA烧写。
  • Phy data: 属于数据区域(data)。存放的是PHY初始化数据
  • Core dump:core dump分区用于查找系统崩溃时的软件错误,系统崩溃的时候会将调试信息

      在esp32中,分区表是以bin类型的二进制文件进行烧写的。如果想读取这个分区表,可以通过一些方法把bin转换为csv进行阅读,具体方法后文会讲。

    2.2 分区表的定义

      分区表含有六个字段。包括Name,Type,SubType、Offset、Size、Flags,如默认的分区表定义如下:

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

    2.2.1 Name字段

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

    2.2.2 Type字段

      Type 字段可以指定为 app (0x00)(代码类型) 或者 data (0x01)(数据类型),也可以直接使用数字0-254(或者十六进制 0x00-0xFE)。注意,0x00-0x3F 不得使用(预留给 esp-idf 的核心功能)。

      如果应用程序需要以ESP-IDF尚未支持的格式存储数据,请在0x40-0xFE内添加一个自定义分区类型。

    2.2.3 SubType字段

      SubType 字段长度为 8 bit,内容与具体分区 Type 有关。目前,esp-idf 仅仅规定了 “app” 和 “data” 两种分区类型的子类型含义。

    Name Type SubType
    any value app factory
    ota_0-15
    any value data ota data
    phy
    nvs
    spiffs

      当Type定义为app的时候,SubType可以选择factory(0x00)、0ta_0(0x10)…ota_15(0x1F)或test(0x20):

    • factory:是默认的 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: 即 OTA 数据分区 ,用于存储当前所选的 OTA 应用程序的信息。这个分区的大小需要设定为 0x2000。
    • phy:存放PHY初始化数据。默认PHY分区不启用,而是把PHY初始化数据编译到应用程序中。如果要从此分区加载PHY初始化数据,请打开项目配置菜单(idf.py menuconfig),并且使能CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION 选项。此时,您还需要手动将 phy 初始化数据烧至设备flash (esp-idf 编译系统并不会自动完成该操作)。
    • nvs :是专门给 非易失性存储 (NVS) API 使用的分区。用于存储phy校准数据、wifi数据和自定义数据。NVS分区至少0x3000字节,如果要存储大量数据,建议增加。默认是0x6000字节
    • nvs_key: NVS秘钥分区。用于存储加密秘钥。此分区至少4096字节
    • 文件系统:可以存放fatspiffs等文件系统

    2.2.4 offset和size

      偏移地址是功能分区的起始地址。这个地址要求与0x10000(64k)对齐。

      如果偏移字段留空,gen_esp32part.py 工具会自动计算得到一个满足对齐要求的偏移地址。

      如果 app 分区的偏移地址没有与 0x10000 (64K) 对齐,则该工具会报错。

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

    2.2.5 flags

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

    2.3 系统分区表的查看

      分区表以二进制文件bin类型的方式进行存储,如果我们想要查看,就要把bin文件转换为csv文件。转换方法如下:

    • 打开esp-idfcomponentspartition_table 路径,找到gen_esp32part.py
    【ESP32-IDF】04-1 存储-分区表
    • 用命令行输入code. 的方法用vscode打开某个项目,输入命令,即可把当前项目中的分区表变成csv查看。注意,python脚本路径,输入文件和输出文件路径需要自己定义修改,这里只是个例子

    python C:SoftwareEspespidfcomponentspartition_tablegen_esp32part.py buildpartition_tablepartition-table.bin C:Users30311Desktoppartition-table.csv

    2.4 分区表的更换

    • 输入指令

    idf.py menuuconfig

    • 在menuconfig中找到partition table,在此选项中即可进行分区表的更换
      【ESP32-IDF】04-1 存储-分区表

    2.4.1 使用内置分区表

      前两个选择是内置分区表

    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,  

    2.4.2 使用自定义的分区表

      把自定义的分区表放在项目路径下,在这里吧名字输入进去即可。idf会自动把csv转换为bin文件

    【ESP32-IDF】04-1 存储-分区表

    3. 参考资料

    [1] ESP32分区表图解

    [2] 玩转ESP32(3):partitiontable使用

    [3] 分区表

版权声明:玥玥 发表于 2021-05-07 12:35:30。
转载请注明:【ESP32-IDF】04-1 存储-分区表 | 女黑客导航