Gcc ARM STR7xx的加载程序脚本

Gcc ARM STR7xx的加载程序脚本,gcc,arm,ld,linker-scripts,Gcc,Arm,Ld,Linker Scripts,我正在尝试使用Eclipse+CDT+yagarto(gnu工具链)+OpenOCD对ARM进行编程。在几个示例项目(例如来自yagarto站点)中,我找到了链接器脚本(*.ld),其中指定了大量链接信息(以及节定义)。事实上,我以前从未面对过这些文件(IAR不需要它们),而且我发现乍一看这些文件有点难以理解。所以我的问题是,我可以在我的所有项目中为我的目标处理器(STR710FZ2T6)使用一个这样的脚本文件吗?或者我必须熟悉编写这些脚本并为每个项目编写它们。如果我可以为特定目标处理器的所有项

我正在尝试使用Eclipse+CDT+yagarto(gnu工具链)+OpenOCD对ARM进行编程。在几个示例项目(例如来自yagarto站点)中,我找到了链接器脚本(*.ld),其中指定了大量链接信息(以及节定义)。事实上,我以前从未面对过这些文件(IAR不需要它们),而且我发现乍一看这些文件有点难以理解。所以我的问题是,我可以在我的所有项目中为我的目标处理器(STR710FZ2T6)使用一个这样的脚本文件吗?或者我必须熟悉编写这些脚本并为每个项目编写它们。如果我可以为特定目标处理器的所有项目使用单个文件,请告知我在哪里可以找到这样的通用文件。

没有通用链接器脚本。这些脚本非常重要,因为它们定义了各种数据和程序部分在内存(RAM或ROM)中的位置。IAR编译器(如果我没记错的话,xcl文件)中有一些等价的东西。到目前为止,您显然只使用了默认值

关于STR7xx有一个很好的文档,叫做“为STR7xx交叉使用开源工具”
发展”。您可以在yagarto主页中找到一个链接。我建议您看看它,并尝试了解链接器文件是如何工作的。您还需要了解一些其他配置文件。

我猜每第三个人都有不同的脚本或解决方案。有许多问题需要解决,不同的链接器将以不同的方式解决这些问题。我认为GNU让它变得太难了,如果不是黑魔法的话

对于嵌入式系统,您通常需要使用闪存、eeprom或其他形式的只读存储器进行引导。与其他处理器一样,ARM有一个向量表,告诉它重置代码的位置和中断等。因此,该表必须位于特定位置,并且您必须告诉链接器将其置于该特定位置(首先)

我喜欢使用的脚本之一是:

MEMORY
{
    bob (RX) : ORIGIN = 0x0000000, LENGTH = 32K
    joe (WAIL) : ORIGIN = 0x2000000, LENGTH = 256K
}

SECTIONS
{
    JANE : { startup.o } >bob
}
我通常使用ram和rom作为名称,而不是bob和joe,但在这里演示,名称是什么并不重要,它们只是标签

主题的另一个变体:

MEMORY
{
    rom(RX)   : ORIGIN = 0x00000000, LENGTH = 0x8000
    ram(WAIL) : ORIGIN = 0x20000000, LENGTH = 0x2000
}

SECTIONS
{
    .text : { *(.text*) } > rom
}
第一个允许您以任何顺序将文件放在链接器命令行上,但必须在startup.o文件中包含向量表。后者允许您使用任何文件名,但链接器脚本上的第一个文件需要有向量表

arm-thumb-elf-gcc -Wall $(COPS) vectors.o putget.o blinker2.c -T memmap -o blinker2.elf
或直接与劳工处联络

arm-thumb-elf-ld vectors.o putget.o blinker2.o -T memmap -o blinker2.elf
RX告诉链接器将读取和执行的内容放在内存部分,而哀号基本上就是其他内容。例如,如果您只有一个ram,则可以将所有标志RXWAIL放在指示ram所在位置的行上。根据您的加载程序,在这种情况下,您可以依赖elf文件告诉加载程序从何处开始分支,或者您可以简单地将入口点作为二进制文件的开头,加载程序可以更简单。arms(不是cortex-m3)有一个分支指令作为重置向量的第一个向量,因此您可以假装为ram解决方案构建一个向量表,并且可以正常工作

这个解决方案中有很多问题我都没有遇到。我在代码中初始化变量,而不是在声明期间

这个

而不是

int rx=7;

int main ( void )
{
我也从不假设一个变量在代码开始时为零,我总是在开始之前将它初始化为某个值。作为一个团队,您的启动代码加上链接器脚本可以协同工作,使bss代码的自动重置和引导时将非零初始数据从rom复制到ram变得更加容易。(上面的int rx=7;需要一些代码从rom中的某处复制值7,并将其写入分配给变量rx的ram中的内存位置,以便在main()启动时,7就在那里

由于此方法,我的启动代码也非常简单:

.globl _start
_start:
    b reset
    b hang
    b hang
    b hang
    b hang
    b hang
    b hang
    b hang
    b hang
    b hang
    b hang
    b hang
    b hang
    b hang
    b hang

hang : b hang

reset:
    ldr sp,=0x10004000
    bl main
    b hang
您将看到或阅读一些解决方案,这些解决方案允许启动代码和链接器脚本协同工作,而不必硬编码堆栈指针、堆空间等,同样,您可以在复杂的启动代码和链接器脚本中投入大量工作,以获得一些自动化,或许可以节省一些工作,或许不需要f/工作时可以并且将减少人为错误,这可能是一件好事,而且如果您经常更换芯片或尝试编写在芯片系列中工作的一位代码,您可能也希望实现这种自动化

我的底线是,对于所有的ARM工作,你只能使用一个链接器脚本。但你必须根据该脚本来调整你的工作。你可能找不到一个可以与每个人的示例代码一起工作的脚本。脚本越复杂,就越难借用。是的,我上面的脚本可能可以在ld comm上完成和行,但当(gcc 2.95)我无法使其工作时,我开发了上面的最小脚本并一直在使用它们。出于某种原因,我不得不修改为第二个脚本,但使用4.x.x,当然4.4.x,我可以使用任何一个

.globl _start
_start:
    b reset
    b hang
    b hang
    b hang
    b hang
    b hang
    b hang
    b hang
    b hang
    b hang
    b hang
    b hang
    b hang
    b hang
    b hang

hang : b hang

reset:
    ldr sp,=0x10004000
    bl main
    b hang