系统大全为您提供
本文将使用sama5d3xekSPL实现做为例子 u-bootSPL(secondprogramloader),对许多人来说也说很陌生。下面对此进行一个简单介绍。 1.armSoC的启动过程: RomBoot-->SPL-->u-boot-->Linuxkernel-->filesystem-->startapplication (RomBoot是固化在SoC内部的。) u-boot实现了一个新功能,能在编译u-boot的同时生成SPL二进制文件。 2.SPL运行代码gothrough 从u-boot-spl.lds链接文件可知,启动代码也是start.S. (reset)<arch/arm

u/armv7/start.S>(blowlevel_init:arch/arm

u/armv7/lowlevel_init.S)(b_main)--><arch/arm

b/crt0.S>(blboard_init_f)--><arch/arm

b/spl.c>(board_init_r)--><common/spl/spl.c>(jump_to_image_no_args去启动u-boot)到此SPL的生命周期结束。 简单来讲:SPL所做工作,一些硬件的初始化,然后读取u-boot,最后调转至u-boot. 3.下面具体分析SPL的相关代码。 <arch/arm

u/armv7/start.S> 110reset: 111blsave_boot_params 112/* 113*disableinterrupts(FIQandIRQ),alsosetthecputoSVC32mode, 114*exceptifinHYPmodealready 115*/ 116mrsr0,cpsr 117andr1,r0,#0x1f@maskmodebits 118teqr1,#0x1a@testforHYPmode 119bicner0,r0,#0x1f@clearallmodebits 120orrner0,r0,#0x13@setSVCmode 121orrr0,r0,#0xc0@disableFIQandIRQ 122msrcpsr,r0 123 124/* 125*Setupvector: 126*(OMAP4splTEXT_BASEisnot32bytealigned. 127*ContinuetouseROMcodevectoronlyinOMAP4spl) 128*/ 129#if!(defined(CONFIG_OMAP44XX)&&defined(CONFIG_SPL_BUILD)) 130/*SetV=0inCP15SCTRLregister-forVBARtopointtovector*/ 131mrcp15,0,r0,c1,c0,0@ReadCP15SCTRLRegister 132bicr0,#CR_V@V=0 133mcrp15,0,r0,c1,c0,0@WriteCP15SCTRLRegister 134 135/*SetvectoraddressinCP15VBARregister*/ 136ldrr0,=_start 137mcrp15,0,r0,c12,c0,0@SetVBAR 138#endif 139 140/*themaskROMcodeshouldhavePLLandothersstable*/ 141#ifndefCONFIG_SKIP_LOWLEVEL_INIT 142blcpu_init_cp15 143blcpu_init_crit 144#endif 145 146bl_main 111:如果没有重新定义save_boot_params,则使用<arch/arm

u/armv7/start.S>中的save_boot_params.其不做任何事情,直接返回。 116~138:看注释即可明白。 141:因为SPL主要是对SoC进行初始化,所以不会定义CONFIG_SKIP_LOWLEVE_INIT,即142,143行得以执行。 142:cpu_init_cpu15,主要作用invalidateL1I/Dcache,disableMMU.检查是否需要workaround. 143:cpu_init_crit直接跳转到lowlevel_init 下面看看lowlevel_init的实现: <arch/arm

u/armv7/lowlevel_init.S> 18ENTRY(lowlevel_init) 19/* 20*Setupatemporarystack 21*/ 22ldrsp,=CONFIG_SYS_INIT_SP_ADDR 23bicsp,sp,#7/*8-bytealignmentforABIcompliance*/ 24#ifdefCONFIG_SPL_BUILD 25ldrr9,=gdata 26#else 27subsp,#GD_SIZE 28bicsp,sp,#7 29movr9,sp 30#endif 31/* 32*Savetheoldlr(passedinip)andthecurrentlrtostack 33*/ 34push{ip,lr} 35 36/* 37*gosetuppll,mux,memory 38*/ 39bls_init 40pop{ip,pc} 41ENDPROC(lowlevel_init) 22:对stackpointer赋值成CONFIG_SYS_INIT_SP_ADDR 23:确保sp是8字节对齐。 25:将gdata的地址存入到r9寄存器中。 39:跳转到s_init.对Atmelsama5d3xekboard,s_init定义在:<arch/arm

u/at91-common/spl.c>此处暂时不分析。 然后返回到start.S处,接下来调用:bl_main到<arch/arm

b/crt0.S> 58ENTRY(_main) 59 60/* 61*SetupinitialCruntimeenvironmentandcallboard_init_f(0)。 62*/ 63 64#ifdefined(CONFIG_SPL_BUILD)&&defined(CONFIG_SPL_STACK) 65ldrsp,=(CONFIG_SPL_STACK) 66#else 67ldrsp,=(CONFIG_SYS_INIT_SP_ADDR)
68#endif
70subsp,#GD_SIZE/*allocateoneGDaboveSP*/ 71bicsp,sp,#7/*8-bytealignmentforABIcompliance*/ 72movr9,sp/*GDisaboveSP*/ 73movr0,#0 74blboard_init_f 65:重新对SP赋值 69:确认sp是8字对齐 70:相当于保留一个global_data的大小。 71:确认更新后的sp是8字对齐 72:r9指向global_data 73:r0赋值0 74:跳转到board_init_f中运行。 board_init_f在<arch/arm

