您的位置:首页 > 其它

u-boot之u-boot-2009.11启动过程分析

2013-05-15 19:36 465 查看
上接博文《TI-Davinci开发系列之八x-loader工作流程分析

原创作品,转载时请务必以超链接形式标明文章原始出处:http://blog.csdn.net/gqb666/article/details/8931775,作者:gqb666

注:本文使用的u-boot源码版本为u-boot-2009.11

        u-boot同其他bootloader一样,其启动过程分为stage1和stage2两个阶段, stage1主要完成基本硬件设备初始化和为加载stage2部分的代码准备RAM空间,stage2则是为引导内核准备环境。下面分两部分来分析u-boot启动的两个阶段。



一、u-boot启动第一阶段stage1

        u-boot的第一阶段主要由u-boot源文件目录cpu\arm_cortexa8目录下的start.S和cpu\arm_cortexa8\omap3目录下lowlevel_init.S来完成,前者是SOC平台相关,后者是开发板相关的。

1、基础硬件初始化

基本硬件设备的初始化主要在start.S内完成,依次完成如下设置:将CPU的工作模式设为管理模式(svc),将中断向量表拷贝到SRAM,关闭WATCHDOG,后来就是关闭MMU,CACHE等。

reset:
/*
* set the cpu to SVC32 mode 设置ARM处理器的工作模式为SVC模式
*/
mrs r0, cpsr
bic  r0, r0, #0x1f
orr  r0, r0, #0xd3
msr cpsr,r0
/*将中断向量表拷贝到SRAM*/
#if (CONFIG_OMAP34XX)
/* Copy vectors to mask ROM indirect addr */
adr  r0, _start             @ r0<- current position of code
add r0, r0, #4             @ skip reset vector
mov       r2, #64                 @ r2 <- size to copy
add r2, r0, r2              @ r2 <- sourceend address
mov       r1, #SRAM_OFFSET0  @ build vect addr
mov       r3, #SRAM_OFFSET1
add r1, r1, r3
mov       r3, #SRAM_OFFSET2
add r1, r1, r3
next:
ldmia     r0!, {r3 - r10}              @ copy from source address [r0]
stmia     r1!, {r3 - r10}              @ copyto   target address [r1]
cmp       r0, r2                   @until source end address [r2]
bne next                     @loop until equal */

ldr   pc, _start_armboot    @ jump to C code
_start_armboot: .wordstart_armboot
cpu_init_crit:
/*关闭MMU与CACHE */
mov       r0, #0                   @ set up for MCR
mcr p15, 0, r0, c8, c7, 0    @ invalidateTLBs
mcr p15, 0, r0, c7, c5, 0    @ invalidateicache

mrc p15, 0, r0, c1, c0, 0
bic  r0, r0, #0x00002000  @ clear bits 13(--V-)
bic  r0, r0, #0x00000007  @ clear bits 2:0 (-CAM)
orr  r0, r0, #0x00000002  @ set bit 1 (--A-) Align
orr  r0, r0, #0x00000800  @ set bit 12(Z---) BTB
mcr p15, 0, r0, c1, c0, 0
/*调用lowlevel_init用来初始化RAM*/
mov       ip, lr                     @persevere link reg across call
bl    lowlevel_init                @go setup pll,mux,memory
mov       lr, ip                     @restore link
mov       pc, lr                    @back to my caller


2、为stage2准备RAM空间

所谓准备RAM空间,就是初始化内存控制器,使它可用。对于OMAP3这种SOC,通过在start.S中调用lowlevel_init函数来设置存储控制器,使得外接的SDRAM可用。代码在cpu\arm_cortexa8\omap3目录下lowlevel_init.S中。

.globl lowlevel_init
lowlevel_init:
ldr   sp,   SRAM_STACK
str     ip,       [sp]   /* stashold link register */
mov       ip,   lr     /*save link reg across call */
bl      s_init          /* gosetup pll,mux,memory */
ldr     ip,       [sp]    /* restore saveip */
mov       lr,    ip    /*restore link reg */
/* back toarch calling code */
mov       pc,  lr
/* the literalpools origin */
.ltorg


 3、复制stage2代码到RAM空间

这里将u-boot的代码(实际包括第一、二阶段)都复制到SDRAM中,这在cpu\arm_cortexa8中start.S中完成,这一步是u-boot第一阶段的核心所在,因为它实际上完成将代码拷贝到u-boot执行的链接地址处,在此之后的变量就可以进行正常读写,前面的代码必须是位置无关代码(只能读操作不能写操作)。

relocate:                           /*将x-loader复制到RAM中      */
adr  r0, _start             /* r0:当前代码的开始地址   */
ldr   r1, _TEXT_BASE         /* r1:代码段的链接地址 */
cmp r0, r1         /* 测试是否需要复制(SRAM,SDRAM,NOR FLAHS不需要复制)
beq stack_setup                /*直接跳到栈初始化部分) */

ldr   r2, _armboot_start /*_armboot_start在前面定义,第一条指令地址*/
ldr   r3, _bss_start /*链接脚本x-loader.lds中定义,是代码段的结束地址*/
sub  r2, r3, r2              /* r2 :代码段长度 */
add r2, r0, r2              /* r2:SRAM上代码段的结束地址         */

copy_loop:
ldmia     r0!, {r3-r10}         /*从地址[r0]处获得数据    */
stmia     r1!, {r3-r10}         /*复制到地址[r1]处    */
cmp       r0, r2                   /*判断是否复制完毕    */
ble  copy_loop


4、设置堆栈

栈的设置灵活性很大,只要让sp寄存器指向一段没有使用的内存即可。

/* Set up the stack                                           */
stack_setup:
ldr   r0, _TEXT_BASE         /*_TEXT_BASE代码段的开始地址   */
sub  sp, r0, #128         /*为 abort-栈保留32字节   */
and sp, sp, #~7           /* 8字节对齐   */


 5、跳转到stage2的入口点

在跳转之前,还要清除BSS段(初始值为0、无初始值的全局变量、静态变量放在BSS段),代码如下:

clear_bss:
ldr   r0, _bss_start             /* bss段的开始地址        */
ldr   r1, _bss_end        /* bss段的结束地址,它的值在链接脚本中定义*/
mov      r2, #0x00000000       /* clear value                      */
clbss_l:
str   r2, [r0]          /*往bss段内写入0值               */
cmp       r0, r1                   /*are we at the end yet            */
add r0, r0, #4             /* increment clearindex pointer    */
bne clbss_l                 /* keep clearing till atend        */

ldr   pc, _start_armboot    /*向C函数入口跳转   */
_start_armboot: .word start_armboot


二、u-boot启动第二阶段stage2

       本部分主要说明u-boot第二阶段stage2的,u-boot在启动内核之前可以让用户决定是否进入下载模式,即进入u-boot的控制界面。第二阶段从lib_arm/board.c中的start_armboot函数开始,由于代码量较大,本文先将其过程用流程图表示,后面有时间再将代码补上,如下图所以:



下转博文《Linux内核启动及文件系统加载过程
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  u-boot