当前位置: 首页 > news >正文

《DNESP32P4开发指南_V1.0》第十章 ESP32-P4存储器类型

第十章 ESP32-P4存储器类型

ESP32-P4芯片具备多种存储器类型及灵活的存储器映射特性。本章节将介绍ESP-IDF如何默认使用这些存储器功能,以优化应用程序性能和资源管理。
本章分为如下几个小节:
10.1 存储器类型概述
10.2 DMA 缓冲区的静态与堆栈内存分配

10.1 存储器类型概述
ESP-IDF将存储器分为指令总线和数据总线。指令总线包括IRAM(指令RAM)、IROM(从Flash中运行的代码)和RTC FAST内存,这些存储器是可执行的,并且只能通过4字节对齐的方式进行读取或写入。数据总线则由DRAM(数据RAM)和DROM(存储在Flash中的数据)组成,这些存储器不可执行,允许单独的字节操作。有关详细信息,请参考ESP32-P4技术参考手册中的“系统和存储器”部分。

1,DRAM(数据RAM)
DRAM用于存放非常量静态数据(.data段)和零初始化数据(.bss段)。链接器会将这些数据放置于内部SRAM中,且该区域的剩余空间可在程序运行时用作堆。使用EXT_RAM_BSS_ATTR宏可将零初始化数据(.bss段)放入外部RAM。要启用此功能,需确保配置了CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY选项,如下图所示。

image001

图10.1.1 允许.bss段放置外部RAM
该配置选项在SDK配置编辑器Component config ESP PSRAM PSRAM config Allow .bss segment placed in external memory路径下定义。启用后,使用EXT_RAM_BSS_ATTR属性的变量将被放置在SPIRAM中。EXT_RAM_BSS_ATTR使用方法如下所示:

#include "esp_attr.h"EXT_RAM_BSS_ATTR uint32_t external_bss_data = 0;/*** @brief       程序入口* @param       无* @retval      无*/
void app_main()
{/* 在此处可以使用external_bss_data */
}

这段代码声明了一个外部RAM变量external_bss_data,使用EXT_RAM_BSS_ATTR宏确保它在外部RAM中存储并初始化为零。

2,IRAM(指令 RAM)
IRAM是存放执行指令的内存区域。内部SRAM中未用于IRAM的部分将作为DRAM供静态数据和动态分配(堆)使用。
1)何时需要将代码放入IRAM
在特定情况下,将部分应用程序代码放入IRAM是有益的。首先,当注册中断处理程序时,如果使用了ESP_INTR_FLAG_IRAM,则该处理程序必须放置于IRAM中,以确保其快速响应。其次,对于时序关键的代码,放入IRAM可以显著减少从Flash加载代码所带来的延迟,从而提升函数性能,确保系统在执行关键任务时的高效性。
2)如何将代码放入IRAM
过链接器脚本,可以自动将特定代码放入IRAM。如果需要手动指定,可以使用IRAM_ATTR宏,如下代码所示:

#include "esp_attr.h"void IRAM_ATTR gpio_isr_handler(void* arg)
{/* 及时相应代码 */
}

需要注意的是,将代码放入IRAM可能会引发安全中断处理程序的问题,因为字符串或常量可能不会自动放入RAM。在这种情况下,应使用DRAM_ATTR属性进行标记,以确保它们正确存储在RAM中,如下示例所示:

void IRAM_ATTR gpio_isr_handler(void* arg)
{const static DRAM_ATTR uint8_t INDEX_DATA[] = { 45, 33, 12, 0 };const static char *MSG = DRAM_STR("I am a string stored in RAM");
}

上述代码中,确定哪些数据需要标记为DRAM_ATTR可能比较困难。如果未标记,某些变量或表达式可能会被编译器识别为常量并放入Flash中。这是因为GCC优化会自动生成跳转表或switch/case查找表。为了解决此问题,可以在ESP-IDF编译时使用-fno-jump-tables -fno-tree-switch-conversion标志,以避免将这些表放入Flash。如果某个源文件不需要放置在IRAM中,可以为该文件重新启用跳转表优化,具体操作请参考乐鑫科技ESP-IDF在线编程指南的构建系统章节中的“组件 CMakeLists 文件”小节。

