ESP32的IRAM和DRAM

ESP32-S3 的 RAM 结构是其高性能和灵活性的关键之一。理解 IRAM 和 DRAM 对于进行高效编程、优化性能以及解决某些内存相关的疑难杂症至关重要。

总览

ESP32-S3 具有丰富且可配置的片上 RAM。其大小取决于具体型号,常见的有:

  • ​ESP32-S3​​:512 KB SRAM

  • ​ESP32-S3(大容量型号)​​:高达 2 MB 的片上 SRAM

这些 RAM 在物理上由多个内存块组成,但从逻辑和功能上,开发者主要关注它们被映射到的两个关键总线区域:​​IRAM​​ 和 ​​DRAM​​。


1. IRAM (Instruction RAM)

​IRAM​​ 是​​指令 RAM​​。顾名思义,这片内存区域的主要用途是存放需要被 CPU 执行的​​机器指令(代码)​​。

关键特性:
  • ​连接总线​​:连接到 ESP32-S3 的 CPU(Xtensa LX7)的 ​​IBus​​ 和 ​​DBus​​。这意味着 CPU 可以从这片内存中高效地​​取指​​(Fetch Instructions)和​​读/写数据​​。

  • ​可执行​​:这是 IRAM 最核心的特征。只有存放在 IRAM 中的代码才能被 CPU 直接执行。

  • ​速度​​:由于与 CPU 内核距离近且通过专用总线连接,访问速度非常快。

什么代码需要放在 IRAM 中?

不是所有代码都需要放在 IRAM 里,因为 IRAM 空间相对有限。通常,以下情况需要将代码强制放入 IRAM:

  1. ​中断处理程序 (Interrupt Handlers)​​:当中断发生时,CPU 需要立即响应并执行中断服务程序 (ISR)。如果 ISR 的代码存放在外部 SPI Flash 中,而 Flash 又恰好在执行写操作或缓存未命中,就会导致中断响应延迟,这是不可接受的。因此,必须将中断处理程序放入 IRAM 以确保其随时可被立即执行。

  2. ​Flash 操作期间的代码​​:当需要对 SPI Flash 进行擦除、写入等操作时,正在执行的代码​​不能​​位于 Flash 中,否则 CPU 去取指时会发现 Flash 正“忙”而无法访问,导致程序崩溃。所以,执行 spi_flash_*这类操作的函数必须放在 IRAM 中。

  3. ​对实时性要求极高的代码​​:避免从 Flash 取指带来的缓存不确定性,将关键性能代码放入 IRAM 可以保证最稳定的执行速度。

如何将代码放入 IRAM(以 ESP-IDF 为例)?

在 ESP-IDF 开发框架中,你可以使用宏来指定函数存放的位置:

#include "esp_attr.h"

// 使用 IRAM_ATTR 宏将该函数放入 IRAM 区域
void IRAM_ATTR my_fast_function(void) {
    // 这里的代码将被链接到 IRAM 中
}

2. DRAM (Data RAM)

​DRAM​​ 是​​数据 RAM​​。这片内存区域的主要用途是存放​​变量数据​​。

关键特性:
  • ​连接总线​​:主要连接到 CPU 的 ​​数据总线 (DBus)​​。CPU 可以读写这片内存中的数据,但​​不能直接从这片内存中取指执行​​。

  • ​不可执行​​:这是与 IRAM 的根本区别。如果尝试跳转到 DRAM 地址去执行代码,会导致硬件异常。

  • ​用途​​:存放所有全局变量、静态变量、堆(heap)和栈(stack)等数据。

DRAM 的细分:D/IRAM

ESP32-S3 的物理内存非常灵活,可以通过配置 Cache 和 MMU,将一大块连续的物理 RAM 映射到不同的总线地址上。

我们通常说的 DRAM 在软件上可以细分为两个区域:

  • ​DRAM​​ (0x3FC8_0000~ ...): 这是​​数据内存​​的默认区域。你的所有普通变量、堆栈都分配在这里。

  • ​D/IRAM​​ (0x3FC8_0000~ ... 的一部分): 这是一块特殊的区域,它既可以被映射为 ​​DRAM​​(用于存放数据),也可以被​​重新映射​​为 ​​IRAM​​(用于存放可执行代码)。系统启动时,Bootloader 和 ESP-IDF 会根据配置决定如何划分这块物理 RAM 给 IRAM 和 DRAM 使用。

​简单理解​​:有一块物理内存池,开发者可以决定从中划出多少给 IRAM(放代码),剩下的全部给 DRAM(放数据)。在 sdkconfig中调整 IRAM 大小,实际上就是在调整这个划分比例。


IRAM 与 DRAM 对比总结

特性

IRAM (Instruction RAM)

DRAM (Data RAM)

​主要用途​

存放​​可执行代码​

存放​​变量数据​

​可执行性​

​可执行​

​不可执行​

​存放内容​

函数(特别是中断、Flash 操作相关函数)

全局变量、静态变量、堆(heap)、栈(stack)

​访问总线​

IBus (取指), DBus (读/写数据)

DBus (读/写数据)

​宏标识​

IRAM_ATTR

默认位置,或 DRAM_ATTR(用于非缓存地址)

​地址范围​

0x4037xxxxx0x4004xxxx

0x3FCExxxxx0x3FFExxxxx


一个重要的相关概念:DCache 和 ICache

为了提高性能,ESP32-S3 具有高速缓存:

  • ​ICache (指令缓存)​​:缓存从外部 Flash 中取出的指令,然后提供给 CPU 执行。

  • ​DCache (数据缓存)​​:缓存从外部 Flash 或 RAM 中存取的数据。

CPU 执行代码的​​默认流程​​是:

  1. 代码被编译后存储在外部 SPI Flash 中。

  2. 上电后,CPU 需要执行代码时,ICache 会将 Flash 中的代码缓存到片内。

  3. CPU 从 ICache 中高速读取指令并执行。

而我们将代码放入 IRAM,实际上是​​绕过​​了“Flash -> ICache”这个过程,让代码直接存在于片内 RAM 中,CPU 可以无延迟、无不确定性地直接访问,从而满足了实时性和可靠性的要求。

总结:

  • ​普通函数和变量​​:无需特殊处理,编译器会将其放在 Flash 和 DRAM 中,通过 Cache 机制高效运行。这是绝大多数代码的情况。

  • ​中断服务程序​​:必须使用 IRAM_ATTR宏将其放入 IRAM。

  • ​操作 Flash 的函数​​:必须使用 IRAM_ATTR宏。

  • ​需要极致性能的代码​​:可以考虑放入 IRAM 以避免缓存未命中,但会占用宝贵的 IRAM 空间。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值