2.第二阶段代码分析(代码在lib_arm目录下的board.c里面,start_armboot函数)
1)初始化CPU及外围硬件
voidstart_armboot (void)
{
init_fnc_t **init_fnc_ptr;
char *s;
#ifdefined(CONFIG_VFD) || defined(CONFIG_LCD)
unsigned long addr;
#endif
/* Pointer is writable since we allocateda register for it */
gd = (gd_t*)(_armboot_start -CONFIG_SYS_MALLOC_LEN - sizeof(gd_t));
/* compiler optimization barrier neededfor GCC >= 3.4 */
__asm__ __volatile__("": ::"memory");
memset ((void*)gd, 0, sizeof (gd_t));
gd->bd = (bd_t*)((char*)gd -sizeof(bd_t));
memset (gd->bd, 0, sizeof (bd_t));
gd->flags |= GD_FLG_RELOC;
monitor_flash_len = _bss_start -_armboot_start;
for (init_fnc_ptr = init_sequence;*init_fnc_ptr; ++init_fnc_ptr) {
if((*init_fnc_ptr)() != 0) {
hang ();
}
}
解释:定义二级指针init_fnc_ptr指向一个存放函数指针的数组,init_fnc_ptr是typedef int (init_fnc_t) (void)类型,即函数类型,init_fnc_ptr可以指向一个没有参数,返回值为int型的函数指针的地址,我们看上面代码最后的for循环init_fnc_ptr = init_sequence,if中会使用(*init_fnc_ptr)()方式调用init_sequence中的函数(函数名可以看为一个地址),如果返回值不是0,则执行hang报错。gd = (gd_t*)(_armboot_start -CONFIG_SYS_MALLOC_LEN - sizeof(gd_t)); 我们知道,malloc区域、stack区域、bdinfo数据、gd_t在内存的位置是放在upper of uboot。__asm__ __volatile__("":: :"memory");这条是内嵌汇编,请查看另一篇介绍内嵌汇编的博文。
gd->bd指针指向数据类型为bd_t的结构体,bd_t结构体记录开发板的参数,例如串口波特率、ip地址、机器类型、启动参数、环境变量位置等。
monitor_flash_len= _bss_start - _armboot_start; bss段是u-boot最后一个段,bss最终需要清零,这时候不再需要搬移,可以参考链接脚本u-boot.lds。
下面分析for循环执行的函数:
#ifdefined(CONFIG_ARCH_CPU_INIT)
arch_cpu_init, /* basic arch cpudependent setup */
#endif
这里我们定义了CONFIG_ARCH_CPU_INIT,所以执行函数arch_cpu_init。跳到这里,又有一个宏,CONFIG_ARCH_CPU_INIT,这个宏也是定义了的,所以可以继续看,
board_init:
30,31行一个是记录机器类型,一个是指定向内核传参的地址。
继续分析,宏CONFIG_USE_IRQ),函数interrupt_init不执行
init_baudrate:
139行使用getenv_r函数在default_environment里找baudrate关键字,找到后把“=”号后面的值赋值给gd->baudrate,然后
再放到gd->bd->bi_baudrate里面。simple_strtoul是uboot实现的字符串转UL类型。
serial_init:什么都没做,保持默认的8位数据、无奇偶校验、1 停止位、无开始位。
console_init_f:gd->have_console = 1就这一句话
display_banner:串口打印uboot信息,就是uboot启动的时候我们看到的信息,这里使用的是printf,但是我们追进去后,关注的函数
应该是serial_putc,它是真实向串口输出一个字符的函数,这个函数会递归调用,应该说自己调用自己,遇到\n结束。
print_cpuinfo:打印CPU信息,CPU型号和速度 CPU:...
checkboard:打印开发板信息 BOARD:...
dram_init:
记录dram的起始地址,0x30000000,size为256M(smdkc100的)
display_dram_config:因为没有定义DEBUG,所以打印DRAM:256M
2)配置malloc空间
这个函数的作用是记录堆栈空间的起始地址、结束地址、当前地址。
4)环境变量初始化
5)网络初始化
6)设备列表初始化
7)配置功能函数表
8)终端完全初始化
9)开中断异常向量表
10)网卡芯片初始化
11)一些后续初始化
12)main_loop详解
等有时间,会针对这些问题在新的文章中深入浅出说明上述问题