学习U-boo源码(转自互连网Linux系统移植.pdf)

来源:互联网 发布:数据战略商业案例 编辑:程序博客网 时间:2024/06/07 10:18

    大多数bootloader都分为阶段1(stage1)和阶段2(stage2)两大部分,uboot也不例外。依赖于CPU体系结构的代码(如CPU初始化代码等)通常都放在阶段1中且通常用汇编语言实现,而阶段2则通常用C语言来实现,这样可以实现复杂的功能,而且有更好的可读性和移植性。

   阶段1介绍
uboot的stage1代码通常放在start.s文件中,它用汇编语言写成,其主要代码部分如下:
  一、 定义入口
由于一个可执行的Image必须有一个入口点,并且只能有一个全局入口,通常这个入口放在ROM(Flash)的0x0地址,因此,必须通知编译器以使其知道这个入口,该工作可通过修改连接器脚本来完成。
1. board/crane2410/uboot.lds: ENTRY(_start) ==> cpu/arm920t/start.S: .globl _start
2. uboot代码区(TEXT_BASE = 0x33F80000)定义在board/crane2410/config.mk

二、 设置异常向量
_start: b reset @ 0x00000000
ldr pc, _undefined_instruction @ 0x00000004
ldr pc, _software_interrupt @ 0x00000008
ldr pc, _prefetch_abort @ 0x0000000c
ldr pc, _data_abort @ 0x00000010
ldr pc, _not_used @ 0x00000014
ldr pc, _irq @ 0x00000018
ldr pc, _fiq @ 0x0000001c
当发生异常时,执行cpu/arm920t/interrupts.c中定义的中断处理函数。
三、 设置CPU的模式为SVC模式
mrs r0,cpsr
bic r0,r0,#0x1f
orr r0,r0,#0xd3
msr cpsr,r0
四、 关闭看门狗
#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)
ldr r0, =pWTCON
mov r1, #0x0 @ 根据三星手册进行调置。
str r1, [r0]
五、 禁掉所有中断
mov r1, #0xffffffff
ldr r0, =INTMSK
str r1, [r0]
# if defined(CONFIG_S3C2410)
ldr r1, =0x3ff
ldr r0, =INTSUBMSK
str r1, [r0]
六、设置以CPU的频率
默认频率为 FCLK:HCLK:PCLK = 1:2:4,默认FCLK的值为120 MHz,该值为S3C2410手册的推荐值。
ldr r0, =CLKDIVN
mov r1, #3
str r1, [r0]
七、 设置CP15
设置CP15, 失效指令(I)Cache和数据(D)Cache后, 禁止MMU与Cache。
cpu_init_crit:
mov r0, #0
mcr p15, 0, r0, c7, c7, 0 /* 失效I/D cache, 见S3C2410手册附录的2-16 */
mcr p15, 0, r0, c8, c7, 0 /* 失效TLB, 见S3C2410手册附录的2-18 */
/*
* 禁止 MMU 和caches, 详见S3C2410手册附录2-11
*/
mrc p15, 0, r0, c1, c0, 0
bic r0, r0, #0x00002300 /* 清除 bits 13, 9:8 (--V- --RS)
* Bit 8: Disable System Protection
* Bit 7: Disable ROM Protection
* Bit 13: 异常向量表基地址: 0x0000 0000
*/
bic r0, r0, #0x00000087 /* 清除 bits 7, 2:0 (B--- -CAM)
* Bit 0: MMU disabled
* Bit 1: Alignment Fault checking disabled
* Bit 2: Data cache disabled
* Bit 7: 0 = Little-endian operation
*/
orr r0, r0, #0x00000002 /* set bit 2 (A) Align, 1 = Fault checking enabled */
orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache, 1 = Instruction cache enabled
*/
mcr p15, 0, r0, c1, c0, 0
八、配置内存区控制寄存器
配置内存区控制寄存器,寄存器的具体值通常由开发板厂商或硬件工程师提供. 如果您对总线周期及外围
芯片非常熟悉, 也可以自己确定, 在UBOOT
中的设置文件是board/crane2410/lowlevel_init.S, 该文件包含
lowleve_init程序段. 详细寄存器设置及值的解释见3.2.2 启动AXD 配置开发板一节中的第5点.
mov ip, lr
bl lowlevel_init
mov lr, ip
九、 安装U-BOOT使的栈空间
下面这段代码只对不是从Nand Flash启动的代码段有意义,对从Nand Flash启动的代码,没有意义。因为
从Nand Flash中把UBOOT执行代码搬移到RAM,由2.1.9中代码完成.
#ifndef CONFIG_SKIP_RELOCATE_UBOOT
...
#endif
stack_setup:
ldr r0, _TEXT_BASE /* 代码段的起始地址 */
sub r0, r0, #CFG_MALLOC_LEN /* 分配的动态内存区 */
sub r0, r0, #CFG_GBL_DATA_SIZE /* UBOOT开发板全局数据存放 */
#ifdef CONFIG_USE_IRQ
/* 分配IRQ和FIQ栈空间 */
sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
sub sp, r0, #12 /* 留下3个字为Abort */
十、BSS段清0
clear_bss:
ldr r0, _bss_start /* BSS段的起始地址 */
ldr r1, _bss_end /* BSS段的结束地址 */
mov r2, #0x00000000 /* BSS段置0 */
clbss_l:str r2, [r0] /* 循环清除BSS段 */
add r0, r0, #4
cmp r0, r1
ble clbss_l
十一、 搬移Nand Flash代码
从Nand Flash中, 把数据拷贝到RAM, 是由copy_myself程序段完成, 该程序段详细解释见:第七部分的3.1节.
#ifdef CONFIG_S3C2410_NAND_BOOT
bl copy_myself
@ jump to ram
ldr r1, =on_the_ram
add pc, r1, #0
nop
nop
1: b 1b @ infinite loop
on_the_ram:
#endif
十二、进入C代码部分
ldr pc, _start_armboot
_start_armboot: .word start_armboot
 阶段2的C语言代码部分 
