实验板子:飞凌FET335xD
uboot版本:2011.09
linux内核版本:linux3.2
cpu:Ti的3354
操作系统:linux3.2
文件系统:ubi
理清 uboot 是如何启动的。通过对 uboot 启动流程的梳理,我们就可以掌握一些外设是在哪里被初始化的,这样当我们需要修改这些外设驱动的时候就会心里有数
以335xd所使用的uboot为例,使用的uboot版本为2011-09
从./ok335x/u-boot.lds可以知道,程序入口为_start
入口函数_start定义的文件路径为:./arch/arm/cpu/armv7/start.S
_start函数第一步是reset复位,之后会初始化异常向量表
而reset会依次执行下面的函数
save_boot_params 设置cpuSVC32模式
save_boot_params函数位于arch/arm/cpu/armv7/ti81xx/lowlevel_init.S
之后又返回reset,跳转到cpy_clk_code,将时钟代码重定位到SRAM中
之后又跳转到cpu_init_crit中,cpu_init_crit就位于start.S中,主要设置重要寄存器,设置内存时序
lowlevel_init 跳转到这里后,平台低级初始化
lowlevel_init函数位于arch/arm/cpu/armv7/ti81xx/lowlevel_init.S
lowlevel_init函数最后会调用s_init_start
而s_init_start会调用s_init函数,该函数作用是初始化复用和时钟
位于board/forlinx/ok335x/evm.c
reset最后跳转到board_init_f
board_init_f函数位于./arch/arm/lib/board.c
board_init_f 函数主要有两个工作:
初始化一系列外设,比如串口、定时器,或者打印一些消息等。
初始化 gd 的各个成员变量, uboot 会将自己重定位到 DRAM 最后面的地址区域,也就是将自己拷贝到 DRAM 最后面的内存区域中
在board_init_f的最后中调用relocate_code
relocate_code 位于./arch/arm/cpu/armv7/start.S,该函数完成把代码段重定位到内存
可以看到relocate_code最后调用了board_init_r
board_init_f此函数里面会调用一系列的函数来初始化一些外设和 gd 的成员变量。但是 board_init_f 并没有初始化所有的外设,还需要做一些后续工作,这些后续工作就是由函数 board_init_r 来完成的
下面重点介绍board_init_r函数
board_init_r函数位于./arch/arm/lib/board.c
这是void board_init_r(gd_t *id, ulong dest_addr)函数的介绍
这是初始化序列的下一部分:我们现在从RAM运行,有一个“正常”的C环境,即全局数据可以被写入,Bss已经被清除,堆栈大小不再是关键的,等等。
335x的board_init_r调用下面的函数
enable_caches();
board_init();
serial_initialize();
logbuff_init_ptrs();
post_output_backlog();
mem_malloc_init (malloc_start, TOTAL_MALLOC_LEN);
flash_init();
nand_init();
onenand_init();
mmc_initialize(bd);
AT91F_DataflashInit();
dataflash_print_info();
env_relocate();
am335_usr_pinmux();
arm_pci_init();
stdio_init();
jumptable_init();
api_init();
console_init_r();
arch_misc_init();
misc_init_r();
interrupt_init();
enable_interrupts();
board_late_init();
bb_miiphy_init();
eth_initialize(gd->bd);
reset_phy();
post_run(NULL, POST_RAM | post_bootmode_get(0));
main_loop();
下面简单说说board_init_r阶段所调用的函数以及其作用
enable_caches(); //使能caches
board_init(); 设置引脚复用
board_init()位于board/forlinx/ok335x/evm.c,该文件就是平时我们在uboot阶段要修改gpio,修改引脚复用,335x系列的gpmc总线的初始化也加到了这里
serial_initialize(); 初始化串口
mem_malloc_init (malloc_start, TOTAL_MALLOC_LEN); 初始化初始化malloc
nand_init(); 初始化nand
onenand_init();
mmc_initialize(bd); 初始化mmc,335x没有emmc,根据宏来判断是否执行
env_relocate(); 初始化环境
am335_usr_pinmux(); 自定义的函数,实际上没执行到,估计是调试时添加
arm_pci_init();
stdio_init(); 进行 stdio 相关初始化
jumptable_init(); 初始化跳转表
api_init();
console_init_r(); 控制台初始化
arch_misc_init(); 杂项依赖环境初始化
misc_init_r(); 杂项依赖平台初始化
interrupt_init(); 初始化中断
enable_interrupts(); /使能中断
board_late_init(); 完成一些环境变量的设置
bb_miiphy_init();
eth_initialize(gd->bd); 初始化网络外部的 phy 芯片的初始化
reset_phy(); 复位phy芯片
post_run(NULL, POST_RAM | post_bootmode_get(0));
main_loop(); 主循环,处理交互命令,uboot倒计时3s由改函数完成



