u_boot初始化流程

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

U-Boot启动代码分析

U-boot的启动顺序分为stage1和stage2两部分,见下图。依赖于CPU体系结构的代码(如设备初始化代码等)通常放在stage1中用汇编语言实现,而在stage2则通常由C语言实现,这样可以实现复杂的功能,而且有更好的可读性和移植性。以下主要梳理了stage2阶段函数的调用顺序以及每个函数的功能。

U-boot的启动顺序

C语言代码部分lib_arm/board.c中的start_armboot既是C语言开始的函数也是整个启动代码中C语言的主函数,同时还是整个U-boot的主函数,该函数只要完成如下操作。

(1)调用一系列的初始化函数。

(2)初始化Flash设备。

(3)初始化系统内存分配函数

(4)如果目标系统拥有NAND设备,则初始化NAND设备

(5)如果目标系统有显示设备,则初始化该类设备。

(6)初始化相关网络设备,填写IP、MAC地址等。

(7)进入命令循环(即整个Boot的工作循环),接收用户从串口输入的命令,然后进行相应的工作。

下面结合源码分析函数调用顺序以及函功能:

代码:

void start_armboot (void)

{

init_fnc_t **init_fnc_ptr;

char *s;

int mmc_exist = 0;

#if defined(CONFIG_VFD) || defined(CONFIG_LCD)

unsigned long addr;

#endif

注释:从U-boot stage1中start.s程序调到这里执行start_armboot函数,这一段代码进行了变量声明,其中定义了一个名为init_fnc_ptr的双重指针。如果CONFIG_VFD或者CONFIG_LCD被定义了则声明一无符号长整型变量addr,本开发板中没有定义无需声明addr。

代码:

/* Pointer is writable since we allocated a register for it */

gd = (gd_t*)(_armboot_start - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t));

/* compiler optimization barrier needed for GCC >= 3.4 */

__asm__ __volatile__("": : :"memory"); //内存屏障,告诉编译器内存被修改过了

memset ((void*)gd, 0, sizeof (gd_t));

gd->bd = (bd_t*)((char*)gd - sizeof(bd_t)); //指向gd之前

memset (gd->bd, 0, sizeof (bd_t));

// gd->flags |= GD_FLG_RELOC;

monitor_flash_len = _bss_start - _armboot_start; //u-boot映像的大小其中_armboot_start为code start ,_bss_start为code + data end == BSS start.

注释:

gd = (gd_t*)(_armboot_start - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t));//内存强制转换,gd为全局环境变量,gd指向uboot之前的地址;

memset ():void * memset(void * s,char c,size_t count)将指针s所指地址以及之后count个地址中数值赋值为c。memset ((void*)gd, 0, sizeof (gd_t))的作用为:gd整个地址的值初始化为0;memset (gd->bd, 0, sizeof (bd_t))的作用为bd地址的值初始化为0。

代码:

for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {

if ((*init_fnc_ptr)() != 0) { //相当于调用指针中的一个函数,如果不为0就表示死机

hang ();

}

}

注释:

将init_squence数组送给init_fnc_ptr,利用循环调用init_squence数组中的多个初始化函数,包括初始化CPU、board、中断、时钟、NOR Flash、NAND Flash等,后面根据代码进行分析。初始化完成之后进入hang()处于死循环即完成U-boot使命。

init_sequence[ ]数组保存基本的初始化函数指针,在board.c中对数组进行了定义:

#if defined(CONFIG_ARCH_CPU_INIT)

arch_cpu_init, /* basic arch cpu dependent setup */

#endif

board_init, /* basic board dependent setup */

//#if defined(CONFIG_USE_IRQ)

interrupt_init, /* set up exceptions */

//#endif

//timer_init, /* initialize timer */

#ifdef CONFIG_FSL_ESDHC

//get_clocks,

#endif

env_init,/* initialize environment */

init_baudrate,/* initialze baudrate settings */

serial_init,/* serial communications setup */

console_init_f,/* stage 1 init of console */

off_charge,// xiebin.wang @ 20110531,for charger&power off device.

display_banner,/* say that we are here */

#if defined(CONFIG_DISPLAY_CPUINFO)

print_cpuinfo,/* display cpu info (and speed) */

#endif

#if defined(CONFIG_DISPLAY_BOARDINFO)

checkboard,/* display board info */

#endif

#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)

//init_func_i2c,

#endif

dram_init, /* configure available RAM banks */

#if defined(CONFIG_CMD_PCI) || defined (CONFIG_PCI)

//arm_pci_init,

#endif

display_dram_config,

NULL,

};

注释:

下面按照顺序依次分析各个初始化函数作用(绿色代码是被注释掉的并不执行):

arch_cpu_init():基本处理器相关配置。如果定义了CONFIG_ARCH_CPU_INIT则执行此函数,本开发板在include/configs/smdkc100.h中定义了此变量。

最终在串口打印:

CPU: SMDK4412-AP1.1 [e4412211]

相关文档
最新文档