【问题标题】:load time base address cortex-m3 bare metal加载时间基地址 cortex-m3 裸机
【发布时间】:2011-06-12 19:53:53
【问题描述】:

我正在开发一个使用裸机环境的 cortex-m3 CPU 的项目。 由于软件升级需要,CPU 上的可执行映像可能位于闪存中的两个地址之一,这会带来问题。映像的起始地址仅在加载时才知道,而在静态链接期间不知道。 我不太确定,但我认为这并不真正符合动态加载的条件,但我在这里真的可能被误认为,因为我不是这方面的专家。 如果没有操作系统也没有动态加载器,有没有办法编译和链接图像,它的基地址只能在加载时给出?

【问题讨论】:

    标签: embedded arm dynamic-loading cortex-m3 gnu-toolchain


    【解决方案1】:

    对于像您这样的裸机嵌入式系统,这是通过将您的代码编译/链接为可重定位代码(也称为Position Independent Code)来完成的。

    如何实现这一点受处理器的影响,而实际方法由您的开发工具集实现,因此您需要查阅有关您的交叉开发工具的文档。它通常是一组编译器和链接器选项(包括您的链接器命令脚本,如果有的话),它们决定了事物的布局方式以及用于访问它们的寄存器。

    当您使用支持 MMU(不在 CM3 上,抱歉)的平台(处理器和操作系统)时,事情会变得容易一些 - 然后代码可以位于物理内存中的任何位置,但通过 MMU,它的逻辑地址空间可以不同。因此,在链接时,代码和数据的地址可以固定,然后在加载时,通过 MMU 设置逻辑地址空间,程序就更聪明了。

    您可能会发现这个其他 SO 问题 ("Trying to load position independent code on cortex-m3") 也很有帮助。

    【讨论】:

    • 好吧,尝试了引用链接中的说明,我的工具链(我认为)甚至不支持 PIC/PIE 选项,我认为是因为 newlib 的编译方式。我在 LPC1758 上使用 NXP LPCXpresso BTW。
    • 如果您不需要 newlib 或 gcclib,您可能会有更大的灵活性,如果不需要,根据您的应用程序大小,您的基于闪存的引导代码可以简单地将二进制文件复制到 ram 并从那里分支/运行。你为固定的 ram 地址编译你的应用程序,启动/复制代码很简单,一些汇编程序包裹在二进制文件中(可以是 PIC,因为你是手工完成的)。这是一个带有分支的 ldm/stm 循环。
    • 这个解决方案确实很容易实现并且肯定会工作,但我担心我们的应用程序二进制映像大于 RAM 大小(64KB,而其中一半用于 AHB 或类似的东西那个)。
    • Boaz 我喜欢你的回答,但我想知道如何从 App 构建环境管理对 OS 端的引用。例如,操作系统端有一些我想从我的 APP 端访问的变量。这两件事如何分开构建并在运行时连接?
    【解决方案2】:

    您需要某种方式让设备确定何时重置它应该从两个可能位置中的哪一个开始执行。但一般来说,裸机设备在复位时只有一个起始位置(某些控制器可以根据设备上某些引脚的逻辑电平从两个或更多入口点中进行选择)。

    我们也有类似的需求,制定了如下方案:

    • 需要一个小型引导加载程序 - 它已构建并链接为在复位时获得 CPU 控制权的程序
    • 主程序映像实际上构建了两次 - 每个可能的位置一次。注意:两个可能的加载位置是固定的,并且由引导加载程序知道。
    • 在程序映像的开头有一个小数据结构,其中包含对引导加载程序很重要的几位信息。其中有程序的入口地址和程序镜像的校验和

    引导加载程序检查固定的已知位置以校验两个可能的图像。

    • 如果它没有找到有效的图像,它会简单地循环(看门狗会重置设备,但这并不重要 - 在加载有效的主程序之前它只是一块砖)
    • 如果它只找到一张有效图像,那就是它跳转到的入口点。
    • 如果它发现两个图像都有效,它会使用数据结构中的其他信息来确定要控制哪个图像(版本信息、最后一次已知的正确信息,无论您的策略是什么)。

    关键是引导加载程序必须简单而愚蠢。它不容易升级,所以你希望它足够愚蠢,不能有错误。

    现在设备可以在运行时通过将映像刷新到非运行位置来升级(我们拥有的 Cortex-M3 设备允许这样做 - 如果 LPC1758 不允许这样做,那么您必须有一些可以运行的东西从 RAM 执行闪存更新)。重置,引导加载程序拾取新刷新的映像。

    系统需要做一些前期工作才能让引导加载程序运行并坚如磐石,但一旦运行,更新是 100% 可靠的(如果新闪存未完成,则旧映像是唯一的校验和,所以它会在下一次重置时运行 - 没有砖块)。主要的缺点——也是一个很大的缺点——是你基本上失去了一半的主程序的闪存地址空间,因为闪存必须能够保存两个竞争图像。

    【讨论】:

    • 嗨迈克尔,这实际上是我们目前正在做的事情,我希望有一个更像第一个答案中提出的解决方案。非常感谢您提供的信息丰富的答案。
    猜你喜欢
    • 2014-02-11
    • 1970-01-01
    • 2012-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-21
    • 2016-04-02
    相关资源
    最近更新 更多