分类: LINUX
2011-02-28 20:15:14
s3c2410 u-boot 之 stage1
本文主要是基于大家比较熟悉的 s3c2410 ,对移植 u-boot 时 stage1 过程进行一个分析,网上关于之方面的资料很多,但是几乎都只是对代码作注解,容易让人产生知其一不知其二的感觉,在这里,我主要结合 u-boot 的 stage1 时的内存布局和 stage1 的具体指令来做个分析,这样看起来比较直观,更容易理解一些 .
我们要深入理解 u-boot 如何工作的,以及跟硬件都有什么依赖,我们需要先对 u-boot 及硬件有一个全局的认识。
在这之前,为了更多的人不会迷糊一些问题,先澄清几个概念:
_start : 这是 u-boot 的第一条指令入口地址 , 如果从 flash 启动,就是 0x0, 如果直接下载到 SDRAM 中执行,则是 TEXT_BASE=0x33F80000.
_TEXT_BASE :本身是一个地址,但是地址处放的内容是 TEXT_BASE,
s3c2410 中我们通常设为 0x33F80000, 通过 config.mk 中的 -Ttext $(TEXT_BASE) 来指定链接选项,从而更新链接脚本中的入口地址,不明白的去查查 linker and loader.
见 cpu/arm920t/start.S
_TEXT_BASE:
.word TEXT_BASE
_armboot_start : 本身也是一个地址,但是地址处放的内容是 _start ,如果 _start 是 0x33F80000, 那 _artboot_start 放的内容就是 0x33F80000 ,见 cpu/arm920t/start.S
_armboot_start:
.word _start
知道这三个地址之后,再看两条指令:
adr r0,_start /*r0 <- current position of code*/
这条指令网上讲得也很多,翻译过来就是 add r0,r0,[PC+#offset], 就是把通过一个地址来知道 _start 处的地址,注意是地址,即 TEXT_BASE=0x33F80000, 这步在链接的时候就已经确定了,或者你不用管那么多,你知道链接完成之后,这条指令相当于 mov r0,0x33F80000(sdram) 或者 mov r0,0x0(flash) 就行了。
ldr r1,_TEXT_BASE /* test if we run from flash or RAM */
注意,这里的 ldr 不是伪指令,伪指令表示时, ldr r1,=_TEXT_BASE
这两个的区别在于,伪指令是直接把 _TEXT_BASE 写入到 r1 中,这里 _TEXT_BASE 就代表一个地址,而 ldr r1,_TEXT_BASE, 是把 _TEXT_BASE 中存放的内容,也就是 TEXT_BASE=0x33F80000 写入到了 r1.
ldr r2, _armboot_start
结合上面讲的,应该知道,这条语句实际上是将 _armboot_start 中的内容,也就是 _start 的地址写入到了 r2 中,而非网上很多人问的是 _armboot_start 的地址 .
ldr r3, _bss_start
这跟上面一样分析了,定义见 cpu/arm920t/start.S
.globl _bss_start
_bss_start:
.word __bss_start
下面这两条语句也就好理解了:
sub r2, r3, r2 /* r2 <- armboot 大小 */
add r2, r0, r2 /* r2 <- 代码结束地址 */
到底 armboot 的大小都包含了哪些东西,结合 u-boot.lds ,见下图:
关于链接脚本,讲起来又很多了,不清楚的,建议看看 linker and loader ,清楚代码的编译链接及加载过程,是我们更深入的理解底层机制的根本。
在上面,我只是讲了几个平时可能遇到的,又不太理解的问题,关于 stage1 中代码的注释网上一搜就有一大把。看了注释,再结合,我讲的这几点,应该能弄清 stage1 中是如何拷贝代码的了。接下来,我们来看看为什么 TEXT_BASE 的值是 0x33F80000 呢?
先看一个 SDRAM 的内存映射图:同样结合上面的 uboot.lds
0x33F80000 |
0x30000000 |
0x33ffffff |
映射前 |
映射后 |
bss 段、 u-boot cmd 段、 .data 段 .rodata 段 及 .text 段及中断向量表 |
malloc 区域,见 start.S sub r0,r0, #CFG_MALLOC_LEN |
全局变量,见 start.S sub r0, r0, #CFG_GBL_DATA_SIZE |
IRQ:sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ) |
sub sp, r0, #12 /* leave 3 words for abort-stack */ |
. . |
|
bss 段 |
u-boot cmd 段 |
.data 数据段 |
.rodata 只读数据段, |
入口 20 字节中断向量表 .text(start.o 及 *(.text)) |
在 S3C2410 中,查看 datasheet , 64M SDRAM 地址空间即为 0x30000000 到 0x33ffffff ,在 bank6 中,而 flash 映射地址为 0x0 开始。
TEXT_BASE=0x33F80000 即为程序加载起始地址,可以使用的空间大小即为 0x33F80000 到 0x33FFFFFF 共 512K ,如果你 u-boot 包含的功能太多,觉得不够用,你可以把 0x33F80000 调小一点,即和往低地址移一些,移的过程中注意 memory page 对齐就行了,一般是 4KB.