arm9_u-boot-2012.4.1分析

u-boot启动方式:

1.设置CPU为管理者模式

start_code:
    /*
     * set the cpu to SVC32 mode
     */
    mrs    r0, cpsr
    bic    r0, r0, #0x1f
    orr    r0, r0, #0xd3
    msr    cpsr, r0
知识兔

2.关看门狗,关中断, 设置时钟频率

0x53000000
#  define INTMSK    0x4A000008    /* Interrupt-Controller base addresses */
#  define INTSUBMSK    0x4A00001C
#  define CLKDIVN    0x4C000014    /* clock divisor register */
# endif

    ldr    r0, =pWTCON
    mov    r1, #0x0
    str    r1, [r0]

    /*
     * mask all IRQs by setting all bits in the INTMR - default
     */
    mov    r1, #0xffffffff
    ldr    r0, =INTMSK
    str    r1, [r0]
# if defined(CONFIG_S3C2410)
    ldr    r1, =0x3ff
    ldr    r0, =INTSUBMSK
    str    r1, [r0]
# endif

    /* FCLK:HCLK:PCLK = 1:2:4 */
    /* default FCLK is 120 MHz ! */
    ldr    r0, =CLKDIVN
    mov    r1, #3
    str    r1, [r0]
#endif    /* CONFIG_S3C24X0 */
知识兔

3.关MMU,初始各个bank

 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
       bl    cpu_init_crit 
知识兔
cpu_init_crit:
    /*
     * 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

    /*
     * before relocating, we have to setup RAM timing
     * because memory timing is board-dependend, you will
     * find a lowlevel_init.S in your board directory.
     */
    mov    ip, lr

    bl    lowlevel_init

    mov    lr, ip
    mov    pc, lr
#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
知识兔
lowlevel_init:
    /* 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

    /* everything is fine now */
    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
知识兔
知识兔
 

4.进入board_init_f()函数 (初始化定时器,GPIO,串口等,划分内存区域: 清空gd指向的结构体、通过init_sequence函数数组,来初始化各个函数以及逐步填充gd结构体,最后划分内存区域,将数据保存在gd里,然后调用relocate_code()对uboot重定位,gd是用来传递给内核的参数)

call_board_init_f:       ldr   sp, =(CONFIG_SYS_INIT_SP_ADDR) //CONFIG_SYS_INIT_SP_ADDR=0x30000f80       bic   sp, sp, #7         //sp=0x30000f80       ldr   r0,=0x00000000       bl    board_init_f 

反汇编:arm-linux-objdump -D u-boot>u-boot.dis

