gpt4 book ai didi

gcc for ARM - 移动代码和堆栈

转载 作者:行者123 更新时间:2023-12-03 16:17:34 24 4
gpt4 key购买 nike

我正在为 ARM Cortex-M3 (SiLabs) SOC 开发一个项目。我需要将中断向量 [编辑] 和代码从闪存底部移开,以便为“引导加载程序”腾出空间。引导加载程序从地址 0 开始,以在内核退出复位时启动。它的功能是验证在更高地址加载的主图像,并可能用新图像替换该主图像。

因此,引导加载程序的向量表为 0,后跟其代码。在更高的固定地址,比如 8KB,将是主图像,从它的向量表开始。

我找到了 this page它描述了引导加载程序可以使用的向量表偏移寄存器(显然屏蔽了中断)将硬件指向新的向量表。

我的问题是如何链接“主”图像,以便在写入闪存时它可以工作,而不是从零开始。我不熟悉 ARM 程序集,但我认为代码不是位置无关的。

我正在使用 SiLabs 的 Precision32 IDE,它使用 gcc 作为工具链。我找到了如何添加链接器标志。我的问题是什么 gcc 标志将提供对向量表和代码基础的更改。

谢谢你。

最佳答案

向量.s

.cpu cortex-m3
.thumb

.word 0x20008000 /* stack top address */
.word _start /* Reset */
.word hang
.word hang
/* ... */

.thumb_func
hang: b .

.thumb_func
.globl _start
_start:
bl notmain
b hang

不是main.c
extern void fun ( unsigned int );
void notmain ( void )
{
fun(7);
}

乐趣.c
void fun ( unsigned int x )
{
}

生成文件
hello.elf : vectors.s fun.c notmain.c memmap
arm-none-eabi-as vectors.s -o vectors.o
arm-none-eabi-gcc -Wall -O2 -nostdlib -nostartfiles -ffreestanding -mthumb -mcpu=cortex-m3 -march=armv7-m -c notmain.c -o notmain.o
arm-none-eabi-gcc -Wall -O2 -nostdlib -nostartfiles -ffreestanding -mthumb -mcpu=cortex-m3 -march=armv7-m -c fun.c -o fun.o
arm-none-eabi-ld -o hello.elf -T memmap vectors.o notmain.o fun.o
arm-none-eabi-objdump -D hello.elf > hello.list
arm-none-eabi-objcopy hello.elf -O binary hello.bin

所以如果链接器脚本(memmap 是我使用的名称)看起来像这样
MEMORY
{
rom : ORIGIN = 0x00000000, LENGTH = 0x40000
ram : ORIGIN = 0x20000000, LENGTH = 0x8000
}

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

由于以上所有内容都是 .text,没有 .bss 或 .data,链接器采用 ld 命令行中列出的对象并将它们放在从该地址开始的位置...

.text 部分的 mbly:
00000000 <hang-0x10>:
0: 20008000 andcs r8, r0, r0
4: 00000013 andeq r0, r0, r3, lsl r0
8: 00000011 andeq r0, r0, r1, lsl r0
c: 00000011 andeq r0, r0, r1, lsl r0

00000010 <hang>:
10: e7fe b.n 10 <hang>

00000012 <_start>:
12: f000 f801 bl 18 <notmain>
16: e7fb b.n 10 <hang>

00000018 <notmain>:
18: 2007 movs r0, #7
1a: f000 b801 b.w 20 <fun>
1e: bf00 nop

00000020 <fun>:
20: 4770 bx lr
22: bf00 nop

因此,要使其正常工作,您必须小心地将 bootstrap 代码放在命令行中。但是您也可以使用链接描述文件执行此类操作。

顺序似乎很重要,首先列出特定的目标文件,然后是通用的 .text
MEMORY
{
romx : ORIGIN = 0x00000000, LENGTH = 0x1000
romy : ORIGIN = 0x00010000, LENGTH = 0x1000
ram : ORIGIN = 0x00030000, LENGTH = 0x1000
bob : ORIGIN = 0x00040000, LENGTH = 0x1000
ted : ORIGIN = 0x00050000, LENGTH = 0x1000
}

SECTIONS
{
abc : { vectors.o } > romx
def : { fun.o } > ted
.text : { *(.text*) } > romy
.bss : { *(.bss*) } > ram
}

我们得到这个
00000000 <hang-0x10>:
0: 20008000 andcs r8, r0, r0
4: 00000013 andeq r0, r0, r3, lsl r0
8: 00000011 andeq r0, r0, r1, lsl r0
c: 00000011 andeq r0, r0, r1, lsl r0

00000010 <hang>:
10: e7fe b.n 10 <hang>

00000012 <_start>:
12: f00f fff5 bl 10000 <notmain>
16: e7fb b.n 10 <hang>

Disassembly of section def:

00050000 <fun>:
50000: 4770 bx lr
50002: bf00 nop

Disassembly of section .text:

