TI-Davinci开发系列之八x-loader工作流程分析

DM3730仅集成了一个Nand Flash控制器,所以uboot镜像只能烧在Nand Flash上,通过Nand Flash启动,然而Nand Flash并不支持XIP(eXecute In Place,即芯片内执行)。所以针对Nand Flash的启动方式,一般在采用0x0地址挂载一个容量较小的SRAM(称为Steppingstone)。而且Nand Flash的第一页烧入的x-load,原因是uboot较大,Steppingstone没有足够的空间存放uboot,而x-loader则较小,只有几KB。系统启动时会自动将Nand Flash的第一页上x-loader复制到Steppingstone,其主要工作是初始化PLL,DDR,只有初始化了DDR,才能把uboot下载到DDR里面执行。所以说系统启动首先执行的是x-loader,而x-loader第一阶段的工作与u-boot的第一阶段完全相同,实际上x-loader是u-boot的一个精简版,所以其第一阶段的工作我们只在x-loader中介绍。X-loader启动过程分为stage1和stage2两个阶段, stage1主要完成基本硬件设备初始化和为加载stage2部分的代码准备RAM空间,stage2则是准备环境并引导u-boot在内存中运行。下面分两部分来分析x-loader启动的两个阶段。

                                                                                  图2.1 两种启动方式存储分配

一、x-loader启动第一阶段stage1

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

(1) 硬件设备初始化

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

[plain]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. reset:  
  2.       /*  
  3.        * set the cpu to SVC32 mode 设置ARM处理器的工作模式为SVC模式  
  4.        */  
  5.       mrs r0, cpsr  
  6.       bic  r0, r0, #0x1f  
  7.       orr  r0, r0, #0xd3  
  8.       msr cpsr,r0  
  9. /*将中断向量表拷贝到SRAM*/  
  10. #if (CONFIG_OMAP34XX)  
  11.       /* Copy vectorsto mask ROM indirect addr */  
  12.       adr  r0, _start             @ r0<- current position of code  
  13.       add r0, r0, #4             @ skip reset vector  
  14.       mov       r2, #64                 @ r2 <- size to copy  
  15.       add r2, r0, r2              @ r2 <- sourceend address  
  16.       mov       r1, #SRAM_OFFSET0  @ build vect addr  
  17.       mov       r3, #SRAM_OFFSET1  
  18.       add r1, r1, r3  
  19.       mov       r3, #SRAM_OFFSET2  
  20.       add r1, r1, r3  
  21. next:  
  22.       ldmia     r0!, {r3 - r10}              @ copy from source address [r0]  
  23.       stmia     r1!, {r3 - r10}              @ copyto   target address [r1]  
  24.       cmp       r0, r2                   @until source end address [r2]  
  25.       bne next                     @loop until equal */  
  26. //  
  27.    
  28.       ldr   pc, _start_armboot    @ jump to C code  
  29. _start_armboot: .wordstart_armboot  
  30. cpu_init_crit:  
  31.       /*关闭MMU与CACHE */  
  32.       mov       r0, #0                   @ set up for MCR  
  33.       mcr p15, 0, r0, c8, c7, 0    @ invalidateTLBs  
  34.       mcr p15, 0, r0, c7, c5, 0    @ invalidateicache  
  35.    
  36.       mrc p15, 0, r0, c1, c0, 0  
  37.       bic  r0, r0, #0x00002000  @ clear bits 13(--V-)  
  38.       bic  r0, r0, #0x00000007  @ clear bits 2:0 (-CAM)  
  39.       orr  r0, r0, #0x00000002  @ set bit 1 (--A-) Align  
  40.       orr  r0, r0, #0x00000800  @ set bit 12(Z---) BTB  
  41.       mcr p15, 0, r0, c1, c0, 0  
  42.       /*调用lowlevel_init用来初始化RAM*/  
  43.       mov       ip, lr                     @persevere link reg across call  
  44.       bl    lowlevel_init                @go setup pll,mux,memory  
  45.       mov       lr, ip                     @restore link  
  46.       mov       pc, lr                    @back to my caller  
(2)为stage2准备RAM空间

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

[plain]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. .globl lowlevel_init  
  2. lowlevel_init:  
  3.       ldr   sp,   SRAM_STACK  
  4.         str     ip,       [sp]   /* stashold link register */  
  5.       mov       ip,   lr     /*save link reg across call */  
  6.       bl      s_init          /* gosetup pll,mux,memory */  
  7.         ldr     ip,       [sp]    /* restore saveip */  
  8.       mov       lr,    ip    /*restore link reg */  
  9.       /* back toarch calling code */  
  10.       mov       pc,  lr  
  11.       /* the literalpools origin */  
  12.       .ltorg  

