分类: LINUX
2013-09-20 23:24:44
原文地址:U-BOOT知识整理 作者:星闪夜空
1、BootLoader的作用
其实BootLoader主要的必须的作用只有一个:就是把操作系统映像文件拷贝到RAM中去,然后跳转到它的入口处去执行。
BootLoader并不是必须的,如果我们的硬件有足够大的NorFlash,并且实现了XIP技术,那么Linux操作系统可以直接在NorFlash里面运行起来,不需要将它复制到RAM中去,所以BootLoader就失去了作用。
2、BootLoader的两个阶段
1) BootLoader第一阶段的功能
l 硬件设备初始化(start.S)
依次完成如下设置:将CPU的工作模式设为管理模式(svc),关闭WATCHDOG,设置FCLK、HCLK、PCLK的比例为1:2:4(即设置CLKDIVN寄存器),关闭MMU、CACHE。
l 为加载BootLoader的第二阶段代码准备RAM空间(lowlevel_init.S)
所谓准备RAM空间,就是初始化内存芯片,使它可用。通过在start.S中调用lowlevel_init函数来设置存储控制器,使得外接的SDRAM可用。
l 复制BootLoader的第二阶段代码到RAM空间中(start.S)
这里将整个U-Boot的代码(包括第一、第二阶段)都复制到SDRAM中。
l 设置好栈(start.S)
让sp寄存器指向一段没有使用的内存即可。
l 跳转到第二阶段代码的C入口点,即start_armboot函数(start.S)
在跳转之前,还要清除BSS段(初始值为0、无初始值的全局变量、静态变量放在BSS段)。
2) BootLoader第二阶段的功能
l 在cpu_init函数中为IRQ、FIQ模式划分了栈,此时U-Boot内存使用图如下:
l 初始化本阶段要使用到的硬件设备
最主要的是设置系统时钟(board_init:该函数还保存机器类型ID和U-Boot传递给内核的参数的地址)、初始化串口(serial_init)。
l 检测系统内存映射(dram_init)
l 将内核映像和根文件系统映像从Flash上读到RAM空间中
main_loop->run_command->find_cmd(argv[0])->do_tftpb(使用tftp协议下载内核映像)。
l 为内核设置启动参数
l 调用内核(do_bootm_linux->theKernel (0, bd->bi_arch_number, bd->bi_boot_params))
由此可知U-Boot第二阶段的流程图如下:
3、U-BOOT命令的格式
例:U_BOOT_CMD(
ping, 2, 1, do_ping,
"ping\t- send ICMP ECHO_REQUEST to network host\n",
"pingAddress\n"
);
l U-Boot所支持的每个命令均有一个结构体与其相对应。
l 所有结构体依次存放在U-Boot最终的二进制代码中。
l 结构体集合在内存中的起始地址由符号__u_boot_cmd_start表示;结束地址由符号__u_boot_cmd_end表示。
l find_cmd函数以命令名字符串为查找标准遍历整个结构体集合,从而找到与该命令对应的结构体。
4、U-Boot引导Linux操作系统的过程分析
对于bootcmd tftp 31000000 uImage \; bootm 31000000,首先会调用do_tftpb函数将uImage通过tftp协议下载到RAM的0x31000000这个位置,然后调用do_bootm命令使用已经位于RAM地址0x31000000处的Linux kernel启动操作系统。在do_bootm函数中,首先校验64B头以及zImage是否完整正确,其次将zImage从0x31000040复制到kernel的正确加载地址0x30008000,最后调用do_bootm_linux函数启动linux。在do_bootm_linux函数中,首先会设置Linux内核的启动参数,然后通过执行theKernel (0, bd->bi_arch_number, bd->bi_boot_params)跳转到Linux内核的第一条指令,从此U-Boot一去不复返,Linux操作系统到来了。
5、调用内核前需要满足的条件
1) CPU寄存器的设置
l R0=0
l R1=机器类型ID
l R2=启动参数标记列表在RAM中起始基地址
2) CPU工作模式
l 必须禁止中断(IRQs和FIQs)
l CPU必须为SVC模式
3) Cache和MMU的设置
l MMU必须关闭
l 指令Cache可以打开也可以关闭
l 数据Cache必须关闭
6、BootLoader与内核的交互
BootLoader将参数放在某个约定的地方(0x30000100)之后,再启动内核,内核启动后从这个地方获得参数。
7、SDRAM为什么每隔一段时间需要刷新
SDRAM的一个bit,存储电容上有电荷表示1,无电荷表示0.但由于存储电容有自动放电的物理属性,因此要维持SDRAM正确运行就必须定期给电容充电,这个周期性的充电操作称为内存刷新,它是由内存控制器自动完成的。