电子书:《模拟对话》,共50卷,数百篇精品文章,下载即奖励400信元!
返回列表 发帖

一个IC设计人员理解的Boot

一个IC设计人员理解的Boot

本人不是做驱动的,下面内容是查阅一些资料再加上自己的理解总结的,和大家讨论,欢迎指证!
=============================================================
一、什么是Uboot              

       Uboot是德国DENX小组的开发用于多种嵌入式CPU的bootloader程序, UBoot不仅仅支持嵌入式Linux系统的引导,当前,它还支持NetBSD, VxWorks, QNX, RTEMS, ARTOS, LynxOS嵌入式操作系统。UBoot除了支持PowerPC系列的处理器外,还能支持MIPS、 x86、ARM、NIOS、XScale等诸多常用系列的处理器。
二、Uboot启动过程简介         

      多数bootloader都分为阶段1(stage1)和阶段2(stage2)两大部分,uboot也不例外。依赖于CPU体系结构的代码(如CPU初 始化代码等)通常都放在阶段1中且通常用汇编语言实现,而阶段2则通常用C语言来实现,这样可以实现复杂的功能,而且有更好的可读性和移植性。               
      第一阶段的功能:                  

     1. 硬件设备初始化                 
     2. 加载U-Boot第二阶段代码到RAM空间                 
     3. 设置好栈                  
     4. 跳转到第二阶段代码入口     
         
  第二阶段的功能:                  
         1. 初始化本阶段使用的硬件设备                  
         2. 检测系统内存映射                  
         3. 将内核从Flash读取到RAM中                  
         4.为内核设置启动参数                  
         5. 调用内核      

下面重点整理一些硬件相关的过程,以ARM926为例              
1.   硬件设备初始化                     

       (1)设置异常向量表                    
       (2)将CPU的工作模式位设置为管理模式SVC               
       (3)将中断禁止位和快中断禁止位置'1',关闭IRQ和FIQ中断处理         
       (4)关闭看门狗;                           
       (5)设置时钟相关寄存器MPLLCON,UPLLCON, CLKDIVN。

                CPU上电几毫秒后,晶振输出稳定,FCLK=Fin(晶振频率),CPU开始执行指令。但实际上,FCLK可以用软件来启用PLL改变。设置PLL的寄存器后,CPU会停滞一段时间,等待频率稳定后再开  始重新工作,中间停滞等待时间有的处理器通过寄存器设置,有的自动插入,总之这段时间CPU时钟不跳转,处于停滞状态, 由硬件保障CPU的停止和恢复的正确性。               
       (6)关闭MMU,cache。

                  数据cache必须关闭,Bootloader主要是装载内核镜像,镜像数据必须真实写回SDRAM中,所以数据cache必须关闭,而对于指令cache,不存在强制性的规定,但在一般情况下,推荐关闭cache和MMU。                     
       (7) 初始化RAM控制寄存器              

2. 复制U-Boot第二阶段代码到RAM   

        /* 判断U-Boot是否是下载到RAM中运行,若是,则不用 再复制到RAM中了,这种情况通常在调试U-Boot时才发生 */               

3. 设置堆栈,清除BSS段              

4. 跳转到第二阶段代码入口

     第二阶段的功能硬件工作人员关心较少,其中初始化本阶段使用的硬件设备主要和硬件有关,例如时钟、串口等外设。

三、重定位Relocate           

    BootLoader中的重定位(relocate)代码段是将BootLoader自身第二阶段的代码由Flash复制到SDRAM,以便跳转到SDRAM执行。之所以需要进行重定位是因为在Flash中执行速度比较慢,而系统复位后总是从0x00000000地址FLASH取指。         
重定位代码,位于/U-Boot/cpu/s3c44b0/start.S :   
          relocate:                        /* relocate U-Boot to RAM  */         
         adrr0, _start                  /* r0 <- current position of code      */           
         ldrr1, _TEXT_BASE    /* test if we run from flash or RAM    */   
         cmp     r0, r1                 /* don't reloc during debug         */      
         beq     stack_setup            
         ldrr2, _armboot_start            
         ldrr3, _bss_start            
        sub r2, r3, r2                                       /* r2 <- size of armboot    */            
        add r2, r0, r2                                      /* r2 <- source end address */   
       copy_loop:     ldmia r0!, {r3-r10}     /* copy from source address [r0]   */           
        stmia r1!, {r3-r10}                            /* copy to target address [r1] */        
       cmp r0, r2                                         /* until source end address [r2]   */               