3,IROM(代码从 flash 中运行)
如果一个函数没有被显式地声明放在IRAM或RTC存储器中,则它将被放置在Flash中。由于IRAM空间有限,大部分应用程序的二进制代码需要放入IROM中。在启动过程中,从IRAM中运行的引导加载程序配置MMU以缓存Flash,将应用程序的指令代码区域映射到指令空间。通过MMU访问的Flash使用一些内部SRAM进行缓存,这使得访问缓存的Flash数据的速度与访问其他类型的内部存储器一样快。

4,DROM(数据存储在 flash 中)
默认情况下,链接器将常量数据放入一个映射到MMU Flash缓存的区域,这个区域与IROM相同,但用于只读数据而非可执行代码。唯一不默认放入DROM的常量数据是那些被编译器嵌入到应用程序代码中的字面常量,这些常量会被放置在周围函数的可执行指令中。
为了强制将常量从DROM放入DRAM(数据RAM)部分,可使用DRAM_ATTR属性,如上文所述。这有助于确保在需要时常量数据能够快速访问,避免因存放在Flash中而引起的延迟。

5,RTC FAST memory(RTC 快速存储器)
除非禁用CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP选项(见下图所示),否则剩余的RTC FAST内存会被添加到堆中。这部分内存可以与DRAM(数据RAM)互换使用,但访问速度略慢一些。这种灵活性允许开发者在内存资源有限的情况下优化应用程序的内存使用。

image003

图10.1.2 启用RTC快速内存区域添加到系统堆
该配置选项允许将RTC快速内存区域添加到系统堆中,具备类似于DRAM区域的功能,但不支持DMA。在堆初始化过程中,早期启动服务和调度相关代码会优先使用这部分内存。从速度上看,RTC快速内存在APB时钟下运行,因此对性能影响不大。这种配置使得在内存紧张的情况下能够更有效地利用可用资源。该配置选项在SDK配置编辑器Component configESP System SettingsCache configEnable RTC fast memory for dynamic allocations路径下定义。

6,紧密耦合内存(TCM)
TCM(紧耦合内存)是靠近CPU的内存,支持在CPU频率下直接访问,无需经过缓存。尽管在一般情况下,TCM的效率或速度相比缓存要低一些,但访问TCM的时间是可预测且始终一致的。这种稳定的访问速度对时间关键型例程尤为重要,因此,TCM在需要精准时序控制的任务中非常有用,可以确保执行的延迟和速度一致。

10.2 DMA 缓冲区的静态与堆栈内存分配
在上一节中我们详细讲解了ESP32-P4的存储器类型概述,介绍了不同存储器(如IRAM、DRAM、TCM等)的特点和用途。在本节中,我们将深入探讨与DMA传输密切相关的缓冲区内存管理问题。具体来说,我们将讨论如何在ESP32-P4上合理分配和使用DMA缓冲区,包括在静态内存和堆栈中放置DMA缓冲区的方式,以及相关的最佳实践和注意事项。通过合理的内存布局,可以有效提高DMA传输的性能和可靠性。
在ESP32开发中,许多DMA控制器(如SPI、SDMMC等)要求发送/接收缓冲区必须放置在DRAM中,并且按字对齐。为了确保DMA传输的稳定性和性能,我们建议将DMA缓冲区放在静态变量中,而不是堆栈中。

1,静态 DMA 缓冲区
静态变量在内存中有固定位置,适合用于DMA传输。可以使用DMA_ATTR宏声明全局或本地静态变量具备DMA能力。如下代码所示;

DMA_ATTR uint8_t buffer[] = "I want to send something";void app_main()
{/* 初始化代码 */spi_transaction_t temp = {.tx_buffer = buffer,.length = 8 * sizeof(buffer),};spi_device_transmit(spi, &temp);/* 其它程序 */
}

此外,如果需要动态分配DMA缓冲区内存,可以使用MALLOC_CAP_DMA标志来确保所分配的内存具备DMA能力。

