是否可以在 ARM Cortex-M4 架构(例如 STM32 F4)上分离基础固件和应用程序代码。我想做的是从外部闪存运行应用程序,从内部闪存运行基本固件。应用程序都在实现相同的“API”(单个头文件),但功能不同。

想法是基础固件提供驱动程序、引擎和用户界面,并且可以独立工作。应用程序将在需要时为基础固件提供额外的功能。由于所有应用程序的总代码大小对于内部闪存来说太大,因此无法在内部闪存上闪存所有应用程序。另一个原因是我们希望在不重新刷新设备的情况下即时更新/添加应用程序。

所以,到目前为止,我对如何做到这一点几乎没有想法,但是这些方法中的任何一个都可行还是有其他选择?

  • 将应用程序动态加载到内部 SRAM
  • RAM 消耗可能是问题。
  • 不确定基础固件和应用程序代码是否可以“同时”执行。可以从基于 FW 和 wise verse 调用应用程序代码函数吗?我已经看到这种技术与闪存加载器一起使用,但是一旦您开始从 RAM 运行代码,闪存中的代码就无法再执行了?
  • 从外部闪存到内部闪存的闪存应用。
  • 不确定内部闪存将持续多长时间。什么是内部闪存的最大写入周期数。需要更改应用程序 1-20 次/天
  • 从那里执行代码时可以刷入内部闪存的一部分(应用程序加载器)
  • 找到支持内部闪存和外部闪存同时运行代码的Cortex-M4。
  • 我还没有找到,Cortex-M4 架构可能无法找到?

  • 感谢所有提示、提示和示例代码!

    编辑: 感谢您的回答,需要一些时间来消化这些。

    此次试验的主要原因是允许在不刷新基本固件的情况下更新设备功能,而不是节省 SRAM/内部闪存。一种插件架构,提供简单的接口(interface)来扩展系统功能,而无需更改底层系统。如果我无法从外部闪存(SD 卡、NAND)构建系统执行代码,我将首先尝试将应用程序动态加载到 SRAM/内部闪存。但我也会深入挖掘 emcraft 解决方案。

    没有必要坚持使用 STM 芯片,我只是碰巧在我的 table 上有他们的开发套件。最终目标是从 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
    

    我还没有想到最终的操作系统,但很可能是 Free/OpenRTOS

    最佳答案

    问题不在于处理器;在不同的内存空间中执行代码是一个适本地构建、链接和加载代码的问题,这在很大程度上是一个工具链问题,而不是芯片选择问题。

    第一个问题是选择实际具有存储器映射的外部存储器接口(interface)的设备。在这种情况下,例如串行存储设备(如 NAND 闪存)或大容量存储设备(如 SD 卡)均不适用。它必须是系统地址/数据总线上的 NOR 闪存。

    其次,在大多数情况下,外部存储器接口(interface)必须针对正确的存储器类型、总线宽度和时序等进行配置,以便可寻址。这意味着您不能直接启动到外部存储器上的软件,因为软件必须运行才能执行配置。

    第三,通常您的工具链会将您的应用程序编译并链接到一个单一的应用程序中 - 将其分成 BIOS/OS 和应用程序并非易事,对于裸机目标(即不运行完整的操作系统,例如带有加载/执行功能的 Linux)和动态链接等内置)没有标准方法 - 你必须自己做饭。

    对于引导加载程序启动、加载应用程序并运行它的情况,这可能很简单,因为一旦应用程序运行,引导加载程序就不再起作用——引导加载程序只需要知道应用程序的起始地址。但是,在您的情况下,您希望单独编译和链接两个单独的软件实体,并使应用程序能够访问您的 BIOS/OS 代码,因此应用程序实体需要知道独立链接的 BIOS/OS 的例程入口点地址。一种方法是生成 BIOS/OS 的链接映射(特定于工具链),并从中生成与每个应用程序链接的入口点查找表(本质上是函数指针数组),这样您的应用程序将具有回调用 BIOS/OS 的方法。

    然而,您可能不需要这样做,您可以将您的应用程序链接到不相交的内存地址区域并分别对内部和外部存储设备进行编程(有时称为“分散加载”)。这样链接器负责解析内部和外部地址并且在任一方向调用都是可能的。当然,您需要确保配置外部存储器的启动代码在内部存储器中,但可以指示链接器将特定代码放置在特定存储器中或让它决定何时没关系。

    重新刷新代码的需要本身并不需要您描述的架构,您可以简单地实现一个引导加载程序(占用内部闪存的保留页面),它可以从某些来源(如 SD 卡、USB、串行或 NAND 闪存)加载数据,并将其写入适当的内部或外部闪存页面;例如,如果加载的数据是 Intel 格式的 Hex 文件,它将包含地址信息,告诉引导加载程序将数据写入何处。在这种方法中,唯一的永久代码是引导加载程序(它必须配置外部存储器),并且您的 BIOS/OS 和应用程序可以是单一的,并且可以跨内部和外部闪存“分散加载”。

    然而,警告一句 Cortex-M 设备经过优化,可以通过单独的总线执行代码和加载数据。在 STM32 上,内部闪存和内部 SRAM 位于单独的总线上,允许并行进行指令和数据提取。从外部存储器运行代码时,您必须意识到,不仅总线可能会变慢,而且从外部存储器中获取的指令和数据也会被串行化。因此,性能可能会受到重大打击。

    关于c - ARM Cortex-M4 : Running code from external flash,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27945069/

    10-12 21:45