虽然这与微控制器编程有关,但它是C / C ++指针和函数操作的常见主题。
我需要从RAM执行闪存编程例程(让我们说 reprogram()),这是一项简单的任务。但是此功能使用闪存访问功能(例如 blockWrite(...), blockErase(...)),这些功能在编译和闪烁时默认设置为闪存。 / p>
将内联添加到函数声明和定义无助于获取我使用的目标,gcc和优化选项,只是忽略内联并且不会扩展这个函数是内联的。
我可以看到的一个选项是将这些函数嵌套在 reprogram()中,但它们可能是库的一部分,也可以从其他地方使用。
除了手动展开它们之外还有什么其他选择? : - )
编辑:好的,我可以看到我可能被误解了。
问题不在于如何实际移动代码并从RAM执行,而是如何使此函数使用的函数也被移动。第一个想法是将此辅助函数更改为 inline ,但gcc在优化时忽略了该指令。 如果我只将 reprogram()函数移动到RAM,它将从flash调用辅助函数。
答案 0 :(得分:2)
我已经完成了这个(或者至少是为其设计软件的团队的一部分)几次。有几种方法,它实际上取决于您的整体系统设计。没有一个解决方案可以做到这一点,你必须弄清楚硬件/软件组合中的正确解决方案。但这里有一些"提示"。
还要记住"失败",例如如果断电或闪存编程出现问题会发生什么。
一般原则是:
另一个选择是拥有两个"银行"闪存,你可以通过CPU上的一些选择引脚选择哪一个在哪里,并使用一个作为你的"执行基地",一个到#34;程序"。这当然要求闪光灯(至少)是两个独立的芯片。优点是你有一个"备份"如果电源进入编程的一半(使用"一半"闪存也将是一个解决方案,结合一个"加载闪存编程代码到RAM"解决方案)
另一个选择是使用一个小的启动加载程序代码片段,以这样的方式编写,您可以将其复制到RAM中,然后从那里加载一段实际附带的Flash编程代码以标准化形式更新软件作为"模块"。再次,确保此代码负责编程中断,仅从RAM调用中断处理程序,并将所有代码加载到RAM中,包括错误处理,异常处理等等。如果小型引导加载程序是单独的,受保护的,闪光块,你再次有一个很好的方法来恢复"。
[1]当我在一家硬件公司工作时,我实际上被叫到了一个客户,因为他们的闪存编程代码工作不正常,他们怀疑他们的处理器坏了。事实证明,如果您的定时器中断正在运行"代码"在正在重新编程的闪存中,它会做一些非常奇怪的事情(因为闪存中的"内容"现在是#34;状态代码",这取决于当前的编程状态,包括a"我活着的位"为每次读取切换。意味着处理器得到各种随机的#34;代码"运行 - 奇怪的事情发生 - 但是只要你停在线路仿真器中,它需要足够的微秒才能停止并且用户输入一个命令使其恢复正常"所以一切看起来都很好 - 除了你已经执行了几个打开"怪异的操作码",现在想知道为什么你在不知名的地方执行随机垃圾)。
答案 1 :(得分:0)
微处理器处理内存地址,其中一些地址指向RAM,其中一些地址(我在这里猜测)指向可执行闪存。创建程序时,链接器(或稍后在OS加载程序中)决定将哪些地址分配给哪些符号。
在编写自己的二进制图像时,需要控制将哪些地址分配给哪些功能。这可以通过编写自己的链接描述文件来完成。有关如何为GNU ld执行此操作的详细信息,请参见here。
答案 2 :(得分:0)
要将功能从Flash复制到RAM,首先要对系统进行配置,以查看Flash和RAM之间的速度差异是否可以忽略不计。代码可以在Flash中执行。
C和C ++语言可以为您提供函数的地址,但不能为您提供长度。您需要获取有关此主题的编译器或链接器特定信息。
我建议使用部分或区域。为需要移动到RAM的函数创建一个部分。告诉您的链接器或编译器将特殊功能放入该部分。您可以编写将数据从Flash中的部分复制到RAM的代码。某些IDE和链接器带有特殊命令,可帮助从ROM复制到RAM。
将代码编程到Flash中
我使用过的大多数中型到大型嵌入式系统,使用Bootloader命令将可执行文件上传到SRAM。 Bootloader是一个小型应用程序,它被复制到SRAM中以设置系统,和加载应用程序。
基本上,算法是:
将Flash设置为读取模式 验证数据已正确编程到Flash中。