(3)复制stage2代码到RAM空间

这里将x-loader的代码(实际包括第一、二阶段)都复制到SDRAM中,这在\cpu\omap3中start.S中完成,在本系统的x-loader中,复制代码实际并未发生,因为SRAM支持XIP。

[plain]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. relocate:                           /*将x-loader复制到RAM中      */  
  2.       adr  r0, _start             /* r0:当前代码的开始地址   */  
  3.       ldr   r1, _TEXT_BASE         /* r1:代码段的链接地址 */  
  4.       cmp r0, r1       /* 测试是否需要复制(SRAM,SDRAM,NOR FLAHS不需要复制)                                    
  5.       beq stack_setup                /*直接跳到栈初始化部分) */  
  6.    
  7.       ldr   r2, _armboot_start /*_armboot_start在前面定义,第一条指令地址*/  
  8.       ldr   r3, _bss_start /*链接脚本x-loader.lds中定义,是代码段的结束地址*/  
  9.       sub  r2, r3, r2              /* r2 :代码段长度 */  
  10.       add r2, r0, r2              /* r2:SRAM上代码段的结束地址         */  
  11.    
  12. copy_loop:  
  13.       ldmia     r0!, {r3-r10}         /*从地址[r0]处获得数据    */  
  14.       stmia     r1!, {r3-r10}         /*复制到地址[r1]处    */  
  15.       cmp       r0, r2                   /*判断是否复制完毕    */  
  16.       ble  copy_loop  

(4) 设置堆栈

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

[plain]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /* Set up the stack                                           */  
  2. stack_setup:  
  3.       ldr   r0, _TEXT_BASE         /*_TEXT_BASE代码段的开始地址   */  
  4.       sub  sp, r0, #128         /*为 abort-栈保留32字节   */  
  5.       and sp, sp, #~7           /* 8字节对齐   */  

(5)跳转到stage2的入口点

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

[plain]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. clear_bss:  
  2.       ldr   r0, _bss_start             /* bss段的开始地址        */  
  3.       ldr   r1, _bss_end        /* bss段的结束地址,它的值在链接脚本中定义*/  
  4.       mov      r2, #0x00000000       /* clear value                      */  
  5. clbss_l:  
  6.       str   r2, [r0]          /*往bss段内写入0值               */  
  7.       cmp       r0, r1                   /*are we at the end yet            */  
  8.       add r0, r0, #4             /* increment clearindex pointer    */  
  9.       bne clbss_l                 /* keep clearing till atend        */  
  10.    
  11.       ldr   pc, _start_armboot    /*向C函数入口跳转   */  
  12. _start_armboot: .word start_armboot  

二、 x-loader启动第二阶段stage2

X-loader第二阶段主要用来引导u-boot从SDRAM启动,主要根据配置文件中定义的启动类型调用相应驱动程序,将u-boot.bin格式的镜像文件从不同存储介质中拷贝到内存,并从内存开始执行。主要代码在lib/下的board.c。

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #ifdef CONFIG_MMC  //如果配置了MMC启动,则调用mmc驱动加载  
  2.       /* first trymmc */  
  3.       if (mmc_init(1)) {  
  4.              size =file_fat_read("u-boot.bin", buf, 0);  
  5.              if (size > 0) {  
  6. #ifdef CFG_PRINTF  
  7.                  printf("Loadingu-boot.bin from mmc\n");  
  8. #endif  
  9.                  buf += size;  
  10.              }  
  11.       }  
  12. #endif  
  13.       if (buf == (uchar*)CFG_LOADADDR) {  
  14.       /* if no u-boot on mmc, tryonenand or nand, depending upon sysboot */  
  15.           if (get_mem_type() ==GPMC_ONENAND){  
  16. #ifdef CFG_ONENAND  
  17. ……  
  18. #ifdef CFG_NAND_K9F1G08R0A  //如果定义了nand启动,调用nand加载  
  19. #ifdef CFG_PRINTF  
  20.     printf("Loading u-boot.bin fromnand\n");  
  21. #endif  
  22.     for (i = NAND_UBOOT_START; i < NAND_UBOOT_END; i+= NAND_BLOCK_SIZE){  
  23.         if (!nand_read_block(buf, i))  
  24.             buf += NAND_BLOCK_SIZE; /* advance buf ptr*/  
  25.     }  
  26. #endif  
  27. }  
  28. 转载:http://blog.csdn.net/gqb_driver/article/details/20069643
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值