2,在堆栈中放置 DMA 缓冲区
虽然可以在堆栈中放置DMA缓冲区,但一般建议避免这样做。如果确实需要在堆栈中使用DMA缓冲区,必须注意以下几点:
①:如果堆栈位于PSRAM中,不建议将DRAM缓冲区放置在堆栈中。这种情况下,任务堆栈在PSRAM中时,必须按照片外RAM(请看ESP-IDF编程指南的“片外 RAM”章节)的相关步骤进行特殊处理,以确保DMA传输的正确性和稳定性。
②:在函数中,使用WORD_ALIGNED_ATTR宏修饰变量,确保变量的内存对齐,从而使其可以被DMA正确访问,如下代码所示:

void app_main()
{
uint8_t stuff;
/* 否则 buffer 会被存储在 stuff 变量后面 */WORD_ALIGNED_ATTR uint8_t buffer[] = "I want to send something";  /* 初始化代码spi_transaction_t temp = {.tx_buffer = buffer,.length = 8 * sizeof(buffer),};spi_device_transmit(spi, &temp);/* 其它程序 */
}

至此,ESP32-P4基于ESP-IDF的基础开发部分讲解到这里。在接下来的章节中,我们将深入探讨ESP32-P4各个外设的API及其使用方法,帮助读者更全面地掌握芯片的各项功能,进行高效开发。

http://www.jsqmd.com/news/522066/

相关文章:

  • 细聊金华、义乌生产规模大的保暖内衣制造厂,靠谱的选哪家 - 工业品网
  • 2026年非标水处理项目怎么选供应商?一家具备“方案+制造+安装”全链条能力厂商考察 - 速递信息
  • 深圳高端腕表走时不准原因全解析|2026六城科普,多品牌维修指南(含六城门店) - 时光修表匠
  • STM32F407与USB3300高速U盘存储系统的设计与优化
  • GraphCL实战指南:基于增强技术的图对比学习应用解析
  • 黑丝空姐-造相Z-Turbo创意无限:社区精选Prompt生成作品画廊
  • 苹果、谷歌、三星中端手机竞争白热化,谁能突出重围?
  • CentOS7下Tailscale子网路由配置全攻略:从安装到内网穿透实战
  • 不想上门收酒被熟人撞见?京城亚南酒业:低调上门,全程无声交易 - 品牌排行榜单
  • 2026年西南地区保温材料厂家综合盘点:从区域竞争力与产品矩阵看成都实力派推荐 - 速递信息
  • 基础网页项目练习
  • 别再低效抓汇率!专业 API 实操分享
  • 手把手教你玩转Nginx:三种虚拟主机配置,这才是高手标配
  • RAGFlow实战:解决DeepSeekR1模型配置中的102错误(Ollama端口避坑指南)
  • 粮食气力输送装置与密相气力输送生产线:选购指南与靠谱厂家推荐 - 工业品网
  • 杭州进水急救全攻略:从百达翡丽到欧米茄,高端腕表进水后的黄金救援时间与北上广深杭宁六城紧急处置指南 - 时光修表匠
  • 无锡高端腕表保养周期全科普|2026六城网点适配,多品牌保养指南(含维修品类 - 时光修表匠
  • 粉体气力输送系统:行业优势尽显,靠谱品牌推荐 - myqiye
  • 多光谱无人机追踪的5大常见误区:从MUST数据集看如何避免新手踩坑
  • STM32实战指南:从零构建智能窗户控制系统(硬件选型+软件逻辑+数据可视化)
  • 你家需要哪种电梯?2026电梯、别墅电梯、自建房电梯、乘客电梯、载货电梯、更新改造电梯、四川电梯场景化服务商适配分析 - 速递信息
  • ArcGIS地统计分析Geostatistical Analyst交叉验证实战指南
  • 物理的两个世界:测量世界和现实世界
  • 工厂采购必看:2026年锅炉设备口碑推荐,一家西南区域服务商的场景化解构 - 速递信息
  • 手机远程操控Windows与Ubuntu:VNC连接实战指南
  • AI程序员 - --
  • 2025年12月大学英语六级真题及答案电子版pdf三套全
  • SeqGPT-560M效果展示:新闻通稿中自动识别机构、事件、时间三元组
  • 2026年服务好的DN1200企口管源头厂家,顶管建设的好帮手,检查井/预制混:凝土电力井/雨水收集井,顶管直销厂家分析 - 品牌推荐师
  • 防尘防爆接线箱厂家技术揭秘:高粉尘环境下,如何实现“零故障”运行? - 品牌推荐大师