zoukankan      html  css  js  c++  java
  • UBoot启动流程

    1. UBoot启动流程可以分为两个阶段:

    (1)第一阶段

    ① 硬件设备初始化

    ② 加载UBoot第二阶段代码到RAM空间

    ③ 设置好栈

    ④ 跳转到第二阶段代码入口

    (2)第二阶段

    ① 初始化本阶段使用的硬件设备

    ② 检测系统内存映射

    ③ 将内核从Flash读取到RAM中

    ④ 为内核设置启动参数

    ⑤ 调用内核

    2. UBoot启动第一阶段

    根据链接器脚本cpu/arm920t/u-boot.lds中指定的链接方式,可以看出,u-boot代码段的第一个链接的是cpu/arm920t/start.o,入口标号是_start,因此u-boot的入口代码在对应源文件cpu/arm920t/start.S中

    (1)设置异常向量表:

    .globl _start
    _start:    b    start_code
        ldr    pc, _undefined_instruction
        ldr    pc, _software_interrupt
        ldr    pc, _prefetch_abort
        ldr    pc, _data_abort
        ldr    pc, _not_used
        ldr    pc, _irq
        ldr    pc, _fiq
    
    _undefined_instruction:    .word undefined_instruction
    _software_interrupt:    .word software_interrupt
    _prefetch_abort:    .word prefetch_abort
    _data_abort:        .word data_abort
    _not_used:        .word not_used
    _irq:            .word irq
    _fiq:            .word fiq
    
        .balignl 16,0xdeadbeef

    (2)CPU进入SVC模式

        /*
         * set the cpu to SVC32 mode
         */
        mrs    r0, cpsr
        bic    r0, r0, #0x1f
        orr    r0, r0, #0xd3
        msr    cpsr, r0

    (3)关闭MMU和Cache

    /*
         * flush v4 I/D caches
         */
        mov    r0, #0
        mcr    p15, 0, r0, c7, c7, 0    /* flush v3/v4 cache */
        mcr    p15, 0, r0, c8, c7, 0    /* flush v4 TLB */
    
        /*
         * disable MMU stuff and caches
         */
        mrc    p15, 0, r0, c1, c0, 0
        bic    r0, r0, #0x00002300    @ clear bits 13, 9:8 (--V- --RS)
        bic    r0, r0, #0x00000087    @ clear bits 7, 2:0 (B--- -CAM)
        orr    r0, r0, #0x00000002    @ set bit 2 (A) Align
        orr    r0, r0, #0x00001000    @ set bit 12 (I) I-Cache
        mcr    p15, 0, r0, c1, c0, 0

    (4)关闭看门狗

        /* 
         *turn off the watchdog 
         */
    #define pWTCON    0x53000000
    #define INTMSK    0x4A000008    /* Interupt-Controller base addresses */
    #define INTSUBMSK    0x4A00001C
        ldr    r0, =pWTCON
        mov    r1, #0x0
        str    r1, [r0]

    (5)屏蔽中断

        /*
         * mask all IRQs by setting all bits in the INTMR - default
         */
        mov    r1, #0xffffffff
        ldr    r0, =INTMSK
        str    r1, [r0]
        
        ldr    r1, =0x7fff
        ldr    r0, =INTSUBMSK
        str    r1, [r0]

    (6)设置MPLLCON、UPLLCON、CLKDIVN

    #define CLKDIVN            0x4C000014        /* Clock divisor register */
    #define CLK_CTL_BASE     0x4C000000
    #define MDIV_405         (0x7f << 12)    /* Default FCLK is 405 MHz! */
    #define PSDIV_405         0x21
    #define MDIV MDIV_405
    #define PSDIV PSDIV_405
    #define CLKDIV             0x05            /* FCLK:HCLK:PCLK = 1:4:8 */
        
        ldr    r0, =CLKDIVN
        mov    r1, #CLKDIV
        str    r1, [r0]
    
        /* Set arm920t to Asynchronous Clock Mode (405 MHz)*/
        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
        add r2, r2, #PSDIV
        str r2, [r1, #0x04]        /* MPLLCON */

    (7)Nand初始化(Nand启动)

    ldr r0, =S3C2440_NAND_BASE
        ldr r1, =0x001210
        str r1, [r0, #NFCONF_OFFSET]
        
        mov r1, #0x03
        str r1, [r0, #NFCONT_OFFSET]
        
        mov pc, lr

    (8)存储控制器初始化(Memeory)

    /* memory control configuration */
        /* make r0 relative the current location so that it */
        /* reads SMRDATA out of FLASH rather than memory ! */
        ldr     r0, =SMRDATA
        ldr    r1, _TEXT_BASE
        sub    r0, r0, r1
        ldr    r1, =BWSCON    /* Bus Width Status Controller */
        add     r2, r0, #13*4
    0:
        ldr     r3, [r0], #4
        str     r3, [r1], #4
        cmp     r2, r0
        bne     0b
    
        mov    pc, lr
    
        .ltorg
    /* the literal pools origin */
    
    SMRDATA:
        .word (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28))
        .word ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))
        .word ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC))
        .word ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC))
        .word ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC))
        .word ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC))
        .word ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC))
        .word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))
        .word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))
        .word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)
        .word 0x32
        .word 0x30
        .word 0x30

    (9)复制u-boot第二阶段的代码到RAM

    relocate:                /* relocate U-Boot to RAM        */
        adr    r0, _start        /* r0 <- current position of code   */
        ldr    r1, _TEXT_BASE        /* test if we run from flash or RAM */
        cmp    r0, r1            /* don't reloc during debug         */
        beq    stack_setup
        
        mov r2, #0
        str r2, [r2]
        ldr r2, [r2]
        cmp r2, #0
        bne copy_to_ram_from_nor
    
        mov sp, #0x1000
        bl copy_to_ram_from_nand
        b stack_setup
        
    copy_to_ram_from_nor:    
        ldr    r2, _armboot_start
        ldr    r3, _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 addreee [r2]    */
        ble    copy_loop

    (10)设置栈

    stack_setup:
        ldr    r0, _TEXT_BASE        /* upper 128 KiB: relocated uboot   */
        sub    r0, r0, #CONFIG_SYS_MALLOC_LEN    /* malloc area              */
        sub    r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo                 */

    (11)清除BSS段

    clear_bss:
        ldr    r0, _bss_start        /* find start of bss segment        */
        ldr    r1, _bss_end        /* stop here                        */
        mov    r2, #0x00000000        /* clear                            */
    
    clbss_l:str    r2, [r0]        /* clear loop...                    */
        add    r0, r0, #4
        cmp    r0, r1
        ble    clbss_l

    (12)跳转到第二阶段代码入口

    ldr    pc, _start_armboot

    (13)UBoot内存分配图

    3. UBoot启动第二阶段

    (1)gd_t结构体:存储全局数据区的数据

    typedef    struct    global_data {
        bd_t        *bd;
        unsigned long    flags;
        unsigned long    baudrate;
        unsigned long    have_console;    /* serial_init() was called */
        unsigned long    env_addr;    /* Address  of Environment struct */
        unsigned long    env_valid;    /* Checksum of Environment valid? */
        unsigned long    fb_base;    /* base address of frame buffer */
    #ifdef CONFIG_VFD
        unsigned char    vfd_type;    /* display type */
    #endif
    #ifdef CONFIG_FSL_ESDHC
        unsigned long    sdhc_clk;
    #endif
    #if 0
        unsigned long    cpu_clk;    /* CPU clock in Hz!        */
        unsigned long    bus_clk;
        phys_size_t    ram_size;    /* RAM size */
        unsigned long    reset_status;    /* reset status register at boot */
    #endif
        void        **jt;        /* jump table */
    } gd_t;

    ① u-boot使用了一个存储在寄存器中的指针gd来记录全局数据区的地址(指针存放在寄存器r8中)

    #define DECLARE_GLOBAL_DATA_PTR     register volatile gd_t *gd asm ("r8")

    ② 根据u-boot内存分布图,可以计算gd的值

    gd = TEXT_BASE - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t)

    与start_armboot()函数中的计算方法一致

    gd = (gd_t*)(_armboot_start - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t));

    (2)bd_t结构:存放板级相关的全局数据

    typedef struct bd_info {
        int            bi_baudrate;    /* serial console baudrate */
        unsigned long    bi_ip_addr;    /* IP Address */
        struct environment_s           *bi_env;
        ulong            bi_arch_number;    /* unique id for this board */
        ulong            bi_boot_params;    /* where this board expects params */
        struct                /* RAM configuration */
        {
        ulong start;
        ulong size;
        }            bi_dram[CONFIG_NR_DRAM_BANKS];
    } bd_t;

    (3)init_sequence数组

    ① u-boot使用一个数组init_sequence来存储大多数开发板都要执行的初始化函数的函数指针

    init_fnc_t *init_sequence[] = {
    
        board_init,        /* basic board dependent setup */
    
        timer_init,        /* initialize timer */
        env_init,        /* initialize environment */
        init_baudrate,        /* initialze baudrate settings */
        serial_init,        /* serial communications setup */
        console_init_f,        /* stage 1 init of console */
        display_banner,        /* say that we are here */
    
        dram_init,        /* configure available RAM banks */
    
        display_dram_config,
        NULL,
    };

    ② board_init函数配置了MPLLCON、UPLLCON和部分GPIO寄存器的值,还设置了u-boot的机器码和内核启动参数地址

    gd->bd->bi_arch_number = MACH_TYPE_MINI2440 ;
    gd->bd->bi_boot_params = 0x30000100;

    ③ dram_init函数

    int dram_init (void)
    {
        gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
        gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
    
        return 0;
    }

    (4)start_armboot()顺序分析

    void start_armboot (void)
    {
        init_fnc_t **init_fnc_ptr;
        char *s;
        ...
        /* Pointer is writable since we allocated a register for it */
        gd = (gd_t*)(_armboot_start - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t));
        /* compiler optimization barrier needed for GCC >= 3.4 */
        __asm__ __volatile__("": : :"memory");
    
        memset ((void*)gd, 0, sizeof (gd_t));
        gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));
        memset (gd->bd, 0, sizeof (bd_t));
    
        gd->flags |= GD_FLG_RELOC;
    
        monitor_flash_len = _bss_start - _armboot_start;
    
        for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
            if ((*init_fnc_ptr)() != 0) {
                hang ();
            }
        }
    
        /* armboot_start is defined in the board-specific linker script */
        mem_malloc_init (_armboot_start - CONFIG_SYS_MALLOC_LEN,
                CONFIG_SYS_MALLOC_LEN);
    
    #ifndef CONFIG_SYS_NO_FLASH
        /* configure available FLASH banks */
        display_flash_config (flash_init ());
    #endif /* CONFIG_SYS_NO_FLASH */
        ...
    #if defined(CONFIG_CMD_NAND)
        puts ("NAND:  ");
        nand_init();        /* go init the NAND */
    #endif
        ...
        /* initialize environment */
        env_relocate ();
        ...
        /* IP Address */
        gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");
    
        stdio_init ();    /* get the devices list going. */
    
        jumptable_init ();
        ...
        console_init_r ();    /* fully init console as a device */
        ...
        /* enable exceptions */
        enable_interrupts ();
        ...
    #if defined(CONFIG_CMD_NET)
    #if defined(CONFIG_NET_MULTI)
        puts ("Net:   ");
    #endif
        eth_initialize(gd->bd);
    #if defined(CONFIG_RESET_PHY_R)
        debug ("Reset Ethernet PHY
    ");
        reset_phy();
    #endif
    #endif
        ...
        /* main_loop() can return to retry autoboot, if so just run it again. */
        for (;;) {
            main_loop ();
        }
    
        /* NOTREACHED - no way out of command loop except booting */
    }

    (5)main_loop函数分析

    ① 设置启动次数有关参数

    ② 启动Modem功能

    ③ 设置版本号、初始化命令自动完成功能

    ④ 启动延时和启动菜单

    ⑤ 执行命令循环

  • 相关阅读:
    VS2015使用scanf报错解决方案
    C++的标准模板库(STL)简介
    C++中常用特殊符号简介(& , * , : , :: , ->)
    C++中#include <xxx.h>和#include "xxx.h"的区别(尖括号和双引号的区别)
    C++中#include的工作原理
    opencv中Mat与IplImage,CVMat类型之间转换
    C++数据类型简析
    让你在DOS中任意切换目录
    七种Prolog解释器/编译器
    C++中引用(&)的用法和应用实例
  • 原文地址:https://www.cnblogs.com/wulei0630/p/10635669.html
Copyright © 2011-2022 走看看