【问题标题】:adding code to an existing firmware [closed]向现有固件添加代码[关闭]
【发布时间】:2013-09-21 12:57:53
【问题描述】:

我正在研究 Cortex-M3。 我想在现有固件映像中添加一个功能(或 ISR)而不更新整个程序。 我可以在没有 main 的情况下编译和构建一个函数并写入闪存吗? 如果我知道这个函数的写地址,我可以用函数指针调用这个函数吗?

我们有单线程代码,没有操作系统。根本问题是在这种情况下,我们将如何创建一个安装和使用应用程序的环境。

【问题讨论】:

  • 不,我们不是在尝试修补其他二进制文件。我们在单线程中有一个代码,我们没有操作系统,问题是如何创建环境以在这样的环境中安装和使用该应用程序案例。
  • 您的大部分问题都可以通过 链接器 优雅地解决。查看您的工具包的文档。例如,Gnu Ldgcc 工具。您可以从一个模块中提取符号并在没有函数指针的情况下调用它们。即使您可以在没有链接器技巧的情况下使用纯 C 语言执行此操作,但您的代码通常会受限。如果你真的没有操作系统,那么我猜你已经有一个自定义链接器脚本。
  • 是的,你可以。您将能够做什么将完全取决于您如何实现它。事实上,你可以实现一个重置向量,甚至给它一个新的向量表,这样你就可以在内存的某个地方上传一个小的引导加载程序。
  • 如果您能详细解释一下您的目标,我可能会提供帮助。现在我正在为 Cortex-M3 编写引导加载程序,并且我已经完成了类似的操作。
  • 这个问题 100% 恰当、切题且完整。要记住的一个主要挑战是,您使用的任何库例程(即使是不知道的,来自编译器内置函数)都必须被复制,否则您将不得不手动通知构建系统它们在内存中的位置现有图像。但是 ISR 通常应该保持相当精简,所以你可能没有问题。最后,如果系统使用闪存中的向量表运行,您将必须使用具有指向您的 ISR 的向量的新版本重新刷新该块。

标签: c embedded arm bare-metal


【解决方案1】:

如果您使用“位置无关代码”编译代码,那么您的函数可以重新定位在 ROM(闪存)或 RAM 中的任何位置。

编写重定位到内存中的代码仍然不是一件容易的事,您应该确保了解 ARM 架构,至少不要害怕 ARM 机器指令集。诀窍是首先了解这在指令级是如何发生的,然后尝试用 C 做同样的事情。当然,有一些复杂性。在main 运行之前,初始化过程中有幕后工作,设置零和非零初始化变量。这取决于您的编译器实际如何进行。运行一个虚拟程序很有用,并逐步完成所有执行之前你到达main

查看这个相关问题:Trying to load position independent code on cortex-m3

【讨论】:

  • 更有效的解决方案是为目标位置编写位置相关代码。
【解决方案2】:

是的,你可以。

在确定您知道如何解决此问题之前,您需要了解 3 个文件:

  1. The SAM3N4C Startup Code
  2. The DeviceVectors definition
  3. The SAM3N4C Linker Memory Region Definitions
  4. The SAM3N4C Linker Script

我已经为您提供了 SAM3N4C 芯片的链接,因为我对它很熟悉。可以根据您使用的芯片制作代码。

要使其满足您的要求,您需要一个向量表,其中包含指向您的函数的指针。您需要将此向量表放在一个已知地址,然后您将使用它来获取您的函数指针。您的函数将紧跟在这个向量表之后的内存中。

简要说明:

您似乎对 Cortex-M3 上的工作原理仍然不熟悉,所以我将尝试解释一下。

main 并不特殊。它只是一个函数,甚至不是第一个执行的东西。在 Cortex-M3 上运行的第一个函数是您的 Reset Vector 中断服务程序。然后这个函数设置你所有的内存,然后调用 main(见The SAM3N4C Startup Code)。

在 Cortex-M3 上,有一个指向此特殊功能的指针,该指针位于距内存开头 (0x00000004) 的已知偏移量处,这就是您的硬件用于启动/启动的方式。来自The SAM3N4C Startup CodeReset_Handler() 函数放置在该地址。这是在DeviceVectors exception_table 结构中完成的,您可以看到它在The SAM3N4C Startup Code 中给出的代码中被初始化。该结构包含所有函数指针,并且对于要位于距内存开头 0x00000004 偏移量的复位向量,exception_table 需要放置在内存的最开头。这是通过使用__attribute__ ((section(".vectors"))) 标志将exception_table 放置在.vectors 部分来完成的(参见The GNU attribute syntax)。然后在The SAM3N4C Linker Script 中使用,其中包括The SAM3N4C Linker Memory Region Definitions 中给出的内存区域定义,将其放置在内存的最开头(使用KEEP(*(.vectors .vectors.*)) 行,将其放入内存first)。

我建议调查您现有的链接器脚本以了解它们的工作原理,因为它们会为您提供有关如何执行此操作的线索。阅读有关the GNU linker 的更多信息将有助于您解决此问题。

此外,在我看来,您所追求的解决方案会复制这种行为,但您会使用更小的“向量表”,因为您只需要一个函数...

【讨论】:

    猜你喜欢
    • 2015-12-09
    • 1970-01-01
    • 2019-06-03
    • 2010-12-05
    • 1970-01-01
    • 2013-02-12
    • 1970-01-01
    • 1970-01-01
    • 2021-04-10
    相关资源
    最近更新 更多