U-Boot深入分析——启动部分


针对s3c2440部分进行分析。
启动分为两个部分,第一部分完成主要功能:
硬件设备、栈指针的初始化、将第二阶段代码复制到ram中。
第二部分主要功能:
检测内存映射,为内核设置启动参数,从flash读取内核到ram,读取ram。

下面分别对两部分进行分析:

第一部分主要文件是start.S和lowlevel_init.S

入口start.S:


.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 /*填充内存,使其满足16字节对齐*/


1,start_code步骤分析:

首先将cpu工作状态置于超级用户模式:

start_code:
    /*
     * set the cpu to SVC32 mode
     */

   

    mrs    r0,cpsr
    bic    r0,r0,#0x1f
    orr    r0,r0,#0xd3
    msr    cpsr,r0

    bl coloured_LED_init
    bl red_LED_on


关闭WatchDog,设置中断屏蔽以及系统时钟

#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)
    /* 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

    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_S3C2400 || CONFIG_S3C2410 */




重置u-boot的代码位置,首先检测当前位置与运行地址(_TEXT_BASE)是否相同,同则转至下步,否则将代码段复制到运行地址:

#ifndef CONFIG_SKIP_RELOCATE_UBOOT
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

    beq stack_setup

    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
#endif    /* CONFIG_SKIP_RELOCATE_UBOOT */
#endif


设置堆栈指针,bss段清零,跳转到第二阶段代码:

    /* Set up the stack                         */
stack_setup:
    ldr    r0, _TEXT_BASE        /* upper 128 KiB: relocated uboot */
    sub    r0, r0, #CFG_MALLOC_LEN    /* malloc area */
    sub    r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */
#ifdef CONFIG_USE_IRQ
    sub    r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
    sub    sp, r0, #12        /* leave 3 words for abort-stack */

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

    ldr    pc, _start_armboot

_start_armboot:    .word start_armboot


2,cpu寄存器初始化过程分析:

清除指令、数据cache:

    mov    r0, #0
    mcr    p15, 0, r0, c7, c7, 0    /* flush v3/v4 cache */
    mcr    p15, 0, r0, c8, c7, 0    /* flush v4 TLB */


禁用mmu和cache,跳转到开发板相关的lowlevel_init函数:

#ifndef CONFIG_SKIP_LOWLEVEL_INIT
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
#if    defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK) || defined(CONFIG_AT91RM9200DF)

#else
    bl    lowlevel_init
#endif
    mov    lr, ip
    mov    pc, lr
#endif /* CONFIG_SKIP_LOWLEVEL_INIT */


3,lowlevel_init函数分析:

_TEXT_BASE:
    .word    TEXT_BASE

.globl 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   /*r0=13个存储控制寄存器在flash 上的开放地址*/
    ldr    r1, =BWSCON    /* Bus Width Status Controller */
    add r2, r0, #13*4 /*r2=结束地址*/
0:
    ldr r3, [r0], #4
    str r3, [r1], #4
    cmp r2, r0
    bne 0b        /*将寄存器的值依次复制到代码段上*/

    /* everything is fine now */
    mov    pc, lr

   

    .ltorg   /*ldr使用的数据缓冲池*/
/* the literal pools origin */


13个寄存器的值:



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 0x30A



第一阶段启动分析完成。

相关内容