事情起因

在调试 lvgl 动画跟WIFI的时候报内存分区不够的错误,但是 ESP32-PICO-KIT 使用的是 ESP32-PICO-D 芯片,拥有 4MB 内存才对,选择的默认是 1MB 而已,后边调整选择自带的 CSV 分区文件,仔细看才有 1500kb ,总感觉不对,才又重新根据需求更改 FLASH,通过这个可以知道能自己改大内存的吧!以后有机会得试试看!

刚刚根据这篇文章将 ESP32-PICO-KIT 开发板中D4芯片ESP32的内存改成了4MB模式,之前最大只到1.5MB,有个地方不同,它计算的方式是kb,而且还是1000为1MB,也就是说设置了4000K内存,同时也要在menuconfig中修改串口flash为4mb,选择相应分区表文件csv即可!

官方分区表

每片 ESP32 的 flash 可以包含多个应用程序,以及多种不同类型的数据(例如校准数据、文件系统数据、参数存储数据等)。因此,我们在 flash 的 默认偏移地址 0x8000 处烧写一张分区表。

分区表的长度为 0xC00 字节,最多可以保存 95 条分区表条目。MD5 校验和附加在分区表之后,用于在运行时验证分区表的完整性。分区表占据了整个 flash 扇区,大小为 0x1000 (4 KB)。因此,它后面的任何分区至少需要位于 (默认偏移地址) + 0x1000 处。

分区表中的每个条目都包括以下几个部分:Name(标签)、Type(app、data 等)、SubType 以及在 flash 中的偏移量(分区的加载地址)。

在使用分区表时,最简单的方法就是打开项目配置菜单(idf.py menuconfig),并在 CONFIG_PARTITION_TABLE_TYPE 下选择一个预定义的分区表:

“Single factory app, no OTA”

“Factory app, two OTA definitions”

在以上两种选项中,出厂应用程序均将被烧录至 flash 的 0x10000 偏移地址处。这时,运行 idf.py partition-table ,即可以打印当前使用分区表的信息摘要。

IDF 前端工具 - idf.py

修改分区表适配大于1M的固件

使用的是esp32的esp-idf sdk;

分区列表路径

相对路径: ~/esp-adf/esp-idf/components/partition_table

注:也可使用环境地址进入 ${IDF_PATH}/components/partition_table

里面的几个后缀为.csv的分区文件均可用,具体使用哪个是在menuconfig中设置的; 如下图所示:需要配置两个地方的信息;

第一处配置:

路径:Component config —> ESP32-specific —> Core dump destination (None) —>

主:现在使用的 ESP-IDF-5.2.2 版本不用这个也正常,只是当前kit开发板的查看了只有1500K内存!

第二处配置:

路径:Partition Table —> Partition Table (Single factory app, no OTA) —>

修改编译

这两处配置完后, 就能确定使用哪个配置文件; 然后修改对应的文件:这边对应的是partitions_singleapp.csv

修改固件存储最大为2M;

保存后,重新编译固件;

不使用OTA时,从0x10000地址处加载固件, 如下所示, factory app显示的长度为2M容量;

大于1M的固件经过上述设置后,可以正常运行了.

内存不够报错

详细内容点击官方分区内容说明即可!

ESP32 分区表

当你编译程序,发现 app partition is too small for binary 错误的时候,就涉及到 ESP32 分区表的内容了。

一、基本概念

在了解分区之前,先了解一下以下概率,便于 ESPe32 分区的理解

  1. 缓存(cache)
    缓存是指可以进行高速数据交换的存储器,它先于内存与CPU交换数据,因此速率很快。而缓存分为:一级缓存、二级缓存、三级缓存,原理如下图所示:

    从图中可以看出,为了减少争用Cache所造成的冲突,提高了处理器效能,将一级缓存分为:数据缓存(Data Cache,D-Cache)和指令缓存(Instruction Cache,I-Cache),想要了解更多信息,参考缓存

  2. 随机存取存储器(RAM)
    随机存取存储器(英语:Random Access Memory,缩写:RAM),也叫主存,是与CPU直接交换数据的内部存储器。根据存储单元的工作原理不同, RAM分为静态SRAM和动态DRAM

    • SRAM
      优点:速度快、使用简单、不需刷新、静态功耗极低;常用作Cache。 [8]
      缺点:元件数多、集成度低、运行功耗大。
    • DRAM
      优点: 集成度远高于SRAM、功耗低,价格也低。 [8]
      缺点:因需刷新而使外围电路复杂;刷新也使存取速度较SRAM慢,所以在计算机中,DRAM常用于作主存储器。

    了解更多,请参考随机存取存储器

  3. 只读存储器(ROM)
    只读存储器(Read-Only Memory,ROM)以非破坏性读出方式工作,只能读出无法写入信息。信息一旦写入后就固定下来,即使切断电源,信息也不会丢失,所以又称为固定存储器。

    ROM有多种类型,且每种只读存储器都有各自的特性和适用范围。从其制造工艺和功能上分,ROM有五种类型,即掩膜编程的只读存储器MROM(Mask-programmedROM)、可编程的只读存储器PROM(Programmable ROM)、可擦除可编程的只读存储器EPROM(Erasable Programmable ROM)、可电擦除可编程的只读存储器 EEPROM(Elecrically Erasable Programmable ROM)和快擦除读写存储器(Flash Memory)。
    了解更多,请参考只读存储器

  4. 闪存(Flash)
    flash存储器又称闪存,它结合了ROM和RAM的长处,不仅具备电子可擦除可编程(EEPROM)的性能,还可以快速读取数据(NVRAM的优势),使数据不会因为断电而丢失。

  5. 电磁频率(RadioFrequency)
    RF 是Radio Frequency的缩写,表示可以辐射到空间的电磁频率,频率范围从300KHz~30GHz之间。

  6. 实时时钟(RTC)
    实时时钟的缩写是RTC(Real_Time Clock)。RTC 是集成电路,通常称为时钟芯片。

  7. 安全系统(Security)
    主要是各种安全算法,确保系统和数据的安全

