iROM code(无源码)
1.1 关闭看门狗
1.2 关闭中断和MMU
1.3 关闭D-cache,打开I-cache
1.4 FLush TLB’s and Invalidate caches
1.5 初始化IRQ和SVC模式的栈
1.6 初始化ZI/RW
1.7 注册函数指针?
1.8 得到重启状态
1.9 设置时钟分频和锁相环
1.10 根据OM引脚状态选择引导设备
1.11 拷贝BL1到iRAM并判断是否拷贝成功
1.12 校验和
1.13 验证BL1完整性
1.14 解译BL1
1.15 跳转到BL1BL1(无源码)
2.1 初始化IRQ和SVC栈
2.2 判断引导设备
2.3 从拷贝BL2到iRAM
2.4 进行一些判断决定是否跳转到BL2
2.5 验证BL2完整性,验证正确就跳转到BL2BL2
3.1 初始化IRQ和SVC模式的栈(各个模式都有各自独立的栈)
3.2 设置时钟频率
3.3 初始化内存
3.4 将OS镜像拷贝到DRAM,验证完整性后跳转。uboot
start.S:
4.1 跳转到reset
4.2 将cpu设置为svc模式,并关闭IRQ和FIQ中断(为什么设置为svc模式,因为svc特权模式可以访问的硬件资源最多,其次uboot要跳转到kernel之前,CPU必须处于svc模式)
4.3 初始化TLB和I-cache
4.4 禁能MMU和caches
4.5 读取引导信息,判断引导设备
4.6 跳转到lowlevel_init(配置pll, mux, memory(因为要将uboot后续代码拷贝到DRAM,所以要先初始化))
4.6.1 初始化DDR内存
bl mem_ctrl_asm_init_ddr3(这个函数在cpu_init.S中实现)
4.7 判断是够已经拷贝过uboot
4.8 根据引导设备执行不同的拷贝函数
4.9 拷贝完成后跳转到after_copy处
4.10 使能MMU,设置TTB
4.11 初始化栈,清除bss段(初始化C语言环境)
4.12 跳转到start_armboot函数,在/lib_arm/board.c中
4.13 完成一些初始化工作后,进入死循环
for(;;)
{
main_loop();
}
4.14 main_loop:
4.14.1 s = getenv (“bootcmd”); 获取引导命令
4.14.2 如果延时大于等于零,并且没有在延时过程中接收到按键,则引导内核
if (bootdelay >= 0 && s && !abortboot (bootdelay))
run_command(s, 0);
4.14.2.1 abortboot中会检查延时是否大于等于零并且是否有按键按下,如果延时大于零并且停止引导内核标记没有被赋值则进入延时循环,直到延时完成或者接收到按键。
1. 延时完成且无按键按下,进入内核,即运行 run_command(s, 0),也就是运行”bootcmd”命令行参数所定义的值
2. 延时期间按键按下,进入uboot命令行
如何去寻找bootcmd命令行参数所定义的值?
1. getenv (“bootcmd”)
2. env_get_addr(val)
3. default_environment(数组)
4. CONFIG_BOOTCOMMAND(对其进行查找引用)
5. smdkc210.h(y:/include/configs)
6. #define CONFIG_BOOTCOMMAND “nand read 40008000 80000 380000;bootm 40008000”
最后,分析这两个uboot命令:
nand read 40008000 80000 380000 将flash 0x8000起始地址处,拷贝0x380000长度的数据(即内核镜像)到内存0x40008000起始处
bootm 40008000 执行内存0x40008000地址处的代码,即启动到内核(见于笔记“内核驱动 - U-Boot命令”)