现在的位置: 首页 > 综合 > 正文

u-boot源码个别分析

2013年08月31日 ⁄ 综合 ⁄ 共 6614字 ⁄ 字号 评论关闭

u-boot源码个别分析 

深入Bootloader系列

http://ftp.denx.de/pub/u-boot/
 

简介===>

1.U-Boot系统加载器

U-Boot是一个规模庞大的开源Bootloader软件,最初是由denx(www.denx.de发起。U-Boot的前身是PPCBoot,目前是SourceForge(www.sourceforge.net)的一个项目。

最初的U-Boot仅支持PowerPC架构的系统,称做PPCBoot。从0.3.2官方版本之后开始逐步支持多种架构的处理器,目前可以支持 PowerPC(MPC5xx、MPC8xx、MPC82xx、MPC7xx、MPC74xx)、ARM(ARM7、ARM9、StrongARM、 Xscale)、MIPS(4kc、5kc)、X86等处理器,支持的嵌入式操作系统有Linux、Vx-Works、NetBSD、QNX、 RTEMS、ARTOS、LynxOS等,是PowerPC、ARM9、Xscale、X86等系统通用的Boot方案。

U-Boot支持的处理器和操作系统很多,但是它对PowerPC系列处理器和Linux操作系统支持最好。U-Boot支持的功能也较多,对于嵌 入式开发常用的查看、修改内存,从网络下载操作系统镜像等功能都提供了很好的支持。U-Boot的项目更新较快,支持的目标板众多,是学习底层开发很好的 示例。

2.ViVi系统加载器

ViVi是韩国的mizi公司专门针对ARM9处理器设计的一款Bootloader。它的特点是操作简便,同时提供了完备的命令体系,目前在三星系列的ARM9处理器上ViVi也比较流行。

与U-Boot相比,由于ViVi支持的处理器单一,ViVi的代码也要小很多。同时,ViVi的软件架构和配置方法采用和Linux内核类似的风格,对于有过配置编译Linux内核经验的读者,ViVi更容易上手。

与其他的Bootloader一样,ViVi有两种工作模式:启动加载模式和下载模式。使用启动加载模式,在目标板上电后,ViVi会从预先配置好 的Flash分区读取Linux或者其他系统的镜像并且启动系统;使用下载模式,ViVi向用户提供了一个命令行接口,通过该接口用户可以使用ViVi提 供的命令。ViVi主要提供了5个命令如下:

Load:把二进制文件载入Flash或RAM。

Part:操作MTD分区信息。显示、增加、删除、复位、保存MTD分区。

Param:设置参数。

Boot:启动系统。

Flash:管理Flash,如删除Flash的数据。

与Linux内核的组织类似,ViVi的源代码主要包括arch、init、lib、drivers和include等几个目录,共200多个代码文件。各目录的具体功能请参考ViVi相关的信息。

=====================================================================》》》

=====================================================================》》》

=====================================================================》》》

 

基本目录分类:

common目录是与体系结构无关的文件,包括实现各种命令的C语言源代码文件。

cpu目录          存放与CPU相关的文件,每种CPU需要的代码文件存放在以CPU名称命名的子目录下,arm920t存放了arm920t为内核的 CPU相关的文件。在每个特定的子目录下都包括cpu.c、interrupt.c和start.S这3个文件,这3个文件是CPU初始化以及配置中断的 代码。U-Boot自带了很多CPU相关的代码,用户可以在现有CPU支持的基础上修改自己所需要的配置。

通用设备的驱动程序存放在drivers目录下。U-Boot自带了许多设备的驱动,包括显示芯片、网络接口控制器、USB控制器、I2C器件等,对于大多数用户而言已经够用,用户也可以按照自己的需求增加或者修改设备驱动。

fs                    存放支持的文件系统代码,U-Boot目前支持cramfs、ext2、fat、jffs、reiserfs、yaffs等多种常见的文件系统。

net目录         是与网络协议有关的代码,比如BOOTP协议、TFTP协议、RARP协议等。

post               存放与硬件自检有关的代码。

rtc目录          存放与硬件实时时钟相关的代码。

tools目录      存放U-Boot编译过程中用到的一些工具代码。  // 例如:mkimage

==========================================

hao:

start_armboot => bootm.c

向量表在_start开始阶段已经汇编搞定。


其实主要就是个寄存器和内存的基本处理。


===》》》

列出了U-Boot在ARM处理器启动过程中的几个关键点,

从图中看出U-Boot的启动代码分布在start.S、low_level_init.S、 board.c和main.c文件中。

start.S                    是U-Boot整个程序的入口,该文件使用汇编语言编写,不同体系结构的启动代码是不同 的;

low_level_init.S    特定开发板的设置代码

board.c                  包含开发板底层设备驱动

main.c是一个与平台无关的代码,U-Boot应用程序的入口在此文件中

取出CPSR寄存器的值,CPSR寄存器保存当前系统状态,

使用比特清除命令清空了CPSR寄存器的中断控制位,表示清除 中断。

设置了CPSR寄存器的处理器模式位为管理模式,然后在第117行写入 CPSR的值强制切换处理器为超级保护模式。

定义看门狗控制器有关的变量,

根据平台设置看门狗定时器。

设置时钟分频寄存器的值。

需要根据CONFIG_SKIP_LOWLEVEL_INIT宏的值是否跳转到cpu_init_crit标号执行

===========cpu_init_crit==========

                                                                cpu_init_crit标号处的代码初始化ARM处理器关键的寄存器


  1. 228 /*  
  2. 229  *****************************************************************  
  3. 230  *  
  4. 231  * CPU_init_critical registers  
  5. 232  *  
  6. 233  * setup important registers  
  7. 234  * setup memory timing  
  8. 235  *  
  9. 236  ******************************************************************  
  10. 237  */  
  11. 238   
  12. 239   
  13. 240 #ifndef CONFIG_SKIP_LOWLEVEL_INIT  
  14. 241 cpu_init_crit:  
  15. 242   /*  
  16. 243    * flush v4 I/D caches  
  17. 244    */  
  18. 245   mov r0, #0  
  19. 246   mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */     // 1.刷新cache
     
  20. 247   mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */          // 2.刷新TLB
     
  21. 248   
  22. 249   /*  
  23. 250    * disable MMU stuff and caches                       // 3.关闭MMU  
  24. 251    */  
  25. 252   mrc p15, 0, r0, c1, c0, 0  
  26. 253   bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)  
  27. 254   bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM)  
  28. 255   orr r0, r0, #0x00000002 @ set bit 2 (A) Align  
  29. 256   orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache  
  30. 257   mcr p15, 0, r0, c1, c0, 0  
  31. 258   
  32. 259   /*  
  33. 260    * before relocating, we have to setup RAM timing  
  34. 261    * because memory timing is board-dependend, you will  
  35. 262    * find a lowlevel_init.S in your board directory.  
  36. 263    */  
  37. 264   mov ip, lr  
  38. 265   bl  lowlevel_init   // 跳转到lowlevel_init
     
  39. 266   mov lr, ip  
  40. 267   mov pc, lr  
  41. 268 #endif /* CONFIG_SKIP_LOWLEVEL_INIT */ 

 

 

