u_boot初始化流程

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

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的工作循环),接收用户从串口输入的命令,然后进行相应的工作。下面结合源码分析函数调用顺序以及函功能:代码:voidstart_armboot(void){init_fnc_t**init_fnc_ptr;char*s;intmmc_exist=0;#ifdefined(CONFIG_VFD)||defined(CONFIG_LCD)unsignedlongaddr;#endif注释:从U-bootstage1中start.s程序调到这里执行start_armboot函数,这一段代码进行了变量声明,其中定义了一个名为init_fnc_ptr的双重指针。如果CONFIG_VFD或者CONFIG_LCD被定义了则声明一无符号长整型变量addr,本开发板中没有定义无需声明addr。代码:/*Pointeriswritablesinceweallocatedaregisterforit*/gd=(gd_t*)(_armboot_start-CONFIG_SYS_MALLOC_LEN-sizeof(gd_t));/*compileroptimizationbarrierneededforGCC=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为codestart,_bss_start为code+dataend==BSSstart.注释:gd=(gd_t*)(_armboot_start-CONFIG_SYS_MALLOC_LEN-sizeof(gd_t));//内存强制转换,gd为全局环境变量,gd指向uboot之前的地址;memset():void*memset(void*s,charc,size_tcount)将指针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、中断、时钟、NORFlash、NANDFlash等,后面根据代码进行分析。初始化完成之后进入hang()处于死循环即完成U-boot使命。init_sequence[]数组保存基本的初始化函数指针,在board.c中对数组进行了定义:#ifdefined(CONFIG_ARCH_CPU_INIT)arch_cpu_init,/*basicarchcpudependentsetup*/#endifboard_init,/*basicboarddependentsetup*///#ifdefined(CONFIG_USE_IRQ)interrupt_init,/*setupexceptions*///#endif//timer_init,/*initializetimer*/#ifdefCONFIG_FSL_ESDHC//get_clocks,#endifenv_init,/*initializeenvironment*/init_baudrate,/*initialzebaudratesettings*/serial_init,/*serialcommunicationssetup*/console_init_f,/*stage1initofconsole*/off_charge,//xiebin.wang@20110531,forcharger&poweroffdevice.display_banner,/*saythatwearehere*/#ifdefined(CONFIG_DISPLAY_CPUINFO)print_cpuinfo,/*displaycpuinfo(andspeed)*/#endif#ifdefined(CONFIG_DISPLAY_BOARDINFO)checkboard,/*displayboardinfo*/#endif#ifdefined(CONFIG_HARD_I2C)||defined(CONFIG_SOFT_I2C)//init_func_i2c,#endifdram_init,/*configureavailableRAMbanks*/#ifdefined(CONFIG_CMD_PCI)||defined(CONFIG_PCI)//arm_pci_init,#endifdisplay_dram_config,NULL,};注释:下面按照顺序依次分析各个初始化函数作用(绿色代码是被注释掉的并不执行):arch_cpu_init():基本处理器相关配置。如果定义了CONFIG_ARCH_CPU_INIT则执行此函数,本开发板在include/configs/smdkc100.h中定义了此变量。最终在串口打印:CPU:SMDK4412-AP1.1[e4412211]APLL=1000MHz,MPLL=800MHzARM_CLOCK=1000MHzboard_init():基本的板级相关配置,设置了一些寄存器,如时钟,IO口,串口,机器类型,启动参数,指令cache,数据cache.env_init():初始化环境变量,这个函数主要是在gd里保存环境变量的存放地址。一般使用默认的环境变量值即default_environment数组。init_baudrate():初始化波特率设置,调用getenv_r()函数来获取环境变量,从上面刚初始化好的环境变量列表里找波特率值,如果没有就赋初始值为CONFIG_BAUDRATE,一般在board.c中定义函数。serial_init():串口通信设置,在cpu/Arm-cortexa9的serial.c中定义了该函数。console_init_f():控制台初始化阶段,初始化了几个控制台相关的标记。在common/Console.c中定义。off_charge():管理和关闭设备。display_banner():打印U-boot信息,包括了一些显示函数,在board.c中定义了该函数。print_cpuinfo():打印cpu信息,如果定义了CONFIG_DISPLAY_CPUINFO,则执行该函数,本开发板定义了此变量。checkboard():如果定义了CONFIG_DISPLAY_BOARDINFO,则执行函数。dram_init():配置可用的RAMdisplay_dram_config():显示RAM的配置,打印出DRAM的大小,在board.c中定义了该函数。代码:/*armboot_startisdefinedintheboard-specificlinkerscript*/mem_malloc_init(_armboot_start-CONFIG_SYS_MALLOC_LEN,CONFIG_SYS_MALLOC_LEN);#ifndefCONFIG_SYS_NO_FLASH/*configureavailableFLASHbanks*/display_flash_config(flash_init());注释:mem_malloc_init():初始化堆空间,malloc使用的内存空间地址。在common/Dlmalloc.c中定义了该函数。flash_init():记录下flash的大小,数量,sector的大小数量等,并对flash上重要的数据进行保护。display_flash_config():通过调用flash_init()来打印flash的大小信息,在board.c中定义了该函数。代码:#ifdefCONFIG_VFD#ifndefPAGE_SIZE#definePAGE_SIZE4096#endif/**reservememoryforVFDdisplay(alwaysfullpages)*//*bss_endisdefinedintheboard-specificlinkerscript*/addr=(_bss_end+(PAGE_SIZE-1))&~(PAGE_SIZE-1);vfd_setmem(addr);gd-fb_base=addr;#endif/*CONFIG_VFD注释:如果CONFIG_VFD被定义PAGE_SIZE没有被定义,则定义PAGE_SIZE为4096,为VFD保存内存空间,以页为单位。vfd_setmem(addr):计算VFD内存大小。代码:#ifdefCONFIG_LCD/*boardinitmayhaveinitedfb_base*/if(!gd-fb_base){#ifndefPAGE_SIZE#definePAGE_SIZE4096#endif/**reservememoryforLCDdisplay(alwaysfullpages)*//*bss_endisdefinedintheboard-specificlinkerscript*/addr=(_bss_end+(PAGE_SIZE-1))&~(PAGE_SIZE-1);lcd_setmem(addr);gd-fb_base=addr;}#endif/*CONFIG_LCD*/注释:如果定义了CONFIG_LCD,则执行这段代码。为LCD保存内存空间。lcd_setmem(addr):计算LCD内存大小。代码:#ifdefined(CONFIG_CMD_NAND)puts(NAND:);、nand_init();/*goinittheNAND*/#endif注释:如果定义了CONFIG_CMD_NAND,则执行该段代码。这一段代码实现:打印NAND1024MB。nand_init():NANDFlash初始化,在drivers/mtd/nand/nand.c中定义了该函数。代码:#ifdefined(CONFIG_CMD_ONENAND)onenand_init();#endif注释:如果定义了CONFIG_CMD_ONENAND,则执行该段代码,本开发板中定义了此变量。onenand_init():

1 / 10
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功