ESP32使用SPI RAM优化内部内存空间

1,启用 外部RAM

勾选 Support for external, SPI-connected RAM 如下图

2,配置说明

1,选择 外部RAM 的类型(见下图)
这个要根据自己的板子选择, ESP32支持的外部RAM有限.
不清楚的 选择 自动检测

2, 设置 外部RAM 的时钟速度(见下图)
勾选40M即可

官方解释:

选择SPI RAM芯片的速度。如果SPI RAM被启用,我们只支持现在支持的三种SPI速度模式的组合:

  1. Flash SPI运行在40Mhz和RAM SPI运行在40Mhz 2。Flash SPI运行在80Mhz和RAM SPI运行在40Mhz 3。Flash SPI运行在80Mhz和RAM SPI运行在80Mhz 注意:如果32MBit类型的SPI
    RAM启用了第三种模式(80Mhz+80Mhz),系统将占用其中一个HSPI/VSPI主机。使用哪个SPI主机可以通过配置项SPIRAM_OCCUPY_SPI_HOST来选择。在这种情况下,应用程序代码不应该接触HSPI/VSPI硬件。只有当闪光SPI速度也是80MHz时,选择80MHz的选项才会可见。(ESPTOOLPY_FLASHFREQ_80M是真的)

3 启动的时候对其进行初始化 勾选即可 (如下图)
官方解释:

如果启用了这一点,SPI RAM将在初始引导期间启用。除非您有特定的需求,否则您将希望保持启用状态,以便在引导期间分配的内存也可以放在SPI RAM中。


4 选择 外部RAM的使用方案
大概意思是
第一个选项: 外部RAM全部由自己也就是应用程序管理.
第二个选项: 外部RAM 交给SDK管理,应用程序使用的时候 要使用规定的函数 heap_caps_malloc(size, MALLOC_CAP_SPIRAM) 调用 才会分配外部内存.
第三个选项: 外部RAM 交给SDK管理,应用程序使用的时候 不需要调用规定的函数 使用常规的 malloc() 函数即可分配得到外部RAM. (这样做的好处 不用从新改写 内存分配函数了) 但会准守一定的策略.
策略 的大概意思就是 会有一个阀值设置 比如设置1K ,当使用malloc 申请的空间小于1K的时候 就使用内部RAM, 大于的时候 就使用外部RAM. 具体下面的配置会涉及到.
官方说明地址:https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32/api-guides/external-ram.html#id5

下面的参数 是按照选择了 RAM使用方案三 (也就是上一个参数的第三个选项) 举例说明的

5 在SPI RAM初始化时 是否要进行 内存测试, 勾选即可(如下图)
官方解释

在初始化时运行基本内存测试。当内存测试失败时中止。禁用此功能可以稍微加快启动速度。


6 选择 RAM使用方案三 后 才会有的.

当大于这个阀值的时候使用外部内存, 小于这个阀值的时候使用 内部内存. 当然也会有一个应急方案, 就是当优先内存满的时候 会选择另一个内存 尝试.

根据自己应用程序的情况设置即可.

官方解释:

如果malloc()也能够分配与spi连接的ram,那么它的分配策略将倾向于在内部内存中分配小于此大小的块,而大于此大小的分配将从外部ram中完成。如果从首选区域分配失败,则尝试从非首选区域分配,这样malloc()就不会在内部或外部内存满时突然失败。


7是否 优先 尝试在SPIRAM中分配WiFi和LWIP的内存。如果失败,则分配内部内存.
如果想要优化内部内存 这个建议勾选, 如下图

8 为DMA或内部内存O中特别需要的数据保留这一数量的字节.
大概意思就是 因为外部的RAM 有一些限制. 比如DMA是不能在外部内存使用的. 所以在使用 内存方案三 的时候, 我们要预留出一定的内部内存空间, 给我们需要用到DMA的时候 , 自己手动的从这个内存池里 申请. 申请函数 heap_caps_malloc(…, MALLOC_CAP_INTERNAL )

