外部RAM工作和内存管理
External RAM working and memory management
对于同样具有内部 RAM 的 MCU,如何利用外部 RAM?
可以在外部 RAM 中创建 stack/heap 等区域吗?
如何link/execute在外部RAM中运行? (Keil 4 IDE)
内存将按照分散文件或链接描述文件中定义的方式使用 - 它与 MCU 和 internal/external RAM 没有任何关系。
您在分散文件中描述您平台上的可用物理内存区域(各种工具链可能使用不同的术语,例如链接器脚本),并为每个部分分配属性以告知链接器每个内存可能用于什么以及可能明确地将某些代码或数据项定位到特定部分。
链接器不会在您未通知它的内存中定位任何内容。您可能希望以相同的方式处理所有内存并让链接器自由支配以分配它喜欢的地方,但对于 MCU,这可能不是最佳选择。例如,内部内存总线可能比外部内存总线更快,因此您可以将时间关键型处理限制在该总线上。如果您让链接器按其选择进行分配,那么如果将某些关键对象移至较慢的内存,对代码的修改可能会显着改变性能。
即使在内部 RAM 中,该部件也可以将其分成具有独立总线的不同区域,例如,您可以使用专门用于 DMA 的区域来减少或消除总线争用。
因此,虽然您的工具链为您的部分提供的一些默认链接描述文件可能适合一般用途,但如果您对内部、外部、QSPI 等有复杂的内存要求。运行以不同的速度和不同的属性,您可能希望自定义脚本以充分利用可用资源。
具体在Keil中,可以在项目配置"Target"选项卡中分配基本内存区域安排:
在这种情况下,您可以在 RAM1/2/3 字段中添加外部存储器。
对于更复杂的要求(例如创建命名部分),在链接器选项卡中:
您需要取消选中 "Use Memory Layout from Target dialog" 框,然后针对分散文件单击 "Edit"(或提供新的分散文件路径)。默认的分散文件是由您在目标对话框中的设置创建的,但现在您已将其解耦,以便您可以根据需要对其进行自定义。
需要注意的一件事是,访问外部存储器通常需要正确配置外部存储器控制器(例如分配总线引脚和设置正确的总线时序)。如果链接器要分配此类内存的使用,重要的是在 C 或 C++ 运行-time 执行应用程序内存初始化之前,在 运行-time 启动代码中配置内存启动代码。通常至少在开始时系统堆栈必须放在内部存储器中,因为启动代码可能在外部存储器初始化之前就需要一个堆栈。稍后可以在 C 运行 时间开始之前移动系统堆栈,但如果您使用的是 RTOS,则可能没有必要,因为在外部存储器工作后每个任务都会建立自己的堆栈。除了在系统堆栈也是中断堆栈的部分之外,您会希望它位于最快和最可靠(在可用性意义上)的内存中。
另一个考虑因素是 ARM Cortex-M 等架构具有用于代码和数据的独立总线,这允许它们同时获取指令和数据。如果将代码放在数据 RAM 中,则可能会显着减慢执行速度,因为必须按顺序从同一内存中提取指令和数据。再加上外部存储器的总线速度通常较低,您可能需要谨慎地将代码放置在外部 RAM(或实际上任何 RAM)中执行。在某些部件上——通常是那些采用冯诺依曼架构的部件,RAM 执行比从 ROM 执行更快,但对于采用哈佛架构总线和闪存加速器或缓存的部件,情况不一定如此。所以不要假设在外部 RAM 中定位代码会有好处。
对于同样具有内部 RAM 的 MCU,如何利用外部 RAM?
可以在外部 RAM 中创建 stack/heap 等区域吗?
如何link/execute在外部RAM中运行? (Keil 4 IDE)
内存将按照分散文件或链接描述文件中定义的方式使用 - 它与 MCU 和 internal/external RAM 没有任何关系。
您在分散文件中描述您平台上的可用物理内存区域(各种工具链可能使用不同的术语,例如链接器脚本),并为每个部分分配属性以告知链接器每个内存可能用于什么以及可能明确地将某些代码或数据项定位到特定部分。
链接器不会在您未通知它的内存中定位任何内容。您可能希望以相同的方式处理所有内存并让链接器自由支配以分配它喜欢的地方,但对于 MCU,这可能不是最佳选择。例如,内部内存总线可能比外部内存总线更快,因此您可以将时间关键型处理限制在该总线上。如果您让链接器按其选择进行分配,那么如果将某些关键对象移至较慢的内存,对代码的修改可能会显着改变性能。
即使在内部 RAM 中,该部件也可以将其分成具有独立总线的不同区域,例如,您可以使用专门用于 DMA 的区域来减少或消除总线争用。
因此,虽然您的工具链为您的部分提供的一些默认链接描述文件可能适合一般用途,但如果您对内部、外部、QSPI 等有复杂的内存要求。运行以不同的速度和不同的属性,您可能希望自定义脚本以充分利用可用资源。
具体在Keil中,可以在项目配置"Target"选项卡中分配基本内存区域安排:
在这种情况下,您可以在 RAM1/2/3 字段中添加外部存储器。
对于更复杂的要求(例如创建命名部分),在链接器选项卡中:
需要注意的一件事是,访问外部存储器通常需要正确配置外部存储器控制器(例如分配总线引脚和设置正确的总线时序)。如果链接器要分配此类内存的使用,重要的是在 C 或 C++ 运行-time 执行应用程序内存初始化之前,在 运行-time 启动代码中配置内存启动代码。通常至少在开始时系统堆栈必须放在内部存储器中,因为启动代码可能在外部存储器初始化之前就需要一个堆栈。稍后可以在 C 运行 时间开始之前移动系统堆栈,但如果您使用的是 RTOS,则可能没有必要,因为在外部存储器工作后每个任务都会建立自己的堆栈。除了在系统堆栈也是中断堆栈的部分之外,您会希望它位于最快和最可靠(在可用性意义上)的内存中。
另一个考虑因素是 ARM Cortex-M 等架构具有用于代码和数据的独立总线,这允许它们同时获取指令和数据。如果将代码放在数据 RAM 中,则可能会显着减慢执行速度,因为必须按顺序从同一内存中提取指令和数据。再加上外部存储器的总线速度通常较低,您可能需要谨慎地将代码放置在外部 RAM(或实际上任何 RAM)中执行。在某些部件上——通常是那些采用冯诺依曼架构的部件,RAM 执行比从 ROM 执行更快,但对于采用哈佛架构总线和闪存加速器或缓存的部件,情况不一定如此。所以不要假设在外部 RAM 中定位代码会有好处。