minis3c2440嵌入式开发板之uboot详解

    技术2022-05-20  63

    Bootloader/u-boot的启动模式

     对于计算机系统来说,从计算机开机上电的到操作系统的启动需要一个引导过程。嵌入式Linux同样也需要一个引导的过程,及引导程序就叫做BootloaderBootloader是在操作系统启动之前执行的一小段程序,通过这段小程序,我们可以初始化硬件设备、建立内存空间映射表,从而建立适当系统软硬件环境,为最终调用操作系统内核做好准备。

     对于嵌入式系统,Bootloader是基于特定平台来实现的,因此几乎不可能为所有的计算机操作系统建立一个通用的Bootloader,不同的处理器架构都有不同的BootloaderBootloader不但依赖于CPU的体系结构,而且依赖于嵌入式系统板级的设备的配置。对于两块不同的嵌入式开发板,即使他们使用同一种处理器,要想让运行于一块板子上的Bootloader运行在另一块板子上,一般都需要修改Bootloader源程序。

     反过来大多数的Bootloader都具有很多的共性,某些Bootloader也能够支持多种体系结构的嵌入式系统。例如:u-boot就同时支持PowerpcARmMIPSX86等等的体系结构,支持的板子有上百种,通常他们都能够自动从存储介质上启动,都能够引导操作系统启动,并且大部分都可以支持串口和网口的操作。

     系统加电或者复位后,cpu通常都会从某个地址开始执行,这是由处理器决定的,对于ARM处理器而言会从0x00000000取第一条指令,嵌入式系统的开发板都要把ROMFLASH映射到这个地址上,因此必须将Bootloader的程序存储在相应的FLASH位置,这样系统加电后就会首先执行它。

    u-boot的启动一般流程:

    第一阶段:依赖cpu初始化外围硬件代码,通常用汇编代码实现

    1、设置cpu的工作模式;

    2、关中断,以防止意外发生;

    /*************************************************

    * set the cpu to SVC32 mode,设置cpu工作模式为11010011

    *  后五位表示cpu的工作模式设置为”管理”,并且关闭中断

    *  110则表示IRQ(普通中断)FIQ(快速中断)都为禁止

    **************************************************/

    mrs     r0,cpsr//读取cpsr中的数据到r0

        bic r0,r0,#0x1f//将寄存器r0的值和0x1f的反码安位与之后将结果存储在r0中相当于清零

        orr r0,r0,#0xd3//将寄存器r0的值和0xd3安位或之后将结果保存在r0寄存器之中,关闭中断

        msr     cpsr,r0//cpsr中的数值写到r0寄存器中

    3、关闭看门狗,避免系统重启;

    #ifdefined(CONFIG_S3C2400)||defined(CONFIG_S3C2410)||defined(CONFIG_S3C2440)

        /* turn off the watchdog,关闭开门狗*/

    # if defined(CONFIG_S3C2400)

    #  define pWTCON           0x15300000

    #  define INTMSK       0x14400008  /* Interupt-Controller base addresses */

    #  define CLKDIVN    0x14800014  /* clock divisor register */

    #else

    #  define pWTCON           0x53000000

    #  define INTMSK       0x4A000008  /* Interupt-Controller base addresses */

    #  define INTSUBMSK     0x4A00001C

    #  define CLKDIVN    0x4C000014  /* clock divisor register */

    # endif

    4、设置back初始化,设置cpu的工作频率;

    #if defined(CONFIG_S3C2440)

    /*FCLK HCLK PCLK = 1: 4: 8*/

     

       ldr  r0, =CLKDIVN

       mov  r1,#5

       str  r1,[r0]

     

       mrc p15,0,r1,c1,c0,0

       orr r1, r1,#0xc0000000

       mcr p15,0,r1,c1,c0,0

     

       mov r1,#CLK_CTL_BASE

       mov r2,#MDIV_405

       add r2,r2,#PSDIV_405

       str r2,[r1,#0x4]

    #else

     

        /* FCLK:HCLK:PCLK = 1:2:4 */

        /* default FCLK is 120 MHz ! */

        ldr r0, =CLKDIVN

        mov    r1, #3

        str r1, [r0]

    #endif     /* CONFIG_S3C2400 || CONFIG_S3C2410 *

    5、从FLASH拷贝到RAM

    #ifndef CONFIG_SKIP_RELOCATE_UBOOT

    relocate:                   /* relocate U-Boot to RAM      */

        adr r0, _start        /* r0 <- current position of code   *///adr是读取地址的伪指令,表示将_start标示的运行地址给r0

        ldr r1, _TEXT_BASE          /* test if we run from flash or RAM *///表示将_TEXT_BASE指向的地址中的数据拷贝到r1

        cmp     r0, r1                  /* don't reloc during debug         *///比较是否相同

        beq     stack_setup     //相同跳转出去

     

    /*****************不同则执行以下代码***********************/

        ldr r2, _armboot_start       //start起始地址,包含RO代码段+RW 数据段+ZI全局变量

        ldr r3, _bss_start          //全局变量的地址

        

        sub      r2, r3, r2        /* r2 <- size of armboot            *///相减之后得到的是代码段+数据段的总大小

        add     r2, r0 r2,        /* r2 <- source end address         *///r0是要烧录的内容,表示的是烧录的代码段+数据段的结束地址

     

    copy_loop:

        ldmia  r0!, {r3-r10}        /* copy from source address [r0]    *///ldmia批量的拷贝,向后拷贝32位到r3-r10(r0中的数据读出到r3-r10的,r0自动加一)

        stmia   r1!, {r3-r10}        /* copy to target address [r1] *///stmia批量的存储到r1上也就是目标运行的地址上(r3-r10中的数据保存到r1指向的地址上,r1自动加一)

        cmp    r0, r2              /* until source end addreee [r2]    *///r0烧录的起始地址,r2烧录的结束地址,相等则说明拷贝完成

        ble copy_loop

    #endif     /* CONFIG_SKIP_RELOCATE_UBOOT */

    6、设置建立堆栈;

    7、执行内存地址上的程序,该工作可以使ldr  pc来完成;

    start.su-boot启动所执行的第一个文件,它说做的是设置系统堆栈和cpu的工作方式,为进入c程序奠定基础。

    第二阶段:用c语言完成,以实现更复杂的命令

    1、          调用系统一系列的初始化函数;

    2、          初始化Flash设备;

    3、          初始化系统内存分配函数;

    4、          如果目标系统有NAND设备,则初始化NAND设备;

    5、          如果系统拥有显示设备,则初始化该类设备;

    6、          初始化相关网络设备,填写IPMAC地址等;

    7、          进去命令循环(即整个boot的工作循环),接收用户从串口输入的相关命令,然后进行相应的工作;


    最新回复(0)