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$$ZI$$Base| ; uninitialised variables
IMPORT |Image$$ZI$$Limit| ; End of variable RAM space
BaseOfROM DCD |Image$$RO$$Base|
TopOfROM DCD |Image$$RO$$Limit|
BaseOfBSS DCD |Image$$RW$$Base|
BaseOfZero DCD |Image$$ZI$$Base|
EndOfBSS DCD |Image$$ZI$$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$$Base|
.data section 的大小为 |Image$$ZI$$Base| - |Image$$RW$$Base|, 起始位置为
|Image$$RW$$Base|
.bss section 的大小为 |Image$$ZI$$Limit| - |Image$$ZI$$Base| 起始位置为
|Image$$ZI$$Base|
不知道大家注意到了没有在3.bin中.data,.bss是紧跟着.text段的
换句话说如果3.bin中.text大小为10K,则.data是紧跟在10K之后,
哎,奇怪了ads中不是设置了.data起始位置为|Image$$ZI$$Base|,那实际在3.bin中,.data却不是在我们要设置的位置了,那bios在执行时它到.data段(ADS中设置的.data位置)中取数据,肯定是取不到数据啊
脑子有点晕了吧
呵呵,这个问题就是要靠bios来完成各段的搬移工作地,如图我们设置RO base为0x0c700000 ,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语言编程都很有帮助,是一个很好的学习代码