您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 项目/工程管理 > u-boot启动过程(基于S3C2410)和uImagezImage启动分析
本文以流行的Samsung公司的S3C2410,openmoko平台和u-boot-1.3.2(2008.5发布)为例,介绍如何在ZIX嵌入式开发环境下探索u-boot启动过程。虽然u-boot已经广泛应用,由于其相对的复杂性使用户在了解其内部机理和进行u-boot的移植工作时还是会碰到困难。u-boot已有一些分析文档,但多数和真正的代码不能同步或者版本老旧,难以将概念和现实的代码匹配——即硬件板上跑的代码在文档资料中却看不到,更无法紧密的跟踪。本文涉及的代码基于在s3c2410硬件运行的成熟u-boot-1.3.2代码,版本较新,提供的特性非常丰富,而且在forum.linuxbj.com可以自由浏览和下载。此u-boot代表了业界的较高水平,可以直接构建新版的嵌入式产品设计,有较高的应用价值。u-boot总的启动流程如下-reset-设置CPU模式-关闭看门狗/中断-设置处理器时钟/片上总线-初始化调试串口-MMU/外部总线/SDRAM等初始化-rom代码/数据搬移到ram-初始化函数调用栈-初始化外围设备/参数-启动完毕,进入main_loop循环嵌入式系统离不开bootloader初始化硬件以及引导操作系统。现在,专用的嵌入式板子运行嵌入式Linux系统已经变得非常流行,u-boot是一种非常适合此类系统的bootloader。u-boot主要提供以下功能:设置目标板硬件参数并初始化;为操作系统传递必要信息;执行交互式的底层操作;智能化装载操作系统;引导和运行的固件程序;支持大容量存储和USB接口利用ZIX开发环境,能够通过比较直观的方式观察u-boot内部,而且可以将代码调试和分析同时进行,是一种了解、移植u-boot的强大工具。使用arm工具链编译u-boot源代码,得到可以烧录的u-boot.bin文件。在ZIX开发环境里,可以将u-boot.bin载入s3c2410板运行,并利用gdb调试。gdb能通过JTAG接口访问硬件,也可以通过TCP/IP访问虚拟硬件。建立好调试连接,即可通过gdb操纵u-boot启动过程,下面可以跟随代码的执行顺序,了解从上点开始,究竟哪些操作被执行。s3c2410复位之后,pc指针会指向0x0地址。在u-boot代码中,该0x0地址是一个向量表,第一条指令跳转branch到复位代码start_code。位于cpu/arm920t/start.S汇编语言文件第53行:.globl_start_start:bstart_codeldrpc,_undefined_instructionldrpc,_software_interruptldrpc,_prefetch_abortldrpc,_data_abortldrpc,_not_usedldrpc,_irqldrpc,_fiq复位指令跳转之后来到第154行,开始执行arm920t处理器的基本初始化。首先修改当前程序状态寄存器CPSR,使处理器进入Supervisor|32bitARM模式,并关闭ARM9TDMI中断和快速中断,这是通过设置CPSR相应掩码实现的:start_code:/**setthecputoSVC32mode*/mrsr0,cpsrbicr0,r0,#0x1forrr0,r0,#0xd3msrcpsr,r0紧接着,将S3C2410特有的WTCON寄存器清零,此举仅为关闭看门狗,代码位置是234行:ldrr0,=pWTCONmovr1,#0x0strr1,[r0]然后在241行,将S3C2410中断控制器INTMSK寄存器置为全1,INTSUBMSK置为0x7ff,禁止全部中断源。S3C2410手册358页起对此有详细描述:movr1,#0xffffffffldrr0,=INTMSKstrr1,[r0]#ifdefined(CONFIG_S3C2410)||defined(CONFIG_S3C2440)||defined(CONFIG_S3C2442)||\defined(CONFIG_S3C2443)ldrr1,=INTSUBMSK_valldrr0,=INTSUBMSKstrr1,[r0]#endif接下来在259行,访问arm920t控制寄存器CP15,并置位最高两位[31,30]。此两位置为0b11后,处理器时钟被设置为异步模式,允许处理器异步访问总线:mrcp15,0,r1,c1,c0,0orrr1,r1,#0xc0000000mcrp15,0,r1,c1,c0,0至此arm920t相关的配置完成,后面开始设定S3C2410时钟合成参数。通过设置UPLL,MPLL和CLKDIVN三个寄存器(在S3C2410手册237页起讲述),得到需要的处理器工作频率,分别在308行:ldrr0,=UPLLCONldrr1,=UPLLCON_valstrr1,[r0]321行:ldrr1,=MPLLCON_valstrr1,[r0,#-4]/*MPLLCON*//*FCLK:HCLKCLK=1:2:4*/ldrr0,=CLKDIVNmovr1,#CLKDIVN_valstrr1,[r0]S3C2410的UART0得到初始化,以便于尽早通过UART0打印信息。此段代码从332行开始,其中涉及到的寄存器读者可参考S3C2410手册293页起:/*enableuart*/ldrr0,=0x4c00000c/*clkcon*/ldrr1,=0x7fff0/*allclockson*/strr1,[r0]/*gpioUART0init*/ldrr0,=0x56000070movr1,#0xaastrr1,[r0]/*inituart*/ldrr0,=0x50000000movr1,#0x03strr1,[r0]ldrr1,=0x245strr1,[r0,#0x04]movr1,#0x01strr1,[r0,#0x08]movr1,#0x00strr1,[r0,#0x0c]movr1,#0x1astrr1,[r0,#0x28]完成UART0设置之后,根据不同的编译时选项和运行时参数,代码会在360行进入相应的分支,分别是从nand启动,代码执行lowlevel_init,主要是清除cpucache,以及关闭mmu和i-cache,并且根据板极硬件配置初始化外部存储器总线和GPIO,最后把代码从nandflash中拷贝到ram中并继续执行。从nor启动,与第1种情况相比,仅仅把代码拷贝部分简化,将DATA段从flash中拷贝到ram中,其余相同从ram启动,因为u-boot已经处于配置好的ram中,所以会跳过所有cache,mmu,sdram,nand和nor相关代码,跳转到done_relocate执行下面以最复杂的nand启动情况为例分析。首先会跳转到572行执行cpu_init_crit,通过操作CP15完成flush处理器arm920t的cache和tlb,并关闭mmu和i-cache:cpu_init_crit:/**flushv4I/Dcaches*/movr0,#0mcrp15,0,r0,c7,c7,0/*flushv3/v4cache*/mcrp15,0,r0,c8,c7,0/*flushv4TLB*//**disableMMUstuffandcaches*/mrcp15,0,r0,c1,c0,0bicr0,r0,#0x00002300@clearbits13,9:8(--V---RS)bicr0,r0,#0x00000087@clearbits7,2:0(B----CAM)orrr0,r0,#0x00000002@setbit2(A)Alignorrr0,r0,#0x00001000@setbit12(I)I-Cachemcrp15,0,r0,c1,c0,0然后跳转到board/neo1973/common/lowlevel_init.S文件的139行执行,进行总线数据宽度、时序、SDRAM控制、GPIO等配置,配置完毕后会返回start.S继续执行。因为该代码是与板相关,故放在board目录里面。由于代码较多,只粘贴开始部分:/*memorycontrolconfiguration*//*maker0relativethecurrentlocationsothatit*//*readsSMRDATAoutofFLASHratherthanmemory!*/adrr0,SMRDATAldrr1,=BWSCON/*BusWidthStatusController*/addr2,r0,#13*4完成板级设置后,在cpu/arm920t/start.S的373行判断代码自身的执行位置。如果从steppingstone内执行,并且u-boot配置为nandboot模式,则跳转到nand_load拷贝代码:ldrr1,=BWSCON/*Z=CPUbootedfromNAND*/ldrr1,[r1]tstr1,#6/*BWSCON[2:1]=OM[1:0]*/teqeqr0,#0/*Z&=runningataddress0*/beqnand_load在417行是nand_load代码,首先会跳转到614行执行may_resume以检测系统是从待机模式唤醒还是上电启动。如果唤醒,则会根据之前保存的现场进行相应处理,本文不做更多叙述;如果是启动,则会返回nand_load继续执行。在nand_load里初始化s3c2410的nandcontroller,涉及存储器映射和寄存器NFCONF等,参见S3C2410手册215页起。同样,仅粘贴开始部分的代码:movr1,#S3C2410_NAND_BASEldrr2,=0xf842@initialvalueenabletacls=3,rph0=6,rph1=0strr2,[r1,#oNFCONF]ldrr2,[r1,#oNFCONF]bicr2,r2,#0x800@enablechip在451行继续根据配置设定栈指针,为后面调用C函数执行拷贝作准备:ldrr0,_TEXT_BASE/*upper128KiB:relocateduboot*/subr0,r0,#CFG_MALLOC_LEN/*mallocarea*/subr0,r0,#CFG_GBL_DATA_SIZE/*bdinfo*/#ifdefCONFIG_USE_IRQsubr0,r0,#(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)#endifsubsp,r0,#12/*leave3wordsforabort-stack*/然后在460行,将SDRAM中的目标地址存入r0,0x0地址存入r1,u-boot长度存入r2,跳入cpu/arm920t/s3c24x0/nand_read.c文件第154行执行nand_read_ll函数,该函数接受前面3个寄存器中的值作为参数,并将返回值放回r0:ldrr0,_TEXT_BASEmovr1,#0x0movr2,#CFG_UBOOT_SIZEblnand_read_ll在nand_read_ll函数中实现了nandflash访问代码,并且支持自动跳过坏块的特性,函数循环执行nand页面读取并存入SDRAM,直到u-boot全部拷贝完,并返回0,该C代码留给读者自己阅读。nand_read_ll返回0后,会跳转到ok_nand_read,并482行对拷贝的头4K字节进行校验:@verifymovr0,#0@ldrr1,=0x33f00000ldrr1,_TEXT_BASEmovr2,#0x400@4bytes*1024=4K-bytesgo_next:ldrr3,[r0],#4ldrr4,[r1],#4teqr3,r4bnenotmatchsubsr2,r2,#4beqdone_nand_readbnego_next校验通过后代码506行,在地址为_booted_from_nand的SDRAM位置保存1,以便告诉上层软件
本文标题:u-boot启动过程(基于S3C2410)和uImagezImage启动分析
链接地址:https://www.777doc.com/doc-2852562 .html