ARM Cortex-M4:从外部闪存运行代码

7
在ARM Cortex-M4架构(例如STM32 F4)上是否可能分离基础FW和应用程序代码?我的想法是从外部闪存运行应用程序,而从内部闪存运行基础FW。所有应用程序都实现相同的“API”(单个头文件),但功能不同。
基础FW提供驱动程序、引擎和UI,并可以作为独立运行。当需要时,应用程序将为基础FW提供额外的功能。所有应用程序不能全部烧录到内部闪存中,因为所有应用程序的总代码大小对于内部闪存来说太大了。另一个原因是我们希望在不重新烧录设备的情况下即可更新/添加应用程序。
到目前为止,我有一些如何做到这一点的想法,但这些想法是否可行或是否有其他选择?
1. 将应用程序动态加载到内部SRAM中 - RAM消耗可能会成为问题。 - 不确定基础FW和应用程序代码是否可以同时执行。应用程序代码函数可以从基础FW中调用,反之亦然吗?我已经看到过使用flash-loader的技术,但一旦你开始从RAM中运行代码,就不能再执行来自flash的代码了?
2. 从外部闪存将应用程序烧录到内部闪存中。 - 不确定内部闪存的寿命有多长。内部闪存的最大写入次数是多少?需要每天更改应用程序1-20次。 - 当从中执行代码(应用程序加载器)时,是否可以烧录内部闪存的一部分?
3. 查找支持在内部闪存和外部闪存同时运行代码的Cortex-M4。 - 我没有找到任何可能性,可能不可能使用Cortex-M4架构?
欢迎提供所有提示、建议和示例代码!
编辑:感谢回答,需要一些时间来消化这些。
这个试验的主要原因是允许更新设备功能而无需刷新基础FW,而不是为了节省SRAM/内部闪存。这是一种插件架构,提供简单的接口以扩展系统功能,而无需修改底层系统。如果我不能构建执行来自外部闪存(SD卡、NAND)的代码的系统,我将首先尝试将应用程序动态加载到SRAM/内部闪存中。但我也会深入挖掘emcraft解决方案。
没有必要坚持使用STM芯片,我只是碰巧在我的桌子上有他们的开发套件。最终目标是从SD卡或NAND存储器加载应用程序,因此在这一点上,我不想限制实现仅适用于NOR闪存。
我将使用STM32 F4 devkit进行最小实现。首先,我需要在其上包装一些NAND/SD卡。我将尝试将应用程序加载到SRAM和内部闪存中的两个选项,以查看它们的工作原理以及对性能的影响。正如Clifford所说,挑战更多地在于链接、构建和工具集设置。即使我可以强制应用程序始终位于内存的同一位置,但函数将位于不同的位置,需要找出如何处理这个问题。示例/演示将很有帮助。

我的最小实现规范。

Project 1: Base FW
    Driver for accessing applications from external flash
    Minimal filesystem to write and read applications to/from external flash
    UART commands -- Write applications to external flash -- Load applications from external flash to SRAM/Internal flash -- Execute application and print result to UART
Interface.h
    int functionWrapper(int functionNumber)
    bool initApplication()
    int executeMathOperation1(int a, int b)
    int executeMathOperation2(int a, int b)
Project 2: Application 1
    MathOp1: Sums up two values
    MathOp2: Multiply up two values
Project 3: Application 2
    MathOp1: Subtracts two values
    MathOp2: Divide two values

我还没有确定最终的操作系统,但很可能会选择自由/开放源代码的RTOS。

4个回答

9
问题不在于处理器;在不同的内存空间中执行代码是建立、链接和适当加载代码的问题,这在很大程度上是一个工具链问题,而不是芯片选择的问题。
首先,选择一个实际具有内存映射的外部存储器接口的设备是第一个问题。例如,在这种情况下,串行存储器设备如NAND闪存或大容量存储设备如SD卡都不适用。必须使用系统地址/数据总线上的NOR闪存。
其次,在大多数情况下,必须为正确的内存类型、总线宽度和时序等配置外部存储器接口,以便进行寻址。这意味着您不能直接从外部存储器启动软件,因为必须运行软件才能执行配置。
第三,通常您的工具链将编译和链接应用程序成为单个单调的应用程序——将其分离为BIOS/OS和应用程序并不是微不足道的,并且对于裸机目标(即不运行具有内置的加载/执行和动态链接等功能的完整操作系统,例如Linux)没有标准方法——您必须自己开发。
对于启动引导程序启动、加载应用程序并运行的情况,可能很简单,因为一旦应用程序运行,引导程序就不再起作用——引导程序只需要知道应用程序的起始地址。但是在您的情况下,您希望单独编译和链接两个独立的软件实体,并且使应用程序能够访问您的BIOS/OS代码,因此应用程序实体需要知道独立链接的BIOS/OS的例行入口地址。一种方法是生成BIOS/OS的链接映射(这是特定于工具链的),并从中生成一个入口点查找表(本质上是一个函数指针数组),将其与每个应用程序链接。这样,您的应用程序将具有回调BIOS/OS的手段。
然而,您可能不需要这样做,您可以将应用程序链接到不相交的内存地址区域,并分别对内部和外部存储器设备进行编程(有时称为“散布加载”)。这样,链接器负责解析内部和外部地址,并且可以在任何方向上进行调用。当然,您需要确保配置外部存储器的启动代码位于内部存储器中,但是可以指示链接器将特定代码放置在特定存储器中,或者在不重要时让它决定。
需要重新刷新代码并不需要您所描述的架构,您可以简单地实现一个引导程序(占用内部闪存的预留页面),该引导程序可以从某些源(如SD卡、USB、串行或NAND闪存)加载数据,并将其写入适当的内部或外部闪存页面;如果加载的数据例如是Intel格式的Hex文件,则其中包含地址信息,告诉引导程序应该在哪里写入数据。在这种方法中,唯一的永久代码是引导程序(必须配置外部存储器),您的BIOS/OS和应用程序可以成为单体并“散布”加载到内部和外部闪存中。

