最近在做展讯Android手机驱动的开发,需要能清楚U-Boot启动过程,然后书写相关的驱动代码。而像lcd驱动一般会在u-boot启动的过程中便会选择加载某一特定的驱动,而且u-boot和kernel中的代码大致相同,因为Android开机过程便会显示开机logo,这涉及到显示的部分驱动。u-boot启动过程可以分为两个阶段,两个阶段的功能如下:
StageI:第一阶段的功能(展讯为16k的汇编代码)
硬件设备初始化
加载U-Boot第二阶段代码到RAM空间
设置好栈
跳转到第二阶段代码入口
StageII:第二阶段的功能
初始化本阶段使用的硬件设备 检测系统内存映射 将内核从Flash读取到RAM中 为内核设置启动参数 调用内核1.1.1 U-Boot启动第一阶段代码分析
第一阶段对应的文件是lowlevel_init.S。 U-Boot启动第一阶段流程如下: 1. 硬件设备初始化 (1)设置异常向量 其中复位异常向量的指令“b start_code”决定了U-Boot启动后将自动跳转到标号“start_code”处执行。 (2)设置控制寄存器地址 (3)关闭看门狗 (4)关闭MMU,cache (5)初始化RAM控制寄存器 其中的lowlevel_init就完成了内存初始化的工作,由于内存初始化是依赖于开发板的,因此lowlevel_init的代码一般放在board下面相应的目录中。
board/samsung/mini2440/lowlevel_init.o将被链接到cpu/arm920t/start.o后面,因此board/samsung/mini2440/lowlevel_init.o也在U-Boot的前4KB的代码中。 U-Boot在NAND Flash启动时,lowlevel_init.o将自动被读取到CPU内部4KB的内部RAM中。因此第137~146行的代码将从CPU内部RAM中复制寄存器的值到相应的寄存器中。 对于U-Boot在NOR Flash启动的情况,由于U-Boot连接时确定的地址是U-Boot在内存中的地址,而此时U-Boot还在NOR Flash中,因此还需要在NOR Flash中读取数据到RAM中。 由于NOR Flash的开始地址是0,而U-Boot的加载到内存的起始地址是TEXT_BASE,SMRDATA标号在Flash的地址就是SMRDATA-TEXT_BASE。 综上所述,lowlevel_init的作用就是将SMRDATA开始的13个值复制给开始地址[BWSCON]的13个寄存器,从而完成了存储控制器的设置。 (6)复制U-Boot第二阶段代码到RAM cpu/arm920t/start.S原来的代码是只支持从NOR Flash启动的,经过修改现在U-Boot在NOR Flash和NAND Flash上都能启动了,实现的思路是这样的: bl bBootFrmNORFlash /* 判断U-Boot是在NAND Flash还是NOR Flash启动 */ cmp r0, #0 /* r0存放bBootFrmNORFlash函数返回值,若返回0表示NAND Flash启动,否则表示在NOR Flash启动 */ beq nand_boot /* 跳转到NAND Flash启动代码 */ /* NOR Flash启动的代码 */ b stack_setup /* 跳过NAND Flash启动的代码 */ nand_boot: /* NAND Flash启动的代码 */ stack_setup: /* 其他代码 */ 其中bBootFrmNORFlash函数作用是判断U-Boot是在NAND Flash启动还是NOR Flash启动,若在NOR Flash启动则返回1,否则返回0。根据ATPCS规则,函数返回值会被存放在r0寄存器中。 bBootFrmNORFlash函数后根据r0的值就可以判断U-Boot在NAND Flash启动还是NOR Flash启动。bBootFrmNORFlash函数在board/samsung/mini2440/nand_read.c中定义如下:
int bBootFrmNORFlash(void) { volatile unsigned int *pdw = (volatile unsigned int *)0; unsigned int dwVal; dwVal = *pdw; /* 先记录下原来的数据 */ *pdw = 0x12345678; if (*pdw !