U boot the universal boot loader
介绍:
u boot是德国的DENX公司的,denx也做ELDK (编译工具,环境,相当于poky ),以前u boot放在sourceforge (1.1.6版本以及之前的版本)
现在以及全部转移到自己的网站了, ,文档在:/Documentation
版本:
uboot版本之间也有些差别,但差别没有像linux kernel版本之间的差别那么大,比如新的版本里有mtd ,而之前的版本里没有
特性 :
中断支持 CONFIG_USE_IRQ
已经有auto update功能了 ,用TFTP或者USB来实现, 一些板子实现了USB update功能
文件系统已经支持了FAT , JFFS , YAFFS等
目录结构 : 以u-boot-2009.11.1 为例
api --> 于芯片,架构无关的一些api 库
board ----> 针对板
cpu ----> 针对cpu
include/config ---> 配置SDRAM/Flash
driver ---> 各种驱动
lib_xxx ---> 各种架构的库文件
net --> 实现了各种协议,比如tftp , dns , nfs
common --> 各种uboot 的命令
fs --> 各种文件系统的支持,比如jffs,yaffs
post --> Power On Self Test 上电后的一些自检测
tools --> 各种工具 比如生产uImage的工具
nand_spl --> nand boot 目录
NOR Boot:
LDFLAGS += -Bstatic -T $(obj)u-boot.lds $(PLATFORM_LDFLAGS)
ifneq ($(TEXT_BASE),)
LDFLAGS += -Ttext $(TEXT_BASE)
endif
这样text段的定位为TEXT_BASE 而非 0 。
参见 http://www.cnitblog.com/buf/archive/2009/05/23/37636.html
Nor boot就是当芯片一上电的时候,芯片从NOR Flash的{BANNED}中国第一个字节开始取代码执行,在NOR Flash的开头处存的是8个向量表,指令分别为:
b reset , //这个是相对的跳转,也就是不论代码在哪里运行, b reset 将跳到相对目前_start的一个偏移位置
ldr pc _undefined_instruction, //绝对的跳转
_software_interrupt
,_data_abort,_not_used,_irq,_fiq . 这样执行reset .
然后芯片初始化(比如disable MMU)以及SDRAM的初始化
对于Nor boot,有两种方式,一种是uboot代码一直在nor中跑(定义宏CONFIG_SKIP_RELOCATE_UBOOT )还一种是把代码从nor flash中搬移到SDRAM中,
对于后一种,需要relocate,我们来分析一下下面的代码.
relocate: /* relocate U-Boot to RAM */
adr r0, _start /* 得到_start的地址,如果在NOR中到,那就是NOR flash的地址 (每个芯片都不一样,参加address map */
ldr r1, _TEXT_BASE /*把_TEXT_BASE位置所存储的值给r1,它存储的值为TEXT_BASE,TEXT_BASE在板子的config.mk中定义 */
cmp r0, r1 /* 当调试的时候,比如用JTAG,直接把uboot下载到SDRAM中了,然后从SDRAM中跑,此时的_start就为_TEXT_BASE了 */
beq stack_setup /*调试的时候 不需把代码从NOR copy到SDRAM */
ldr r2, _armboot_start
ldr r3, _bss_start
sub r2, r3, r2 /* text段的大小 */
add r2, r0, r2 /* r2 变成 text的{BANNED}最佳末位置 ,r0为_start 运行时候的地址 */
copy_loop:
ldmia r0!, {r3-r10} /* copy from source address [r0] */
stmia r1!, {r3-r10} /* copy to target address [r1] */
cmp r0, r2 /* until source end addreee [r2] */
ble copy_loop
这里主要要区别三个操作:
adr : 得到运行时候的地址,也就是当代码运行在_start时候的PC值
使用的格式:ADR register,exper。
伪指令,编译器在编译程序的时候,会计算出此行代码与_start的偏移,然后加上此时的PC,就得到_start时候的PC值
ldr : 把_TEXT_BASE位置所存储的值给r1
ldr r1, =_TEXT_BASE
r1 = _TEXT_BASE位置
然后 初始化完堆栈后
ldr pc, _start_armboot /*如果代码是从NOR flash 搬移到SDRAM中, 则_start_armboot 为SDRAM中的位置,因为link的时候,加上了TEXT_BASE, 而TEXT_BASE为SDRAM中的一个位置 */
还有一个问题,就是关于中断, 对于中断,如果没有remap ,则发生中断就将跳到中断向量表处,也就是NOR Flash的地方了,
但是 我们看 ldr pc, _undefined_instruction , 这个代码在NOR flash中, 而_undefined_instruction 所指向的地址为 SDRAM中 (加上了TEXT_BASE) , 所以发生了中断后,跳转到NOR flash中,
然后nor flash在跳转到SDRAM中 。
Nand Boot :
Nand Boot的原理为简单: 当CPU上电启动的时候,它从某一个位置开始取代码,对于支持Nand booting的芯片,其内部有一小段固化的代码,里面包括了Flash的驱动。
此时,固化的代码根据芯片的引脚来判断是Nor启动还是Nand启动,如果是Nand启动,则从Nand Flash中load一小段代码,对于S3C2440为4K,S3C6410为8K到SRAM中(不是SDRAM,这小容量的SRAM集成在芯片里面,samsung芯片称之为stepping stone),然后代码在SRAM中运行。 对于u boot , 代码在SRAM后,它先执行 cpu_init_crit 来进行cpu的初始化(比如disable MMU)以及SDRAM的初始化
然后进行的是 : 把代码从NAND Flash中搬运到SDRAM中
以2410为例 : 定义 CONFIG_S3C2410_NAND_BOOT, 将跳入 nand_load , 这个比NOR load要复杂,因为NOR读是直接读的,而NAND读需要去配置NAND Flash 控制器 。
uboot的执行路线 :
1) cpu/arm920t/start.S
向量表 _start
reset (对cpu的内存,频率,中断向量表设定)
2) start_armboot lib_arm/board.c (重新初始化主频和外设等)
3) main_loop common/main.c
for(;;)
readline (读入命令)
run_command (执行命令)
命令 :
--u_boot_cmd_start 通过u_boot.lds 定位到u_boot_cmd , 这个表通过u_boot-CMD宏加入 (在command.h中定义)
编译 :
先 make smdk2410_config
然后 make all