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$$Limit|
.data section 的大小为 |Image$$ZI$$Base| - |Image$$RW$$Base|, 起始位置为
|Image$$ZI$$Base|
.bss section 的大小为 |Image$$ZI$$Limit| - |Image$$ZI$$Base| 起始位置为
|Image$$ZI$$Limit|
不知道大家注意到了没有在3.bin中.data,.bss是紧跟着.text段的
换句话说如果3.bin中.text大小为10K,则.data是紧跟在10K之后,
哎,奇怪了ads中不是设置了.data起始位置为|Image$$ZI$$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语言编程都很有帮助,是一个很好的学习代码
使得工程连接后在通过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$$Limit|
.data section 的大小为 |Image$$ZI$$Base| - |Image$$RW$$Base|, 起始位置为
|Image$$ZI$$Base|
.bss section 的大小为 |Image$$ZI$$Limit| - |Image$$ZI$$Base| 起始位置为
|Image$$ZI$$Limit|
不知道大家注意到了没有在3.bin中.data,.bss是紧跟着.text段的
换句话说如果3.bin中.text大小为10K,则.data是紧跟在10K之后,
哎,奇怪了ads中不是设置了.data起始位置为|Image$$ZI$$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语言编程都很有帮助,是一个很好的学习代码
本文详细介绍了ARM BIOS启动过程中的内存布局配置方法,包括如何使用ARMLinker和fromELF工具生成二进制代码,以及如何通过设置RObase和RWbase实现不同内存段的定位与重定位。

1391

被折叠的 条评论
为什么被折叠?