官方解释如下

由于有些内存缓冲器仅可在内部存储器中分配,因此需要使用第二个配置项
CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL 定义一个内部内存池,仅限显式的内部存储器分配使用(例如用于DMA 的存储器)。常规 malloc() 将不会从该池中分配,但可以使用 MALLOC_CAP_DMA 和 MALLOC_CAP_INTERNAL 标志从该池中分配存储器。

9 是否 允许 .bss 段放入片外存储器 和 允许 .noinit 段放入片外存储器

可以优化内部RAM 建议勾选. 但要注意外部RAM的使用限制.

大概意思是 可以将 应用程序 定义的静态变量 全局变量这些数据 放入外部内存.

官方解释
官方说明地址:https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32/api-guides/external-ram.html#id5


10 当外部 RAM 大于 4M的时候的一个优化选项. (见下图)
小于等于4M外部内存的 应该可以忽略 勾选不勾选都可以.

大概意思是 当外部内存大于 4M的时候 ESP32 寻址空间是有限的. 所以需要 分配一些资源给它 用来扩展寻址空间?? 这个没有细研究 有清楚的 可以留言

11 当时用 xTaskCreateStatic 申请任务时 是否要使用 指定的 外部内存 (不建议勾选)

大概意思是 外部内存 不适用于 任务堆栈 所以尽量不要用. 如果你非要用,要先勾选.

官方解释

因为ESP32代码环境的一些位不能用缓存解决方案重新编译,通常情况下,任务不能安全地在其堆栈驻留在外部内存中运行;因此,xTaskCreate(和相关的任务创建函数)总是在内存中分配堆栈,xTaskCreateStatic将检查传递给它的内存是否在内存中。如果你有一个需要大量堆栈的任务,并且不以任何方式调用ROM代码(没有直接调用,也没有蓝牙/WiFi),你可以尝试使xTaskCreateStatic允许任务在外部内存中堆栈。


12 剩下的这些 基本都是引脚配置

进一步优化内部RAM

如果内部的内存 还是不够用 ,应用程序中使用了 蓝牙和mbedTLS

那么 可以 将 蓝牙和mbedTLS的 内存 配置使用外部的PSARM
搜索 Memory allocation strategy
分别按下图设置 选择外部内存

外部RAM使用限制说明

大概意思就是 外部RAM 有一些功能是不支持的 使用要注意

官方解释:

使用片外 RAM 有下面一些限制:

Flash cache 禁用时(比如,正在写入 flash),片外 RAM 将无法访问;同样,对片外 RAM 的读写操作也将导致 cache
访问异常。出于这个原因,ESP-IDF 不会在片外 RAM 中分配任务堆栈(详见下文)。 片外 RAM 不能用于储存 DMA
事务描述符,也不能用作 DMA 读写操作的缓冲区 (Buffer)。因此,当片外 RAM 启用时,与 DMA 搭配使用的 Buffer
必须先使用 heap_caps_malloc(size, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL)
进行分配,之后可以调用标准 free() 回调释放 Buffer。 片外 RAM 与片外 flash 使用相同的 cache
区域,这意味着频繁在片外 RAM 访问的变量可以像在片上 RAM 中一样快速读取和修改。但访问大块数据时(大于 32 KB),cache
空间可能会不足,访问速度将回落到片外 RAM 访问速度。此外,访问大块数据会挤出 flash cache,可能降低代码执行速度。
一般来说,片外 RAM 不会用作任务堆栈存储器。xTaskCreate() 及类似函数始终会为堆栈和任务 TCB 分配片上储存器。 可以使用
CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY 选项将任务堆栈放入片外存储器。这时,必须使用
xTaskCreateStatic() 指定从片外存储器分配的任务堆栈缓冲区,否则任务堆栈将会从片上存储器分配。

物联沃分享整理
物联沃-IOTWORD物联网 » ESP32使用SPI RAM优化内部内存空间

发表评论