lib_arm/board.c中的start armboot是C语言开始的函数,也是整个启动代码中C语言的主函数,同时还是整个uboot(armboot)的主函数,该函数主要完成如下操作:
一、调用一系列的初始化函数
1. 指定初始函数表:
init_fnc_t *init_sequence[] = {
cpu_init, /* cpu的基本设置 */
board_init, /* 开发板的基本初始化 */
interrupt_init, /* 初始化中断 */
env_init, /* 初始化环境变量 */
init_baudrate, /* 初始化波特率 */
serial_init, /* 串口通讯初始化 */
console_init_f, /* 控制台初始化第一阶段 */
display_banner, /* 通知代码已经运行到该处 */
dram_init, /* 配制可用的内存区 */
display_dram_config,
#if defined(CONFIG_VCMA9) || defined (CONFIG_CMC_PU2)
checkboard,
#endif
NULL,
};
执行初始化函数的代码如下:
for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
if ((*init_fnc_ptr)() != 0) {
hang ();
}
}
2. 配置可用的Flash区
flash_init ()
3. 初始化内存分配函数
mem_malloc_init()
4. nand flash初始化
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
puts ("NAND:");
nand_init(); /* 初始化 NAND */
5. 初始化环境变量
env_relocate ();
6. 外围设备初始化
devices_init()
7. I2C总线初始化
i2c_init();
8. LCD初始化
drv_lcd_init();
9. VIDEO初始化
drv_video_init();
10. 键盘初始化
drv_keyboard_init();
11. 系统初始化
drv_system_init();
二、 初始化网络设备
初始化相关网络设备,填写IP、MAC地址等。
1. 设置IP地址
/* IP Address */
gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");
/* MAC Address */
{
int i;
ulong reg;
char *s, *e;
uchar tmp[64];
i = getenv_r ("ethaddr", tmp, sizeof (tmp));
s = (i > 0) ? tmp : NULL;
for (reg = 0; reg < 6; ++reg) {
gd->bd->bi_enetaddr[reg] = s ? simple_strtoul (s, &e, 16) : 0;
if (s)
s = (*e) ? e + 1 : e;
}
}
三、进入主UBOOT命令行
进入命令循环(即整个boot的工作循环),接受用户从串口输入的命令,然后进行相应的工作。
for (;;) {
main_loop (); /* 在common/main.c */
}
四、 代码搬运
  为了支持NAND flash起动,S3C2410内建了内部的4k的SRAM缓存“Steppingstone”。当起动时,NAND flash最初的4k字节将被读入”Steppingstone”然后开始执行起动代码。通常起动代码会把NAND flash中的内容拷到SDRAM中以便执行主代码。
  使用硬件的ECC, NAND flash中的数据的有效性将会得到检测。
功能
1. NAND flash 模式:支持读/删除/编程 NAND Flash
2. 自动起动模式:在复位时起动代码将被读入”Steppingstone”中,然后开始执行起动代码。
3. 硬件ECC检测模块(硬件检测,软件纠正)
4. “Steppingstone” 4KB
内部SRAM在起动后可以另外使用。

原创粉丝点击