了解完成后上面的基本概念后,我们在看一下ESP32 的架构就很容易了,如下图所示:

二、芯片配置

分区配置需要根据自己芯片的 Flash 大小进行配置的,所以在配置之前首先得了解自己芯片的信息,如下图所示:

三、选择分区方式

  1. 设置 flash 大小,并选择分区方式

    注意:这个可以主要可以分为两种配置方式,除自定义(Custom partition table CSV)分区方式外,其他的都是预定义分区,主要分析自定义分区方式

  2. 设置自定义分区

  3. 在工程文件中创建 partitions.csv 文件,如下图所示:

  4. partitions.csv 文件中添加自定义分区内容

    1
    2
    3
    4
    5
    6
    # 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, 4M,

三、分区类容

1
2
3
4
5
6
7
8
9
# 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-S3 并不是特别重要。

Type 字段

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

注意:启动加载器将忽略 app (0x00) 和 data (0x01) 以外的其他分区类型。

SubType 字段

  • 当 Type 定义为 app 时,SubType 字段可以指定为 factory (0x00)、 ota_0 (0x10) … ota_15 (0x1F) 或者 test (0x20)。
  • 当 Type 定义为 data 时,SubType 字段可以指定为 ota (0x00)、phy (0x01)、nvs (0x02)、nvs_keys (0x04) 或者其他组件特定的子类型

Offset 字段

Offset(偏移地址) 为空时,则会紧跟着前一个分区之后开始;若为首个分区,则将紧跟着分区表开始。
注意:app 分区的偏移地址必须要与 0x10000 (64K) 对齐

Size 字段

分区的大小

Flags字段

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

详细见 ESP-IDF 编程指南

配置完成后,在编译过程中会打印 分区配置表的信息,如下所示:

1
2
3
4
5
6
7
8
9
*******************************************************************************
# ESP-IDF Partition Table
# Name, Type, SubType, Offset, Size, Flags
nvs,data,nvs,0x9000,16K,
otadata,data,ota,0xd000,8K,
phy_init,data,phy,0xf000,4K,
factory,app,factory,0x10000,4M,
*******************************************************************************

参考文献

缓存
随机存取存储器
只读存储器
RF
实时时钟

扩大ESP32可用FLASH容量

起因:

由于会用到蓝牙和WIFI以及HTTP OTA功能,导致需要的Flash会比较大。乐鑫原本的分区表是一个固件(factory)和两个OTA(ota_0,ota_1),而固件(factory)分区是用来兜底的,但是这部分可以用ota_0或ota_1来作为兜底的功能分区。那么固件(factory)分区我们是可以删除,把这部分的flash长度平均到ota_0和ota_1,来扩大可编程flash空间。

截取有用部分内容参考

检查容量是否正确

我使用的是4MB,如果你们使用的是2MB,则要更改分区表ota_0和ota_1的长度和起始位置,注意ota_0的起始位置0x10000是不更改的

添加并选中自定义分区表

在工程目录下添加partitions.csv文件,内容可以见红框内

选中分区表,该作用为,编译阶段会使用你指向的CSV文件生成相应的 partitions.bin 文件

解决ESP32的flash空间不足

esp32同时使用wifi和蓝牙时,通过编译会发现内存不够。

编译结果:

该程序需要1404165bytes内存(1404165/1024/1024=1.34mb),但是可用内存只有1310720bytes(1310720/1024/1024=1.25mb),显然内存是不够的, 但是我们使用的esp-wroom-32的flash总共有4mb,那我们有没有办法增加用来存储程序的内存呢?答案是肯定的。

esp32内存中有一张分区表,将内存划分成几个不同的区域,用于存储不同的内容,我们只需要对这一张分区表进行修改就能实现我们的目的。

根据路径 C:\Users\pc.platformio\packages\framework-arduinoespressif32\tools\partitions,打开partitions文件,里面有很多excel表格,这些就是esp32的分区表(在下载platformio时自动下载的)。

其中default.csv就是默认的分区表,我们将其打开。

这里用于存储程序的内存大小为0x140000=1310720bytes,与目前编译环境下的内存相同。

现在我们采用现存的另一分区表huge_app.csv,我们将其打开。

表中用于存储程序的内存为0x300000=3145728bytes。

为了使用该分区表,我们打开paltformio.ini,在其中输入以下命令。

1
board_build.partitions=huge_app.csv

其中命令monitor_speed=115200是用于修改波特率的,命令upload_speed=921600是用于修改下载速度的,大家可以根据需要使用,修改完成后我们进行编译。

此时内存变为我们刚才计算的数值3145728bytes(3145728/1024/1024=3mb),此时内存已经绰绰有余了。

当然我们也可以根据自己的需要来修改分区表,复制一张默认分区表default.csv到工程文件中。

将其文件名修改为mymenset.csv,在此处,我对该分区表进行了如下修改(大家可以根据需要自行修改):

此时内存应为0x180000=1572864bytes,我们再在platformio.ini中进行对应修改。

编译结果如下:


相关链接(侵删)

  1. ESP32编译的固件大于1M时, 更改分区列表
  2. Error: app partition is too small for binary (IDFGH-11454)
  3. ESP32 分区表
  4. 【笔记】ESP32修改分区表 – 扩大可编程FLASH容量
  5. 解决ESP32的flash空间不足

=================我是分割线=================

欢迎到公众号来唠嗑: