1. 所先在Target Settings里的Linker 选种 ARM Linker, Post-linker 选种ARM fromELF
使得工程连接后在通过fromELF产生2进制代码
如图
2. 在ARM Linker 有2个非常重要的设置
第一个,output中 RO base 和RW base
第二个,Layout中 Object/symbol与section
好现在要重点讲这两个设置,大家不妨打开bios的源代码找到如下代码
IMPORT |Image
RO
Base| ; ROM code start
IMPORT |Image
RO
Limit| ; RAM data starts after ROM program
IMPORT |Image
RW
Base| ; Pre-initialised variables
IMPORT |Image
Z
I
Base| ; uninitialised variables
IMPORT |Image
Z
I
Limit| ; End of variable RAM spaceBaseOfROM DCD |Image
RO
Base|
TopOfROM DCD |Image
RO
Limit|
BaseOfBSS DCD |Image
RW
Base|
BaseOfZero DCD |Image
Z
I
Base|
EndOfBSS DCD |Image
Z
I
Limit|output中 RO base中设定的值经过编译器处理后传递给|Image
RO
Base|,然后负值给
BaseOfROM
RW base 设定的值经过编译器处理后传递给|Image
RW
Base|,然后负值给BaseOfBSS好,现在引出一个重要的概念section(段)
连接后的生成ELF格式的文件包括8个section
.text,.rel.text,.rodata,.data,.bss,.shstrtab,.symtab,.strtab,经过fromELF处理后
生产的2进制代码,2进制代码中只包含3个段.text,.data,.bss
PS:其实还有.rodata,只是将其归到.text中了
这就是为什么我们要在Post-linker中选种fromELF
举个例子
假设我的bios只有2个文件1.c,2.c那么编译和连接生成3.bin(3.bin为最终烧写到flash的
2进制文件)过程如下图
.text section 的大小为 |Image
RO
Limit| - |Image
RO
Base|,起始位置为
|Image
RO
Limit|.data section 的大小为 |Image
Z
I
Base| - |Image
RW
Base|, 起始位置为
|Image
Z
I
Base| .bss section 的大小为 |Image
Z
I
Limit| - |Image
Z
I
Base| 起始位置为
|Image
Z
I
Limit|不知道大家注意到了没有在3.bin中.data,.bss是紧跟着.text段的
换句话说如果3.bin中.text大小为10K,则.data是紧跟在10K之后,
哎,奇怪了ads中不是设置了.data起始位置为|Image
Z
I
Base|,那实际在3.bin中,.d
ata却不是在我们要设置的位置了
那bios在执行时它到.data段(ADS中设置的.data位置)中去数据,肯定是取不到数据啊脑子有点晕了吧
呵呵,这个问题就是要靠bios来完成各段的搬移工作地,如图我们设置RO base为0x0c700
000 ,RW base为0x0c008000
将RO base设置为0x0c700000总要是为了让bios在SDRAM里运行,如果RO base为0x0则它将
在flash 中运行,如图
你可以在bios中找到如下代码
adr r0, ResetEntry
ldr r1, BaseOfROM
cmp r0, r1
ldreq r0, TopOfROM
beq InitRamData //如果ResetEntry==BaseOfROM 既RO base为0x0它将在flash 中运行,不等要进行代码搬迁
ldr r2, =CopyProcBeg
sub r1, r2, r1
add r0, r0, r1
ldr r3, =CopyProcEnd
0
ldmia r0!, {r4-r7}
stmia r2!, {r4-r7}
cmp r2, r3
bcc %B0 //先把拷贝代码搬迁到SDRAM中
ldr r3, TopOfROM
ldr pc, =CopyProcBeg //跳到SDRAM中刚刚搬迁好的拷贝代码中去执行
//以下是拷贝bios代码到SDRAM中去的拷贝代码 :)有点晕吧,好好理解一下
CopyProcBeg
0
ldmia r0!, {r4-r11}
stmia r2!, {r4-r11}
cmp r2, r3
bcc %B0
CopyProcEnd
//以上代码完成整个bios代码到SDRAM中的COPY,OK,以后的bios执行都在SDRAM中了
接着就是完成.data,.bss的重定位了
//以下完成.data的重定位
sub r1, r2, r3
sub r0, r0, r1 //r0为.data在3.bin中的开始位置
InitRamData
ldr r2, BaseOfBSS //搬迁到ADS设置的位置
ldr r3, BaseOfZero
0
cmp r2, r3
ldrcc r1, [r0], #4
strcc r1, [r2], #4
bcc %B0
//将.bss段清0,r2为.bss在3.bin中的开始位置
mov r0, #0
ldr r3, EndOfBSS
1
cmp r2, r3
strcc r0, [r2], #4
bcc %B1
最后跳到main中去
ldr pc, GotoMain
再好好理解一下,.....................时间过了5分钟
接着,讲讲关于Layout中 Object/symbol与section的设置
Object/symbol为连接时放在最前面的.o文件,即与系统设置相关的文件,section为这个
文件
的中.text的开始位置
大家可以看看bios的文件,我的为vector.s,
所以Object/symbol为vector.o
在这个文件里有
AREA SelfBoot, CODE, READONLY
所以section为SelfBoot,如图
3. ARM fromELF的设置
Output format为生成2进制文件的格式
output file name 为生成2进制文件的路径和名字
如图
OK,我要讲的就这么多,bios还有很多的地方值得研究的,不管是加深对计算机启动理解
,还是C语言编程都很有帮助,是一个很好的学习代码 |