是否可以在 ARM Cortex-M4 架构(例如 STM32 F4)上分离基础固件和应用程序代码。我想做的是从外部闪存运行应用程序,并从内部闪存运行基本固件。应用程序都在实现相同的“API”(单个头文件),但功能不同。
想法是基础固件提供驱动程序、引擎和用户界面,并且可以独立工作。应用程序会在需要时为基础固件提供额外的功能。由于所有应用程序的总代码大小对于内部闪存来说太大,因此无法在内部闪存上刷新所有应用程序。另一个原因是我们希望在不重新刷新设备的情况下即时更新/添加应用程序。
所以,到目前为止,我对如何做到这一点几乎没有什么想法,但是这些可行还是有其他选择?
感谢所有提示、提示和示例代码!
编辑:感谢您的回答,需要一些时间来消化这些。
进行此试验的主要原因是允许在不刷新基本固件的情况下更新设备功能,而不是节省 SRAM/内部闪存。一种插件架构,提供简单的接口(interface)来扩展系统功能,而无需更改底层系统。如果我无法从外部闪存(SD 卡、NAND)构建执行代码的系统,我将尝试首先将应用程序动态加载到 SRAM/内部闪存。但我也会深入挖掘 emcraft 解决方案。
没有必要坚持使用 STM 芯片,我只是碰巧在我的 table 上放了他们的开发套件。最终目标是从 SD 卡或 NAND 内存加载应用程序,因此在这一点上,我不想将实现限制为仅适用于 NOR 闪存。
我将使用 STM32 F4 devkit 开始以最小的实现工作。首先,我需要在上面包裹一些 NAND/SD 卡。我将尝试两种将应用程序加载到 SRAM 和内部闪存的选项,以了解它们是如何工作的以及对性能的影响。正如克利福德所说,挑战将更多地在于链接、构建和工具集设置。即使很难,我也可以强制应用程序始终在内存中的同一位置,功能将在不同的位置,需要弄清楚如何处理这个问题。示例/演示会有所帮助。
规范我的最小实现。
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/