b/spl.c>定义: 20/* 21*InthecontextofSPL,board_init_fmustensurethatanyclocks/etcfor 22*DDRareenabled,ensurethatthestackpointerisvalid,cleartheBSS 23*andcallboard_init_f.Weprovidethisversionbydefaultbutmarkit 24*as__weaktoallowforplatformstodothisintheirownwayifneeded. 25*/ 26void__weakboard_init_f(ulongdummy) 27{ 28/*CleartheBSS.*/ 29memset(__bss_start,0,__bss_end-__bss_start); 30 31/*Setglobaldatapointer.*/ 32gd=&gdata; 33 34board_init_r(NULL,0); 35} 26:board_init_f是一个弱函数,是可以被重新定义的。 29:对BSS段进行清零操作。 34:跳转到board_init_r board_init_r在<common/spl/spl.c>中定义: 132voidboard_init_r(gd_t*dummy1,ulongdummy2) 133{ 134u32boot_device; 135debug("》spl:board_init_r()"); 136 137#ifdefCONFIG_SYS_SPL_MALLOC_START 138mem_malloc_init(CONFIG_SYS_SPL_MALLOC_START, 139CONFIG_SYS_SPL_MALLOC_SIZE); 140#endif 141 142#ifndefCONFIG_PPC 143/* 144*timer_init()doesnotexistonPPCsystems.Thetimerisinitialized 145*andenabled(decrementer)ininterrupt_init()here. 146*/ 147timer_init(); 148#endif 149 150#ifdefCONFIG_SPL_BOARD_INIT 151spl_board_init(); 152#endif 135:输出debug信息:》spl:board_init_r(); 137~140:如果定义了:CONFIG_SYS_SPL_MALLOC_START,则进行memory的malloc池初始化。以后调用malloc就在这个池子里面分配内存。142~148:如果没有定义:CONFIG_PPC,则进行timer的初始化:timer_init()<arm/arm

u/armv7/at91/time.c> 150~150:CONFIG_SPL_BOARD_INIT,则调用spl_board_init()。这是board相关的定义,<board/atmel

ma5d3xek

ma5d3xek.c> 一切就绪后,就要检查从什么设备来启动了。这里就贴出RAM,MMC,NAND相关代码 154boot_device=spl_boot_device(); 155debug("bootdevice-%d",boot_device); 156switch(boot_device){ 157#ifdefCONFIG_SPL_RAM_DEVICE 158caseBOOT_DEVICE_RAM: 159spl_ram_load_image(); 160break; 161#endif 162#ifdefCONFIG_SPL_MMC_SUPPORT 163caseBOOT_DEVICE_MMC1: 164caseBOOT_DEVICE_MMC2: 165caseBOOT_DEVICE_MMC2_2: 166spl_mmc_load_image(); 167break; 168#endif 169#ifdefCONFIG_SPL_NAND_SUPPORT 170caseBOOT_DEVICE_NAND: 171spl_nand_load_image(); 172break; 173#endif 154:获取spl_boot_device,即从什么设备启动。 157~161:如果定义了CONFIG_SPL_RAM_DEVICE,则执行spl_ram_load_image(),其就是将image下载到ram中。 162~168:如果定义了CONFIG_SPL_MMC_SUPPORT,则执行spl_mmc_load_image(),其就是将image从mmc/sd里面读取到ram中。 169~173:如果定义了CONFIG_SPL_NAND_SUPPORT,则执行spl_nand_load_image(),其就是将image从nandflash中读取到ram中。 当要启动的image位于RAM中后,我们就可以启动之。 213switch(spl_image.os){ 214caseIH_OS_U_BOOT: 215debug("JumpingtoU-Boot"); 216break; 217#ifdefCONFIG_SPL_OS_BOOT 218caseIH_OS_LINUX: 219debug("JumpingtoLinux"); 220spl_board_prepare_for_linux(); 221jump_to_image_linux((void*)CONFIG_SYS_SPL_ARGS_ADDR); 222#endif 223default: 224debug("UnsupportedOSimageJumpingnevertheless"); 225} 226jump_to_image_no_args(&spl_image); 227}
213:判断image的类型。
214:如果是u-boot,则直接到227去运行u-boot. 218:如果是Linux,则到221去启动Linux.
至此,SPL结束它的生命,控制权交于u-boot或Linux.
以上就是系统大全给大家介绍的如何使的方法都有一定的了解了吧,好了,如果大家还想了解更多的资讯,那就赶紧点击系统大全官网吧。
本文来自系统大全http://www.win7cn.com/如需转载请注明!推荐:win7纯净版