ARM STR7xx 的加载器脚本

发布于 2024-07-08 09:32:13 字数 298 浏览 12 评论 0原文

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

I'm trying to program ARM using Eclipse + CDT + yagarto (gnu toolchain) + OpenOCD. In several sample projects (from yagarto site for example) I found linker scripts (*.ld) where a lot of linking information specified (along with sections definitions). Actually I haven't faced this files before (IAR doesn't need them), and I find them somewhat difficult to understand from a first glance. So my question is can I use one single such script file for my target processor (STR710FZ2T6) with all my projects or I have to get familiar in writing this scripts and write them for each project. If I can use single file for all projects for particular target processor can you please advice where I can find such universal one.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

往事随风而去 2024-07-15 09:32:14

我的猜测是每三个人就有一个不同的脚本或解决方案。 有许多问题需要解决,不同的链接器将以不同的方式解决这些问题。 我认为 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

或者直接使用 ld

arm-thumb-elf-ld vectors.o putget.o blinker2.o -T memmap -o blinker2.elf

RX 告诉链接器将读取和执行的内容放入该内存部分,WAIL 基本上是其他所有内容。 例如,如果您只有一个 ram,您可以将所有标志 RXWAIL 放在告诉 ram 位置的行上。 在这种情况下,根据您的加载器,您可以依靠 elf 文件告诉加载器从哪里开始分支,或者您可以简单地将入口点设置为二进制文件的开头,并且加载器可以更简单。 手臂(不是 cortex-m3)有一个分支指令作为重置向量的第一个向量,因此您可以假装为 ram 解决方案构建一个向量表并且可以正常工作。

这个解决方案有很多问题,但这些问题并没有困扰我。 我在代码中初始化变量,而不是在声明期间初始化变量。

相反

int rx;

int main ( void )
{
  rx = 7;

int rx=7;

int main ( void )
{

当代码启动时,我也从不假设变量为零,我总是在开始之前将其初始化为某个值。 您的启动代码加上链接器脚本作为一个团队可以协同工作,以便更轻松地自动重置 bss 代码以及在启动时将非零初始化数据从 rom 复制到 ram。 (上面的 int rx=7; 需要一些代码,从 rom 中的某个位置复制值 7 并将其写入 ram 中为变量 rx 分配的内存位置,以便当 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

您将看到或阅读有关允许启动代码和链接器脚本一起工作的解决方案,而不必硬编码堆栈指针,堆空间,类似的东西,您可以再次将在复杂的启动代码和链接器脚本中进行大量工作以获得一些自动化,也许可以节省一些工作,也许不会,如果/当工作时,自动化可以并且将会减少人为错误,这可能是一件好事,即使您正在切换。经常使用芯片或尝试编写在一系列芯片中工作的一点代码,您可能也需要这种自动化,

我的底线是,您可以只使用一个链接器脚本来完成所有 ARM 工作,但您必须进行定制。您可能找不到适合每个人的示例代码的脚本。 剧本越复杂就越难借用。 是的,我上面的脚本很可能可以在 ld 命令行上完成,但是早在(gcc 2.95)我就无法让它工作,所以开发了上面的最小脚本并从那时起就一直使用它们。 由于某种原因必须修改第二个脚本,但对于 4.xx,当然 4.4.x,我可以使用其中之一。

My guess is every third person has a different script or solution. There are a number of problems that have to be solved, different linkers are going to solve those in different ways. I think GNU has made it way too difficult if not black magic.

For an embedded system you are often going to have a flash or eeprom or some other form of read only memory to boot from. Like other processors the ARM has a vector table to tell it essentially where the reset code is and interrupt, etc. So that table has to be in a specific place and you have to tell the linker to put it in that specific place (first).

One of the scripts I like to use is:

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

SECTIONS
{
    JANE : { startup.o } >bob
}

I usually use ram and rom as names instead of bob and joe but demonstrating here that it doesnt matter what the names are they are just labels.

Another variation on the theme:

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

SECTIONS
{
    .text : { *(.text*) } > rom
}

The first one allows you to put the files on the linker command line in any order but you have to have the vector table in the startup.o file. The latter lets you use whatever filenames but the first file on the linker script needs to have the vector table.

arm-thumb-elf-gcc -Wall $(COPS) vectors.o putget.o blinker2.c -T memmap -o blinker2.elf

Or with ld directly

arm-thumb-elf-ld vectors.o putget.o blinker2.o -T memmap -o blinker2.elf

The RX tells the linker to put read and execute stuff in that memory section and the WAIL is basically everything else. If you only have one ram for example you can put all the flags RXWAIL on the line that tells where the ram is. Depending on your loader in that case you can rely on the elf file telling the loader where to branch to to start or you can simply make the entry point the beginning of the binary and the loader can be simpler. The arms (not the cortex-m3) have a branch instruction as the first vector for the reset vector so you can just pretend to build a vector table anyway for a ram solution and will just work.

The are a number of problems with this solution that dont happen to bother me. I initialize variables in my code, not during declaration.

This

int rx;

int main ( void )
{
  rx = 7;

instead of

int rx=7;

int main ( void )
{

I also never assume that a variable is zero when the code starts I always initialize it to something before I start. Your startup code plus linker script as a team can work together to make it easier to automate the resetting of the bss code and copying non-zero init data from rom to ram on boot. (that int rx=7; above requires some code that copies the value 7 from somewhere in rom and writes it to the memory location in ram allocated for the variable rx so that when main() starts the 7 is there.

My boot code is also quite simple as a result of this method:

.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

You are going to see or read about solutions that allow the startup code and the linker script to work together to not have to hardcode stack pointers, heap space, things like that, again you can put a lot of work into complicated startup code and linker scripts to gain some automation and perhaps save some work, perhaps not. The automation, if/when working can and will reduce human error and that can be a good thing, also if you are switching chips often or trying to write one bit of code that works in a family of chips you may want this automation as well.

My bottom line is YES you can live with only one linker script for all of your ARM work. But you have to tailor your work to that script. You are likely not going to find one script that works with everyones example code. The more complicated the script the harder it will be to borrow. Yes, my scripts above can likely be done on the ld command line, but way back when (gcc 2.95) I couldnt get that to work so developed the minimal script above and have been using them ever since. Had to modify to the second script for some reason but with 4.x.x, certainly 4.4.x I am able to use either one.

晨曦÷微暖 2024-07-15 09:32:14

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

有一个关于 STR7xx 的很好的文档,名为“Using Open Source Tools for STR7xx Cross
开发”。你可以在yagarto主页找到一个链接。我建议你看一下它并尝试了解链接器文件是如何工作的。还有一些其他配置文件需要你有一些了解。

There is not a universal linker script. These scripts are very important, since they define where in memory (RAM or ROM) the various data and program sections will be placed. There is something equivalent in IAR compilers (xcl files if I remember correctly). You've obviously only used the default ones until now.

There is a nice document about STR7xx called "Using Open Source Tools for STR7xx Cross
Development". You can find a link in yagarto homepage. I recommend that you have a look at it and try to understand how linker files work. There are also some other configuration files that you need to have some understanding of.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文