是否可以在ARM Cortex-M4架构(例如STM32 F4)上分离基本FW和应用程序代码。我想做的是从外部闪存运行应用程序和从内部闪存基础FW。应用程序都实现相同的“API”(单头文件),但功能不同。
理念是基础FW提供驱动程序,引擎和UI,并且可以独立运行。应用程序将在需要时为FW提供额外的功能。由于所有应用程序的总代码大小对于内部闪存而言太大,因此无法在内部闪存上刷新所有应用程序。另一个原因是我们想要在不重新刷新设备的情况下即时更新/添加应用程序。
所以,到目前为止,我几乎没有想法如何做到这一点,但这些是可行的还是有其他选择?
赞赏所有提示,提示和示例代码!
编辑:感谢您的回答,需要一些时间来消化它们。
此试验的主要原因是允许更新设备功能而不闪烁基本FW,而不是保存SRAM /内部闪存。一种插件架构,提供简单的界面来扩展系统功能,而无需改变底层系统。如果我无法从外部闪存(SD卡,NAND)构建系统执行代码,我将尝试首先将应用程序加载到SRAM /内部闪存。但我也会深入挖掘emcraft解决方案。
没有必要坚持STM芯片,我恰好在我的桌子上有他们的devkits。最终目标是从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
答案 0 :(得分:8)
问题不在于处理器;在不同的内存空间中执行代码是一个适当构建,链接和加载代码的问题,这在很大程度上是一个工具链问题,而不是芯片选择问题。
第一个问题是选择实际具有内存映射的外部存储器接口的设备。在这种情况下,例如,诸如NAND闪存的串行存储器设备或诸如SD卡的大容量存储设备是不合适的。它必须是系统地址/数据总线上的NOR闪存。
在大多数情况下,必须为外部存储器接口配置正确的存储器类型,总线宽度和时序等,以便可寻址。这意味着您无法直接启动外部存储器上的软件,因为必须运行软件才能执行配置。
第三,通常你的工具链会编译并将你的应用程序链接到一个单一的monotithic应用程序 - 将它分成BIOS / OS和应用程序并不简单,对于裸机目标(即没有运行完整的操作系统,如Linux)内置加载/执行和动态链接等没有标准的方法 - 你必须自己做饭。
对于启动引导加载程序,加载应用程序并运行它的情况,它可能很简单,因为一旦应用程序运行,引导加载程序就不再发挥作用 - 引导加载程序只需要知道应用程序的起始地址。但是在您的情况下,您需要单独编译和链接两个单独的软件实体,并让应用程序能够访问您的BIOS / OS代码,因此应用程序实体需要知道独立链接的BIOS / OS的例程入口点地址。一种方法是生成BIOS / OS的链接映射(特定于工具链),并从中生成一个入口点查找表(本质上是函数指针数组),它与每个应用程序链接,这样您的应用程序将具有回调BIOS / OS的方法。
您可能不需要这样做,您可以将应用程序链接到不相交的内存地址区域,并单独编程内部和外部存储器设备(有时称为"分散加载)。这样链接器负责解析内部和外部地址,并且可以向任一方向调用。当然,您需要确保配置外部存储器的启动代码在内部存储器中,但是可以指示链接器将特定代码放在特定的存储器中,或让它决定何时无关紧要。
重新刷新代码的需要本身并不需要您描述的架构,您可以简单地实现一个引导加载程序(占用内部闪存的保留页面),可以从某些来源(如SD卡,USB,串行或NAND闪存,并将其写入适当的内部或外部闪存页面;如果加载的数据是例如英特尔格式的Hex文件,它将包含将告诉引导加载程序在何处写入数据的地址信息。在这种方法中,唯一的永久代码是引导加载程序(必须配置外部存储器),并且您的BIOS / OS和应用程序可以是单片的,并且“分散加载”#34;内部和外部闪光灯。
警告,但Cortex-M设备经过优化,可以通过单独的总线执行代码和加载数据。在STM32上,内部闪存和内部SRAM位于不同的总线上,允许并行进行指令和数据读取。当从外部存储器运行代码时,你必须意识到不仅总线可能更慢,外部存储器的指令和数据取出也将被序列化。因此,性能可能会受到重创。
答案 1 :(得分:1)
编辑:实际上,您的芯片具有外部存储器映射(FMC / FSMC)。这将允许直接执行,因此如果你可以使它工作,它可能是最简单的方法。
如果你坚持使用这个芯片,将整个应用程序加载到SRAM可能是最简单的。在RAM和Flash执行之间跳转不是问题,RAM和闪存映射在不同的地址。为了简单起见,您应该始终在相同的RAM地址加载应用程序,并且需要构建应用程序以在此特定地址运行(通常使用链接器设置完成)。您可以尝试实现部分加载系统,该系统可以在需要时加载部分应用程序,但这需要一些努力来设计主机FW和构建应用程序。
写入内部闪存可以正常工作,如果你的RAM很短,可能会更好。通常,内部闪存可以在执行时写入,但这通常会导致CPU停止(CPU等待闪存操作完成),这可能不是问题。如果查看芯片数据表,闪存的特点是最少10,000次擦除/写入周期。这意味着,如果你的芯片应该持续5年,你应该每天加载少于6个应用程序(对于典型的耐力,你可以合理地加倍这个数量,或许更多,但是没有保证)。
答案 2 :(得分:0)
cortex-m4与你所说的无关,与所有arm处理器核心一样,cortex-m4只是一个处理器核心,arm使得IP不是芯片。您必须查看芯片供应商的实现,其中任何一个都能够在外部闪存接口上执行代码。我不会假设,就像很难找到一个从外部ram执行的微控制器,但这些微处理器比闪存更常见。几乎所有你都可以复制和运行或闪存和运行,在内部芯片资源上运行的代码将代码从外部资源复制到内部(rom / ram)然后在那里运行,该代码可以再次复制和跳转或返回到主片上固件复制并加载下一个叠加层。
芯片供应商应该能够告诉你闪存的使用寿命,闪存耗尽,代码设计为定期/不断擦除和写闪存会在几天或几周或几个月内磨损掉那部分,具体取决于多么糟糕你惩罚闪光。断电时将状态保存到舞会或闪光,例如车辆上的里程表读数,可以是一天一次或几次,或者可能是每隔几年一次,但每十分之一节省一次英里将在车辆使用寿命之前耗尽该部分。
m4s很难称微控制器具有内部的所有功能(浮点,缓存,mmu等东西),并且与cortex-m0兄弟姐妹相比,往往会有大量的ram和flash。所以你最好的选择是获得一个更多的ram,复制和跳跃。应该有很多部分可以很好地为你工作......
答案 3 :(得分: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