00010000 <notmain>:
10000: 2007 movs r0, #7
10002: f03f bffd b.w 50000 <fun>
10006: bf00 nop

简短的回答是使用 gnu 工具,您使用链接器脚本来操纵事情结束的位置,我假设您希望这些函数位于某个指定位置的 rom 中。我不太明白你在做什么。但是,例如,如果您尝试在 flash 中最初将 main() 分支这样简单的东西放在 flash 中,而 main() 在 flash 中更深,那么不知何故,无论是通过 flash 中更深的任何代码还是通过某种其他方法,然后之后你只删除和重新编程接近零的东西。第一次你仍然需要一个简单的 main() 分支。您可以强制我所说的vectors.o 位于地址零,然后.text 可以在闪存中更深,将所有代码的重置基本上放在那里,然后将其留在闪存中并仅替换为零的内容。

像这样
MEMORY
{
romx : ORIGIN = 0x00000000, LENGTH = 0x1000
romy : ORIGIN = 0x00010000, LENGTH = 0x1000
ram : ORIGIN = 0x00030000, LENGTH = 0x1000
bob : ORIGIN = 0x00040000, LENGTH = 0x1000
ted : ORIGIN = 0x00050000, LENGTH = 0x1000
}

SECTIONS
{
abc : { vectors.o } > romx
.text : { *(.text*) } > romy
.bss : { *(.bss*) } > ram
}

给予
00000000 <hang-0x10>:
0: 20008000 andcs r8, r0, r0
4: 00000013 andeq r0, r0, r3, lsl r0
8: 00000011 andeq r0, r0, r1, lsl r0
c: 00000011 andeq r0, r0, r1, lsl r0

00000010 <hang>:
10: e7fe b.n 10 <hang>

00000012 <_start>:
12: f00f fff7 bl 10004 <notmain>
16: e7fb b.n 10 <hang>

Disassembly of section .text:

00010000 <fun>:
10000: 4770 bx lr
10002: bf00 nop

00010004 <notmain>:
10004: 2007 movs r0, #7
10006: f7ff bffb b.w 10000 <fun>
1000a: bf00 nop

然后留下 0x10000 的东西,稍后替换 0x00000 的东西。

无论如何,简短的回答是链接器脚本,您需要制作链接器脚本以将内容放在您想要的位置。 gnu 链接器脚本可能会变得非常复杂,我倾向于简单的。

如果你想把所有东西都放在其他地址,包括你的向量表,那么可能是这样的:

酒花
.cpu cortex-m3
.thumb

.word 0x20008000 /* stack top address */
.word _start /* Reset */
.word hang
.word hang
/* ... */

.thumb_func
hang: b .

.thumb_func
ldr r0,=_start
bx r0

和这个
MEMORY
{
romx : ORIGIN = 0x00000000, LENGTH = 0x1000
romy : ORIGIN = 0x00010000, LENGTH = 0x1000
ram : ORIGIN = 0x00030000, LENGTH = 0x1000
bob : ORIGIN = 0x00040000, LENGTH = 0x1000
ted : ORIGIN = 0x00050000, LENGTH = 0x1000
}

SECTIONS
{
abc : { hop.o } > romx
.text : { *(.text*) } > romy
.bss : { *(.bss*) } > ram
}

给这个
Disassembly of section abc:
00000000 <hang-0x10>:
0: 20008000 andcs r8, r0, r0
4: 00010013 andeq r0, r1, r3, lsl r0
8: 00000011 andeq r0, r0, r1, lsl r0
c: 00000011 andeq r0, r0, r1, lsl r0

00000010 <hang>:
10: e7fe b.n 10 <hang>
12: 4801 ldr r0, [pc, #4] ; (18 <hang+0x8>)
14: 4700 bx r0
16: 00130000
1a: 20410001

Disassembly of section .text:

00010000 <hang-0x10>:
10000: 20008000 andcs r8, r0, r0
10004: 00010013 andeq r0, r1, r3, lsl r0
10008: 00010011 andeq r0, r1, r1, lsl r0
1000c: 00010011 andeq r0, r1, r1, lsl r0

00010010 <hang>:
10010: e7fe b.n 10010 <hang>

00010012 <_start>:
10012: f000 f803 bl 1001c <notmain>
10016: e7fb b.n 10010 <hang>

00010018 <fun>:
10018: 4770 bx lr
1001a: bf00 nop

0001001c <notmain>:
1001c: 2007 movs r0, #7
1001e: f7ff bffb b.w 10018 <fun>
10022: bf00 nop

然后您可以将向量表更改为 0x10000 例如。

如果你问一个不同的问题,比如将引导加载程序放在 0x00000,那么引导加载程序会修改闪存以添加一个应用程序,比如在 0x20000,那么你想运行该应用程序,有更简单的解决方案,不一定需要你修改的位置向量表。

关于gcc for ARM - 移动代码和堆栈,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18157773/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com