我正在开发一个ARM Cortex-M3(SiLabs)SOC项目。我需要将中断向量[编辑]和代码从闪存底部移开,为“引导加载程序”腾出空间。当核心复位时,引导加载程序从地址0开始出现。它的功能是验证主图像,加载到更高的地址,并可能用新图像替换主图像。
因此,引导加载程序的向量表将为0,后跟其代码。在更高的固定地址(例如8KB)将是主要图像,从其向量表开始。
我找到了this page,它描述了引导加载程序可以使用的向量表偏移寄存器(显然屏蔽了中断)将硬件指向新的向量表。
我的问题是如何将“主”图像链接起来,以便在写入闪存时起作用,从零开始。我不熟悉ARM程序集,但我认为代码不是与位置无关的。
我正在使用SiLabs的Precision32 IDE,它使用gcc作为工具链。我发现了如何添加链接器标志。我的问题是gcc标志将提供对向量表和代码基础的更改。
谢谢。
答案 0 :(得分:6)
vectors.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
notmain.c
extern void fun ( unsigned int );
void notmain ( void )
{
fun(7);
}
fun.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命令行中列出的对象,并将它们从该地址开始...
mbly of section .text:
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
因此,要使其工作,您必须小心将引导代码放在命令行上。但您也可以使用链接描述文件执行此类操作。
顺序似乎很重要,先列出特定的目标文件,然后再列出通用的.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(),最初main()在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链接器脚本可以变得非常复杂,我倾向于简单。
如果你想把所有东西放在其他地址,包括你的矢量表,那么可能是这样的:
hop.s
.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,那么引导加载程序会修改flash以在0x20000处添加应用程序,然后你想要运行该应用程序,有一些更简单的解决方案,不一定要求你修改向量表的位置。