c - 外部 RAM 工作和内存管理
问题描述
对于也具有内部 RAM 的 MCU,如何使用外部 RAM?
可以在外部 RAM 中创建堆栈/堆等区域吗?
如何链接/执行外部 RAM 中的功能?(基尔 4 IDE)
解决方案
内存将以分散文件或链接器脚本中定义的方式使用 - 它与 MCU 和内部/外部 RAM 无关。
您在分散文件中描述平台上可用的物理内存区域(各种工具链可能使用不同的术语,例如链接器脚本),并为每个部分分配属性以告知链接器每个内存可以用于什么,并可能显式定位某些代码或特定部分的数据项。
链接器不会在您未通知它的内存中找到任何内容。您可能希望以相同的方式处理所有内存,并让链接器自由支配以随意分配,但对于 MCU,这可能不是最佳选择。例如,内部存储器总线可能比外部存储器总线更快,因此您可能会将时间关键型处理限制在此范围内。如果您让链接器按照它的选择进行分配,那么如果某些关键对象被移动到较慢的内存中,对代码的修改可能会显着改变性能。
即使在内部 RAM 中,该部分也可以将其划分为具有独立总线的不同区域,例如,您可以使用专门用于 DMA 的区域来减少或消除总线争用。
因此,虽然您的工具链为您提供的某些默认链接器脚本可能适合一般用途,但如果您有复杂的内存要求,内部、外部、QSPI 等以不同的速度和不同的属性运行,您可能需要自定义脚本以充分利用现有资源。
具体来说,在 Keil 中,您可以在项目配置“目标”选项卡中分配基本内存区域排列:
在这种情况下,您可以在 RAM1/2/3 字段中添加外部存储器。
对于更复杂的要求(例如创建命名节),在链接器选项卡中: 您需要取消选中“从目标对话框中使用内存布局”框,然后针对分散文件单击“编辑”(或提供新的分散文件小路)。默认分散文件是由您在目标对话框中的设置创建的,但现在您已将其解耦,以便您可以根据需要对其进行自定义。
需要注意的一点是,访问外部存储器通常需要正确配置外部存储器控制器(例如分配总线引脚和设置正确的总线时序)。如果链接器要分配此类内存的使用,重要的是在 C 或 C++ 运行时启动代码执行应用程序内存初始化之前,在运行时启动代码中配置内存。通常至少最初需要将系统堆栈放置在内部存储器中,因为启动代码可能在外部存储器初始化之前需要一个堆栈。稍后可以在 C 运行时开始之前移动系统堆栈,但如果您使用的是 RTOS,则可能没有必要这样做,因为每个任务都会在外部存储器工作后建立自己的堆栈。
另一个考虑因素是 ARM Cortex-M 等架构具有用于代码和数据的单独总线,这允许它们同时获取指令和数据。如果将代码放在数据 RAM 中,则可能会显着减慢执行速度,因为必须按顺序从同一内存中提取指令和数据。再加上外部存储器的总线速度通常较低,您可能需要谨慎地将代码放置在外部 RAM(或实际上是任何 RAM)中执行。在某些部分——通常是冯诺依曼架构的部分,RAM 执行比从 ROM 执行要快,但对于哈佛架构总线和闪存加速器或缓存的部分,情况不一定如此。所以不要以为在外部 RAM 中定位代码会有好处。
推荐阅读
- javascript - 如何在网站上制作一个随机传送的按钮onclick
- sql-server-2012 - 如何将多个select语句合并到一个表中
- sql - 当布尔变量改变他的状态时引发事件
- python - Python 中 {ab, abc}* 的非确定性有限自动机
- python - 最佳 tkinter 文件结构
- python - Python:从记事本复制文本,然后粘贴到网页中的特定框中?
- perl - 如果有人可以帮助我,我正在尝试理解代码片段中的语句
- asp.net - 使用生成器将新行插入 Firebird 数据库
- jquery - 我的对象没有使用 jQuery 的 ASP.NET MVC 发布
- android - 安卓。领域层包括什么?