一、背景知识
1、uboot第二阶段应该做什么?
- 概括来讲uboot第一阶段主要就是初始化了SoC内部的一些部件(譬如看门狗、时钟),然后初始化DDR并且完成重定位。
- 由宏观分析来讲,uboot的第二阶段就是要初始化剩下的还没被初始化的硬件。主要是SoC外部硬件(譬如iNand、网卡芯片····)、uboot本身的一些东西(uboot的命令、环境变量等····)。然后最终初始化完必要的东西后进入uboot的命令行准备接受命令。
2、uboot中经常出现一种情况就是根据一个宏是否定义了来条件编译决定是否调用一个函数内部的代码。uboot中有2种解决方案来处理这种情况:方案一:在调用函数处使用条件编译,然后函数体实际完全提供代码。方案二:在调用函数处直接调用,然后在函数体处提供2个函数体,一个是有实体的一个是空壳子,用宏定义条件编译来决定实际编译时编译哪个函数进去。
二、函数执行流程
1、定义变量,gd,然后实例化
2、给gd->bd赋值,内存间隔 为了防止高版本的gcc的优化造成错误
3、执行init_sequence函数,都是board级别的各种硬件初始化
- cpu_init():cpu内部的初始化,但在start.S初始化过,所以这里是空的。
- board_init():网卡的GPIO和端口的配置、定义开发板的机器码、定义uboot给linux kernel启动时的传参的内存地址gd->bd->bi_boot_params=0x30000100
注意:board_init中除了网卡的初始化之外,剩下的2行用来初始化DDR。这里的初始化DDR和汇编阶段lowlevel_init中初始化DDR是不同的。当时是硬件的初始化,目的是让DDR可以开始工作。现在是软件结构中一些DDR相关的属性配置、地址设置的初始化,是纯软件层面的。
- interrupt_init():初始化定时器,将timer4设置为定时10ms
- env_init():环境变量有关的初始化
注:这个函数只是对内存里维护的那一份uboot的env做了基本的初始化或者说是判定(判定里面有没有能用的环境变量)。当前因为我们还没进行环境变量从SD卡到DDR中的relocate,因此当前环境变量是不能用的。
- init_baudrate():初始化串口通信的波特率的
- serial_init():初始化串口的,其实什么都没做
- console_init_f():事情都没做
注:f表示是第一阶段初始化,_r表示第二阶段初始化
- display_banner():用来串口输出显示uboot的logo
- print_cpuinfo():输出CPU的一些信息,比如:时钟频率
- checkboard():检查当前开发板是哪个开发板并且打印出开发板的名字。
- dram_init():关于DDR软件的初始化,关于DDR配置部分的全局变量赋值
- display_dram_config():打印显示dram的配置信息
4、NorFlash的初始化,打印的也是NorFlash的配置信息(491-492)[和此开发板无关]
5、初始化uboot的堆管理器,DDR内存中给堆预留了896KB的内存
6、开发板独有初始化:mmc初始化;初始化SoC内部的SD/MMC控制器的
7、环境变量的重定位,完成从SD卡中将环境变量读取到DDR中的任务。
8、IP地址、MAC地址的确定
9、开发板上的硬件设备(818)
10、跳转表,通过函数指针就可以执行具体的函数
11、console的纯软件架构方面的初始化,去给console相关的数据结构中填充相应的值
12、使能CPSR中总中断标志位
13、loadaddr、bootfile这两个环境变量都是内核启动有关的
14、网卡相关的初始化(于X210(DM9000)来说,这个函数是空的)
15、x210开发板在启动起来之前的一些初始化,以及LCD屏幕上的logo显示(887)
16、自动更新的功能
- 我们可以将要升级的镜像放到SD卡的固定目录中,然后开机时在uboot启动的最后阶段检查升级标志(是一个按键。按键中标志为"LEFT"的那个按键,这个按键如果按下则表示update mode,如果启动时未按下则表示boot mode)。如果进入update mode则uboot会自动从SD卡中读取镜像文件然后烧录到iNand中;如果进入boot mode则uboot不执行update,直接启动正常运行。
三、总结
(1)第一阶段为汇编阶段、第二阶段为C阶段
(2)第一阶段在SRAM中、第二阶段在DRAM中
(3)第一阶段注重SoC内部、第二阶段注重SoC外部Board内部