00000098 <call_board_init_f>:      98:    e59fd3d8     ldr    sp, [pc, #984]    ; 478 <fiq+0x58>
.......
     478: 30000f80 .word 0x30000f80
void board_init_f(ulong bootflag){    bd_t *bd;    init_fnc_t **init_fnc_ptr;    gd_t *id;    ulong addr, addr_sp;#ifdef CONFIG_PRAM    ulong reg;#endif    bootstage_mark_name(BOOTSTAGE_ID_START_UBOOT_F, "board_init_f");    /* Pointer is writable since we allocated a register for it */    gd = (gd_t *) ((CONFIG_SYS_INIT_SP_ADDR) & ~0x07);    /* compiler optimization barrier needed for GCC >= 3.4 */    __asm__ __volatile__("": : :"memory");    memset((void *)gd, 0, sizeof(gd_t));    gd->mon_len = _bss_end_ofs;#ifdef CONFIG_OF_EMBED    /* Get a pointer to the FDT */    gd->fdt_blob = _binary_dt_dtb_start;#elif defined CONFIG_OF_SEPARATE    /* FDT is at end of image */    gd->fdt_blob = (void *)(_end_ofs + _TEXT_BASE);#endif    /* Allow the early environment to override the fdt address */    gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", 16,                        (uintptr_t)gd->fdt_blob);    for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {        if ((*init_fnc_ptr)() != 0) {            hang ();        }    }#ifdef CONFIG_OF_CONTROL    /* For now, put this check after the console is ready */    if (fdtdec_prepare_fdt()) {        panic("** CONFIG_OF_CONTROL defined but no FDT - please see "            "doc/README.fdt-control");    }#endif    debug("monitor len: %08lX\n", gd->mon_len);    /*     * Ram is setup, size stored in gd !!     */    debug("ramsize: %08lX\n", gd->ram_size);#if defined(CONFIG_SYS_MEM_TOP_HIDE)    /*     * Subtract specified amount of memory to hide so that it won't     * get "touched" at all by U-Boot. By fixing up gd->ram_size     * the Linux kernel should now get passed the now "corrected"     * memory size and won't touch it either. This should work     * for arch/ppc and arch/powerpc. Only Linux board ports in     * arch/powerpc with bootwrapper support, that recalculate the     * memory size from the SDRAM controller setup will have to     * get fixed.     */    gd->ram_size -= CONFIG_SYS_MEM_TOP_HIDE;#endif    addr = CONFIG_SYS_SDRAM_BASE + gd->ram_size;#ifdef CONFIG_LOGBUFFER#ifndef CONFIG_ALT_LB_ADDR    /* reserve kernel log buffer */    addr -= (LOGBUFF_RESERVE);    debug("Reserving %dk for kernel logbuffer at %08lx\n", LOGBUFF_LEN,        addr);#endif#endif#ifdef CONFIG_PRAM    /*     * reserve protected RAM     */    reg = getenv_ulong("pram", 10, CONFIG_PRAM);    addr -= (reg << 10);        /* size is in kB */    debug("Reserving %ldk for protected RAM at %08lx\n", reg, addr);#endif /* CONFIG_PRAM */#if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF))    /* reserve TLB table */    addr -= (4096 * 4);    /* round down to next 64 kB limit */    addr &= ~(0x10000 - 1);    gd->tlb_addr = addr;    debug("TLB table at: %08lx\n", addr);#endif    /* round down to next 4 kB limit */    addr &= ~(4096 - 1);    debug("Top of RAM usable for U-Boot at: %08lx\n", addr);#ifdef CONFIG_LCD#ifdef CONFIG_FB_ADDR    gd->fb_base = CONFIG_FB_ADDR;#else    /* reserve memory for LCD display (always full pages) */    addr = lcd_setmem(addr);    gd->fb_base = addr;#endif /* CONFIG_FB_ADDR */#endif /* CONFIG_LCD */    /*     * reserve memory for U-Boot code, data & bss     * round down to next 4 kB limit     */    addr -= gd->mon_len;    addr &= ~(4096 - 1);    debug("Reserving %ldk for U-Boot at: %08lx\n", gd->mon_len >> 10, addr);#ifndef CONFIG_SPL_BUILD    /*     * reserve memory for malloc() arena     */    addr_sp = addr - TOTAL_MALLOC_LEN;    debug("Reserving %dk for malloc() at: %08lx\n",            TOTAL_MALLOC_LEN >> 10, addr_sp);    /*     * (permanently) allocate a Board Info struct     * and a permanent copy of the "global" data     */    addr_sp -= sizeof (bd_t);    bd = (bd_t *) addr_sp;    gd->bd = bd;    debug("Reserving %zu Bytes for Board Info at: %08lx\n",            sizeof (bd_t), addr_sp);#ifdef CONFIG_MACH_TYPE    gd->bd->bi_arch_number = CONFIG_MACH_TYPE; /* board id for Linux */#endif    addr_sp -= sizeof (gd_t);    id = (gd_t *) addr_sp;    debug("Reserving %zu Bytes for Global Data at: %08lx\n",            sizeof (gd_t), addr_sp);    /* setup stackpointer for exeptions */    gd->irq_sp = addr_sp;#ifdef CONFIG_USE_IRQ    addr_sp -= (CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ);    debug("Reserving %zu Bytes for IRQ stack at: %08lx\n",        CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ, addr_sp);#endif    /* leave 3 words for abort-stack    */    addr_sp -= 12;    /* 8-byte alignment for ABI compliance */    addr_sp &= ~0x07;#else    addr_sp += 128;    /* leave 32 words for abort-stack   */    gd->irq_sp = addr_sp;#endif    debug("New Stack Pointer is: %08lx\n", addr_sp);#ifdef CONFIG_POST    post_bootmode_init();    post_run(NULL, POST_ROM | post_bootmode_get(0));#endif    gd->bd->bi_baudrate = gd->baudrate;    /* Ram ist board specific, so move it to board code ... */    dram_init_banksize();    display_dram_config();    /* and display it */    gd->relocaddr = addr;    gd->start_addr_sp = addr_sp;    gd->reloc_off = addr - _TEXT_BASE;    debug("relocation Offset is: %08lx\n", gd->reloc_off);    memcpy(id, (void *)gd, sizeof(gd_t));    relocate_code(addr_sp, id, addr);    /* NOTREACHED - relocate_code() does not return */}
init_fnc_t *init_sequence[] = {#if defined(CONFIG_ARCH_CPU_INIT)    arch_cpu_init,        /* basic arch cpu dependent setup */#endif#if defined(CONFIG_BOARD_EARLY_INIT_F)    board_early_init_f,#endif#ifdef CONFIG_OF_CONTROL    fdtdec_check_fdt,#endif    timer_init,        /* initialize timer */#ifdef CONFIG_FSL_ESDHC    get_clocks,#endif    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 */#if defined(CONFIG_DISPLAY_CPUINFO)    print_cpuinfo,        /* display cpu info (and speed) */#endif#if defined(CONFIG_DISPLAY_BOARDINFO)    checkboard,        /* display board info */#endif#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)    init_func_i2c,#endif    dram_init,        /* configure available RAM banks */    NULL,};

5.重定位     (复制uboot,然后修改SDRAM上的uboot链接地址)

copy_loop:    ldmia    r0!, {r9-r10}        /* copy from source address [r0]    */    stmia    r1!, {r9-r10}        /* copy to   target address [r1]    */    cmp    r0, r2            /* until source end address [r2]    */    blo    copy_loop#ifndef CONFIG_SPL_BUILD    /*     * fix .rel.dyn relocations     */    ldr    r0, _TEXT_BASE        /* r0 <- Text base */    sub    r9, r6, r0        /* r9 <- relocation offset */    ldr    r10, _dynsym_start_ofs    /* r10 <- sym table ofs */    add    r10, r10, r0        /* r10 <- sym table in FLASH */    ldr    r2, _rel_dyn_start_ofs    /* r2 <- rel dyn start ofs */    add    r2, r2, r0        /* r2 <- rel dyn start in FLASH */    ldr    r3, _rel_dyn_end_ofs    /* r3 <- rel dyn end ofs */    add    r3, r3, r0        /* r3 <- rel dyn end in FLASH */fixloop:    ldr    r0, [r2]        /* r0 <- location to fix up, IN FLASH! */    add    r0, r0, r9        /* r0 <- location to fix up in RAM */    ldr    r1, [r2, #4]    and    r7, r1, #0xff    cmp    r7, #23            /* relative fixup? */    beq    fixrel    cmp    r7, #2            /* absolute fixup? */    beq    fixabs    /* ignore unknown type of fixup */    b    fixnextfixabs:    /* absolute fix: set location to (offset) symbol value */    mov    r1, r1, LSR #4        /* r1 <- symbol index in .dynsym */    add    r1, r10, r1        /* r1 <- address of symbol in table */    ldr    r1, [r1, #4]        /* r1 <- symbol value */    add    r1, r1, r9        /* r1 <- relocated sym addr */    b    fixnextfixrel:    /* relative fix: increase location by offset */    ldr    r1, [r0]    add    r1, r1, r9fixnext:    str    r1, [r0]    add    r2, r2, #8        /* each rel.dyn entry is 8 bytes */    cmp    r2, r3    blo    fixloop#endif

6.清bss

clear_bss:#ifndef CONFIG_SPL_BUILD    ldr    r0, _bss_start_ofs    ldr    r1, _bss_end_ofs    mov    r4, r6            /* reloc addr */    add    r0, r0, r4    add    r1, r1, r4    mov    r2, #0x00000000        /* clear                */clbss_l:str    r2, [r0]        /* clear loop...            */    add    r0, r0, #4    cmp    r0, r1    bne    clbss_l    bl coloured_LED_init    bl red_led_on#endif

7. 跳转到board_init_r()函数,启动流程结束

ldr    r0, _board_init_r_ofs    adr    r1, _start    add    lr, r0, r1    add    lr, lr, r9    /* setup parameters for board_init_r */    mov    r0, r5        /* gd_t */    mov    r1, r6        /* dest_addr */    /* jump to it ... */    mov    pc, lr_board_init_r_ofs:    .word board_init_r - _start

void board_init_r(gd_t *id, ulong dest_addr)
{

//硬件初始化...
.........
for (;;) { main_loop(); }.........

}
计算机