然而,需要注意的是Cortex-M设备针对执行代码和加载数据进行了优化。在STM32上,内部闪存和内部SRAM位于不同的总线上,允许指令和数据获取并行进行。当从外部存储器运行代码时,你必须意识到,不仅总线可能会变慢,而且来自外部存储器的指令和数据获取将被串行化。因此,性能可能会受到显着影响。


2022年4月更新 具有QSPI存储器控制器的MCU可以从QSPI闪存中执行代码(尽管与正常地址/数据总线并行存储器相比速度较慢)。与普通的串行(SPI或I2C)或NAND闪存不同,QSPI存储器为读取访问进行了内存映射,因此可以包含直接执行的代码。


1
+1,非常感谢您提供的出色答案。我知道这是一个旧问题,但我想问您:当STM32F4设备支持从外部闪存执行代码时,这实际上意味着什么?是否还应该始终具有相同大小的RAM以支持并行闪存中的外部内存代码执行? - User323693

3

编辑:实际上,你的芯片有外部存储映射(FMC/FSMC),这将允许直接执行,所以如果你能让它正常工作,这可能是最简单的方法。

如果你选择继续使用这个芯片,将整个应用程序加载到SRAM可能是最简单的。在RAM和Flash执行之间跳转不是问题,因为RAM和Flash被映射到不同的地址。为了使事情更简单,你应该始终将应用程序加载到同一RAM地址,并且你的应用程序需要构建在此特定地址上运行(通常使用链接器设置完成)。你可以尝试实现一个部分加载系统,这可以在需要时加载应用程序的某些部分,但这需要一些努力,对于设计主机FW和构建应用程序都是如此。

写入内部闪存可能有效,如果你的RAM空间有限,那么内部闪存可能更可取。通常,在执行过程中可以写入内部闪存,但这经常导致CPU停顿(CPU等待闪存操作完成),这可能不是一个问题。如果你查看芯片数据手册,闪存被表征为最小10,000次擦除/写入周期。这意味着,如果你的芯片应该持续5年,你应该每天加载不到6个应用程序(你可以合理地将此数量翻倍,甚至更多,以获得典型的耐久性,但没有任何保证)。


你为什么认为STM32F4芯片不能执行来自外部存储器的代码?Cortex-M没有代码和数据空间的概念。并非所有的STM32部件都有外部存储器接口,但这里可能不是这种情况。 - Clifford
@Clifford,我刚刚查看了数据手册,所以我知道。这个特定芯片上没有外部存储器的内存映射。 - ElderBug
STM32F4 参考手册 第37节 - FMC 支持 NOR Flash、SRAM 和 SDRAM。 - Clifford
@ Clifford 对不起,这个芯片实际上有一个外部存储器映射。 - ElderBug

1
cortex-m4与你所谈论的内容无关,像所有arm处理器内核一样,cortex-m4只是一个处理器内核而已,arm制造IP而非芯片。您必须查看芯片供应商的实现,他们是否提供在外部闪存接口上执行代码的能力。我认为不会,就像很难找到从外部RAM执行的微控制器一样,但这些比闪存更常见。几乎所有的产品都可以复制、运行或烧录,运行在内部芯片资源上的代码将外部资源的代码复制到某些内部资源(ROM/RAM)中,然后在那里运行它,该代码可以再次复制、跳转或返回到主芯片固件以复制和加载下一个叠加层。
芯片供应商应该能够告诉您闪存的寿命,闪存会磨损,设计成经常/不断擦除和写入闪存的代码将在几天、几周或几个月内磨损该部分,具体取决于您对闪存的使用情况。当电源丢失时将状态保存到PROM或闪存中,例如车辆上的里程表读数,这是可以的,每天一次或几次,或者可能是每几年一次,但保存每十英里将在车辆寿命之前磨损该部分。

m4s很难被称为微控制器,因为它们内部拥有所有的功能(浮点、缓存、类似于mmu的东西等),相对于cortex-m0兄弟来说,m4s往往拥有更多的ram和flash。因此,最好的选择是选择一个带有更多ram的芯片,并进行复制和跳转。你应该能够找到许多适合你的部件...


很确定他在谈论STM32F4。 - Ospho

0

有一些使用Cortex M3/M4微控制器的实现,其中内部固件仅用于配置外部RAM并将其映射到内部存储器映射,然后从外部介质(如闪存芯片、SD卡等)加载主程序到此RAM并从中执行(几乎像基于ARM处理器的Linux板一样,其中内部固件只是一个初始引导加载程序)

这家公司做到了这一点: http://www.emcraft.com/

看一下,他们甚至使用STM32F4

最大的问题是Cortex M没有MMU,因此您无法在上面运行完整的Linux,将其限制为uClinux

编辑:这篇文章对您也应该很有帮助: http://electronicdesign.com/embedded/practical-advice-running-uclinux-cortex-m3m4


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接