==>2.

TLB的作用是在处理器访问内存数据的时候做地址转换。TLB的全称是Translation Lookaside Buffer,可以翻译做旁路缓冲。

TLB中存放了一些页表文件,文件中记录了虚拟地址和物理地址的映射关系。当应用程序访问一个虚拟地址的时候,会
TLB中查询出对应的物理地址
,然后访问物理地址。TLB通常是一个分层结构,使用与Cache类似的原理。处理器使用一定的算法把最常用的页表放在最先 访问的层次。

==>3.

程序第252~257行关闭MMU。MMU是内存管理单元(Memory Management Unit)的缩写。在现代计算机体系结构上,MMU被广泛应用。使用MMU技术可以向应用程序提供一个巨大的虚拟地址空间。在U-Boot初始化的时候,
程序看到的地址都是物理地址,无须使用MMU。

 

 


=========================lowlevel_init=========================  

                                                                                 位于board/smdk2410/lowlevel_init.S文件
                                        
开发板相关的初始化配置


  1. 133 lowlevel_init:  
  2. 134   /* memory control configuration */  
  3. 135   /* make r0 relative the current location so that it */  
  4. 136   /* reads SMRDATA out of FLASH rather than memory ! */  
  5. 137   ldr      r0,   =SMRDATA                      // 读取SMRDATA变量地址
     
  6. 138   ldr  r1,  _TEXT_BASE                        // 读取_TEXT_BASE变量地址  
  7. 139   sub    r0,  r0, r1                                 // 得出相对偏移
  8. 140   ldr      r1,  =BWSCON                        // 主要是了解BANK的位宽,16位
  9. 141   add    r2,     r0,  #13*4                     
    // 得到SMRDATA占用的大小,结尾处的偏移
  10. 142 0:  
  11. 143   ldr     r3, [r0], #4                               // 加载SMRDATA到内存  ,相当于一个while循环
  12. 144   str     r3, [r1], #4  
  13. 145   cmp     r2, r0  
  14. 146   bne     0b                                       
    // 循环,相当于while循环
  15. 147   
  16. 148   /* everything is fine now */  
  17. 149   mov pc, lr  
  18. 152 /* the literal pools origin */  
  19. 153   
  20. 154 SMRDATA:            // 定义SMRDATA值
     
  21. 155     .word (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON 
     
  22.         <<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28))
     
  23. 156     .word ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_ Tcoh<<6)+
     
  24.         (B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))
     
  25. 157     .word ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+ 
     
  26.         (B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC))
     
  27. 158     .word ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+ 
     
  28.         (B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC))
     
  29. 159     .word ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+ 
     
  30.         (B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC))
     
  31. 160     .word ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+ 
     
  32.         (B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC))
     
  33. 161     .word ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+ 
     
  34.         (B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC))
     
  35. 162     .word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))
     
  36. 163     .word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))
     
  37. 164     .word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+ 
     
  38.         (Tchr<<16)+REFCNT)
     
  39. 165     .word 0x32  
  40. 166     .word 0x30  
  41. 167     .word 0x30 

程序第137~141行计算SMRDATA需要加载的内存地址和大小。首先在137行读取SMRDATA的变量地址,之后计算存放的内存地址并且记录在r0寄存器,然后根据总线宽度计算需要加载的SMRDATA大小,并且把加载结束地址存放在r2寄存器。

程序第14

抱歉!评论已关闭.