4

我已经编写了 avr 微控制器,但对 arm 来说是新手。我只是查看了 winarm 附带的 sam7s64 的示例代码。我对这些文件 rom.ld 、 ram.ld 、 scatter 文件、 cstartup.s 文件感到困惑。我在编写 avr 时从未见过这类文件。请澄清我对它们每个文件的作用的怀疑。

4

2 回答 2

4

我还有更多示例供您思考http://github.com/dwelch67

假设您有一个支持特定指令集的工具链。工具经常尝试支持不同的实现。您可能有一个具有 X 数量的闪存和 Y 数量的 ram 的微控制器。一个芯片的 ram 可能与另一个芯片的位置不同,等等。指令集可能是相同的(或者本身可能有细微的变化),以便工具链对它最终想知道的内存布局的一些指令进行编码是。可以为某些纯粹与位置无关的处理器编写代码,尽管这不一定是目标,因为它有成本。工具也倾向于采用 Unix 方法处理事物。从源语言到目标文件,它还不知道内存布局,它留下了一些漏洞,有待以后填补。您可以根据工具链和指令集从不同的语言中获取,可能混合使用 ada 和 C 以及其他编译为对象的语言。然后链接器需要结合所有这些东西。作为程序员,你可以而且有时必须控制什么去哪里。您希望向量表位于正确的位置,您希望您的输入代码可能位于某个位置,您肯定希望最终在 ram 中使用 .data 并在 flash 中使用 .text。

对于 gnu 工具,您使用链接器脚本告诉链接器事情去向,其他工具链可能有其他方法。使用 gnu ld 您还可以使用 ld 命令行...您看到的 .ld 文件可以控制它。现在有时这被埋在工具链安装的内部,有一个默认位置可以找到默认链接器脚本,如果没问题,那么您不需要制作链接器脚本并将其随身携带。根据您在 avr 上使用的工具,您要么不需要弄乱它(使用程序集、avra 或您使用 .org 或其他类似语句控制它的东西),要么工具链/沙箱会为您处理好它,它被掩埋了(例如使用 arduino 沙箱)。例如,如果您编写一个 hello world 程序

#include <stdio.h>
int main ( void )
{
   printf("Hello World!\n");
   return(0);
}

并在您的台式机/笔记本电脑上编译

gcc hello.c -o hello

有一个链接器脚本,可能是一个讨厌的、可怕的、丑陋的。但是由于您对操作系统的默认链接器脚本和布局感到满意,因此您不需要弄乱它,它就可以工作。对于这些微控制器,一个工具链可以支持大量芯片和供应商,您开始必须处理这个问题。将链接器脚本保留在项目中是一个好主意,因为您不知道从一台机器或个人到下一台机器或人他们有什么确切的 gnu 交叉编译器,如果你创建在许多 gnu 交叉编译器安装上工作的项目并不难在项目中保留一些东西,而不是强迫它们进入工具链。

另一半,特别是 gnu 工具,与链接描述文件密切相关的是启动代码。在调用您的 C 程序之前,有一些期望。例如 .data 已就位且 .bss 已清零。对于微控制器,您希望将 .data 保存在非易失性存储器中,因此当您启动 C 程序时它就在那里,所以它需要在闪存中,但它不能从那里运行,因为 .data 是读/写的,所以在入口点之前调用 C 代码,您需要将 .data 从闪存复制到 ram 中的适当位置。链接描述文件描述了在闪存中保存 .data 的位置以及在 ram 中复制它的位置。启动代码,你可以命名任何你想要的startup.s,start.s,crt0.s等,在链接阶段填充变量,以便代码可以将.data复制到ram,可以将.bss归零,可以设置堆栈指针,以便您拥有一个堆栈(C 工作所需的另一项),然后该代码调用 C 入口点。这对于任何其他高级语言也是如此,如果没有别的,每个人都需要一个堆栈指针,所以你需要一些启动代码。

如果您查看我的一些示例,您会看到我也在为 avr 处理器编写链接器脚本和启动代码。

于 2012-05-26T14:50:25.847 回答
3

在您的具体情况下,很难确切知道每个文件(rom.ld、ram.ld、scatter file、cstartup.s)的内容是什么。但是,假设它们的名称具有足够的描述性,我将让您了解它们的用途:

1- rom.ld/ram.ld:通过文件扩展名,这些是“链接器脚本”。这些文件告诉链接器如何将目标文件的每个内存部分放在哪里(请参阅GNU LD以了解有关链接器脚本及其语法的所有信息)

2- cstartup.s:同样,来自该文件的扩展名。它似乎是用汇编编写的代码。通常在此文件中,软件开发人员将在将控制权传递给您的主应用程序之前初始化该微控制器。此文件执行的操作示例如下:

  • 设置 ARM 向量
  • 配置振荡器频率
  • 初始化易失性内存
  • 调用 main()

3- Scatter:就我个人而言,我从未使用过这个文件。然而,它似乎是一个文件,用于控制应用程序的内存布局以及它在 micro 中的布局方式(参见参考资料)。这似乎是一个特定于 Keil 的文件,与任何其他链接描述文件没有什么不同。

于 2012-05-27T06:02:02.173 回答