ble copy_loop以上代码首先判断是否需要进行重定位(如果是调试状态,代码直接下载到SDRAM就不需要relocate),如果需要的话首先确定复制的源基址、源大小和目标基址,然后以r3 ~ r13为媒介,将BootLoader复制到SDRAM中。分析copy_loop很容易理解,这里主要分析relocate处的前两条指令:
1. adrr0, _start adr是一条伪指令,汇编器总是试图为它产生add/sub这样的指令,(在这里)以pc为基址装载目标寄存器。以下是arm-elf-objdump产生的反汇编代码: c700048:   e24f0050  sub r0, pc, #80   ; 0x50e24f0050是指令对应的机器码,c700048是存放该机器码的地址(十六进制表示)。这个地址是怎么来的呢?在/U-Boot/config.mk中有问题的答案: LDFLAGS += -Bstatic -T $(LDSCRIPT) -Ttext $(TEXT_BASE) $(PLATFORM_LDFLAGS)上面的宏指定连接时的命令行参数,-Ttext设定了.text段的地址,而TEXT_BASE在/U-Boot/board/.../config.mk中定义为0x0C700000。这些信息最后都以硬编码的方式记录在程序映像文件中,程序的入口_start = TEXT_BASE = 0x0C700000 : Disassembly of section .text:0c700000 <_start>: c700000: ea00000a  b   c700030  ...但是,程序映像是烧写到Flash中并开始执行的,而Flash的地址从0x00000000开始。于是,程序映像的第一条指令对齐到0x00000000处。相应的,这条adr指令的地址应对齐到0x00000048处,执行后r0等于0。
2.  ldr r1, _TEXT_BASE 以下是arm-elf-objdump产生的反汇编代码: c70004c:   e51f1034  ldr r1, [pc, #-52]    ; c700020 <_TEXT_BASE>由此可见,这里的ldr并不是简单的将_TEXT_BASE地址处的4字节装载到r1,而同样是以pc为基址计算得到源地址的。这里的pc = 0x4c + 8 = 0x54,于是该指令把0x54 – 52 = 0x20处的4字节(即TEXT_BASE,亦即0x0C700000)装载到r1。
3.   源大小的确定
       通过上面的分析,我们已经有了一个概念:程序的实际执行地址与连接时指定的加载地址可能是不一样的。我们已经得到BootLoader代码开始的运行时开始地址,存放于r0,还需要计算它的运行时结束地址。运行时结束地址 = 运行时开始地址 + 代码段大小。代码段大小由.bss段的期望开始地址 - .text段的期望开始地址获得。小结通过连接时的-Ttext选项,将.text段的地址硬编码到程序映像中。虽然程序映像在Flash中执行,其实际执行地址与期望执行地址不一致,但在relocate之前,通过以pc为基址进行相对寻址,使得这些代码的执行与其实际装载的地址无关。

三、重映射Remap     

        从Remap这个英文单词的构成不难看出,它是对此前已确立的存储器映射的再次修 改。从本质上讲,Map和Remap是一样的,都是将地址编码资源分配给存储器块,只不过二者产生的时间不同:前者在系统上电的时刻发生,是任何计算机系统都必需的;而后者在系统上电后稳定运行的时刻发生,对计算机系统设计人员来说是可选的。典型的8位单片机系统中,就没有使用Remap技术。     
         Remap通常始于系统的Bootload过程。具体执行动作为:Bootload将FLASH中的异常向量复制到SDRAM块的一端,然后执行Remap命令,将位于SDRAM异常向量块映射到异常向量表地址空间(原FLASH地址)上。此后,系统若产生异常,CPU将从SDRAM中读取异常向量。Remap的目的就是让CPU可以快速跳入异常处理程序,获得最佳的实时异常响应。(中断向量表的设置要看当前CPU运行的模式。如果是实模式的话,中断向量表就在物理地址00000000h开始。如果是保护模式就复杂了,要用lgdt之类的命令来加载表,教写操作系统的书会有说的。)   
          Remap由处理器硬件实现,它会允许把内存地址空间的某一段映射到某个位置,ARM中常见的是在上电复位的时候自动把引导加载程序锁在FLASH的地址映射到0x00000000,在引导加载的过程中由软件通过设置某个内存重映射寄存器,然后把主存地址重映射到0x00000000。在这种重映射的情况下,访问映射的地址相当于直接访问对应的FLASH或者主存的地址。  
四、Boot与硬件      

        通常Bootloader存储在Nor Flash上,可以直接运行。那能不能从NAND Flash启动呢?原则上不行,因为NAND Flash读写需要驱动程序的支持,Boot没完成前驱动程序不可用。但是为了解决这个问题,有些处理器在硬件上做了特殊处理,例如三星的S3C2440 有一个内部的 SDRAM 缓存称为“Steppingstone”,当上电 的时候,Nand Flash 的首 4kbyte 会被自动导入到 Steppingstone 并且开始执行。所以,从NAND Flash启动只要保证它不超过4kbyte就好了。
========================================================================
有的硬件系统与上述的有些差别,比如我公司设计的一款芯片,Bootloader第一段代码固化在芯片内部的ROM,Bootloader第二段代码固话在芯片外设SPI接口的Flash存储中,上电后先进行RomBoot,RomBoot执行Relocate任务,将Flash中的代码复制到DRAM中,然后切换时钟后跳转到DDR中执行,Remap最后完成。

写的挺好!

TOP

从芯片设计者的角度看确实是一个号的角度。。

TOP

赞一个

TOP

很好。顶

TOP

标题党,这个和IC设计没啥关系

TOP

回复 6# hit_troy

这个跟IC还真有关系,做过类似手机、平板主芯片没有

TOP

谢谢分享~

TOP

THANKS

TOP

返回列表

站长推荐 关闭


电子书:《模拟对话》,共50卷,数百篇精品文章,下载即奖励400信元!

电子书:《模拟对话》,共50卷,数百篇精品文章,下载即奖励400信元!


查看