首页 > 解决方案 > 外部 RAM 工作和内存管理

问题描述

对于也具有内部 RAM 的 MCU,如何使用外部 RAM?

可以在外部 RAM 中创建堆栈/堆等区域吗?

如何链接/执行外部 RAM 中的功能?(基尔 4 IDE)

标签: cembeddedmicrocontrollerram

解决方案


内存将以分散文件或链接器脚本中定义的方式使用 - 它与 MCU 和内部/外部 RAM 无关。

您在分散文件中描述平台上可用的物理内存区域(各种工具链可能使用不同的术语,例如链接器脚本),并为每个部分分配属性以告知链接器每个内存可以用于什么,并可能显式定位某些代码或特定部分的数据项。

链接器不会在您未通知它的内存中找到任何内容。您可能希望以相同的方式处理所有内存,并让链接器自由支配以随意分配,但对于 MCU,这可能不是最佳选择。例如,内部存储器总线可能比外部存储器总线更快,因此您可能会将时间关键型处理限制在此范围内。如果您让链接器按照它的选择进行分配,那么如果某些关键对象被移动到较慢的内存中,对代码的修改可能会显着改变性能。

即使在内部 RAM 中,该部分也可以将其划分为具有独立总线的不同区域,例如,您可以使用专门用于 DMA 的区域来减少或消除总线争用。

因此,虽然您的工具链为您提供的某些默认链接器脚本可能适合一般用途,但如果您有复杂的内存要求,内部、外部、QSPI 等以不同的速度和不同的属性运行,您可能需要自定义脚本以充分利用现有资源。

具体来说,在 Keil 中,您可以在项目配置“目标”选项卡中分配基本内存区域排列:

在此处输入图像描述

在这种情况下,您可以在 RAM1/2/3 字段中添加外部存储器。

对于更复杂的要求(例如创建命名节),在链接器选项卡中: 在此处输入图像描述 您需要取消选中“从目标对话框中使用内存布局”框,然后针对分散文件单击“编辑”(或提供新的分散文件小路)。默认分散文件是由您在目标对话框中的设置创建的,但现在您已将其解耦,以便您可以根据需要对其进行自定义。

需要注意的一点是,访问外部存储器通常需要正确配置外部存储器控制器(例如分配总线引脚和设置正确的总线时序)。如果链接器要分配此类内存的使用,重要的是在 C 或 C++ 运行时启动代码执行应用程序内存初始化之前,在运行时启动代码中配置内存。通常至少最初需要将系统堆栈放置在内部存储器中,因为启动代码可能在外部存储器初始化之前需要一个堆栈。稍后可以在 C 运行时开始之前移动系统堆栈,但如果您使用的是 RTOS,则可能没有必要这样做,因为每个任务都会在外部存储器工作后建立自己的堆栈。

另一个考虑因素是 ARM Cortex-M 等架构具有用于代码和数据的单独总线,这允许它们同时获取指令和数据。如果将代码放在数据 RAM 中,则可能会显着减慢执行速度,因为必须按顺序从同一内存中提取指令和数据。再加上外部存储器的总线速度通常较低,您可能需要谨慎地将代码放置在外部 RAM(或实际上是任何 RAM)中执行。在某些部分——通常是冯诺依曼架构的部分,RAM 执行比从 ROM 执行要快,但对于哈佛架构总线和闪存加速器或缓存的部分,情况不一定如此。所以不要以为在外部 RAM 中定位代码会有好处。


推荐阅读