飞凌嵌入式
直播中

陈召

10年用户 223经验值
擅长:接口/总线/驱动
私信 关注
[问答]

【OK210试用体验】uboot启动代码分析一

在链接脚本中可以看到系统上电之后运行start函数
SECtiONS
{
        . = 0x00000000;

        . = ALIGN(4);
        .text      :
        {
          cpu/s5pc11x/start.o        (.text)
          cpu/s5pc11x/s5pc110/cpu_init.o        (.text)
          board/samsung/smdkc110/lowlevel_init.o        (.text)
          cpu/s5pc11x/onenand_cp.o      (.text)                 
          cpu/s5pc11x/nand_cp.o (.text)                     
          cpu/s5pc11x/movi.o (.text)
          board/samsung/smdkc110/flash.o (.text)
          common/secure.o (.text)
          common/ace_sha1.o (.text)
          cpu/s5pc11x/pmic.o (.text)
          *(.text)
        }

        . = ALIGN(4);
        .rodata : { *(.rodata) }

        . = ALIGN(4);
        .data : { *(.data) }

        . = ALIGN(4);
        .got : { *(.got) }

        __u_boot_cmd_start = .;
        .u_boot_cmd : { *(.u_boot_cmd) }
        __u_boot_cmd_end = .;

        . = ALIGN(4);
        .mmudata : { *(.mmudata) }

        . = ALIGN(4);
        __bss_start = .;
        .bss : { *(.bss) }
        _end = .;

我们找到start函数,里面安装了异常向量表,那么系统上点之后自动执行_start函数,
.globl _start
_start: b        reset
        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
直接跳转到reset,这里面初始化了很多必要的寄存器。
reset:
        /*
         * set the cpu to SVC32 mode and IRQ & FIQ disable
         */
        @;mrs        r0,cpsr
        @;bic        r0,r0,#0x1f
        @;orr        r0,r0,#0xd3
        @;msr        cpsr,r0
        msr        cpsr_c, #0xd3                @ I & F disable, Mode: 0x13 - SVC


/*
*************************************************************************
*
* CPU_init_critical registers
*
* setup important registers
* setup memory timing
*
*************************************************************************
*/
         /*
         * we do sys-critical inits only at reboot,
         * not when booting from ram!
         */
cpu_init_crit:

#ifndef CONFIG_EVT1
#if 0       
        bl        v7_flush_dcache_all
#else
        bl        disable_l2cache

        mov        r0, #0x0        @
        mov        r1, #0x0        @ i       
        mov        r3, #0x0
        mov        r4, #0x0
lp1:
        mov        r2, #0x0        @ j
lp2:       
        mov        r3, r1, LSL #29                @ r3 = r1(i) <<29
        mov        r4, r2, LSL #6                @ r4 = r2(j) <<6
        orr        r4, r4, #0x2                @ r3 = (i<<29)|(j<<6)|(1<<1)
        orr        r3, r3, r4
        mov        r0, r3                        @ r0 = r3
        bl        CoInvalidateDCacheIndex
        add        r2, #0x1                @ r2(j)++
        cmp        r2, #1024                @ r2 < 1024
        bne        lp2                        @ jump to lp2
        add        r1, #0x1                @ r1(i)++
        cmp        r1, #8                        @ r1(i) < 8
        bne        lp1                        @ jump to lp1

        bl        set_l2cache_auxctrl
       
        bl        enable_l2cache
#endif
#endif
       
        bl        disable_l2cache

        bl        set_l2cache_auxctrl_cycle

        bl        enable_l2cache
       
       /*
        * Invalidate L1 I/D
        */
        mov        r0, #0                  @ set up for MCR
        mcr        p15, 0, r0, c8, c7, 0   @ invalidate TLBs
        mcr        p15, 0, r0, c7, c5, 0   @ invalidate icache

       /*
        * disable MMU stuff and caches
        */
        mrc        p15, 0, r0, c1, c0, 0
        bic        r0, r0, #0x00002000     @ clear bits 13 (--V-)
        bic        r0, r0, #0x00000007     @ clear bits 2:0 (-CAM)
        orr        r0, r0, #0x00000002     @ set bit 1 (--A-) Align
        orr        r0, r0, #0x00000800     @ set bit 12 (Z---) BTB
        mcr         p15, 0, r0, c1, c0, 0


        /* Read booting information */
        ldr        r0, =PRO_ID_BASE
        ldr        r1, [r0,#OMR_OFFSET]
        bic        r2, r1, #0xffffffc1

#ifdef CONFIG_VOGUES
        /* PS_HOLD(GPH0_0) set to output high */
        ldr        r0, =ELFIN_GPIO_BASE
        ldr        r1, =0x00000001
        str        r1, [r0, #GPH0CON_OFFSET]

        ldr        r1, =0x5500
        str        r1, [r0, #GPH0PUD_OFFSET]

        ldr        r1, =0x01
        str        r1, [r0, #GPH0DAT_OFFSET]
#endif

        /* NAND BOOT */
        cmp        r2, #0x0                @ 512B 4-cycle
        moveq        r3, #BOOT_NAND

        cmp        r2, #0x2                @ 2KB 5-cycle
        moveq        r3, #BOOT_NAND

        cmp        r2, #0x4                @ 4KB 5-cycle        8-bit ECC
        moveq        r3, #BOOT_NAND

        cmp        r2, #0x6                @ 4KB 5-cycle        16-bit ECC
        moveq        r3, #BOOT_NAND

        cmp        r2, #0x8                @ OneNAND Mux
        moveq        r3, #BOOT_ONENAND

        /* SD/MMC BOOT */
        cmp     r2, #0xc
        moveq   r3, #BOOT_MMCSD       

        /* NOR BOOT */
        cmp     r2, #0x14
        moveq   r3, #BOOT_NOR       

#if 0        /* Android C110 BSP uses OneNAND booting! */
        /* For second device booting */
        /* OneNAND BOOTONG failed */
        cmp     r2, #0x8
        moveq   r3, #BOOT_SEC_DEV
#endif

        /* Uart BOOTONG failed */
        cmp     r2, #(0x1<<4)
        moveq   r3, #BOOT_SEC_DEV
       
        ldr        r0, =INF_REG_BASE
        str        r3, [r0, #INF_REG3_OFFSET]     

        /*
         * Go setup Memory and board specific bits prior to relocation.
         */

        ldr        sp, =0xd0036000 /* end of sram dedicated to u-boot */
        sub        sp, sp, #12        /* set stack */
        mov        fp, #0
       
        bl        lowlevel_init        /* go setup pll,mux,memory */
执行到这里可以看到这行reset时执行了cpu_init_crit:这个函数里关闭了mmu和cache之后跳转到lowlevel_init,在这个函数里关闭了看门狗,初始化dram,设置了时钟,串口。
lowlevel_init:
        push        {lr}

        /* check reset status  */
       
        ldr        r0, =(ELFIN_CLOCK_POWER_BASE+RST_STAT_OFFSET)
        ldr        r1, [r0]
        bic        r1, r1, #0xfff6ffff
        cmp        r1, #0x10000
        beq        wakeup_reset_pre
        cmp        r1, #0x80000
        beq        wakeup_reset_from_didle

        /* IO Retention release */
        ldr        r0, =(ELFIN_CLOCK_POWER_BASE + OTHERS_OFFSET)
        ldr        r1, [r0]
        ldr        r2, =IO_RET_REL
        orr        r1, r1, r2
        str        r1, [r0]

        /* Disable Watchdog */
        ldr        r0, =ELFIN_WATCHDOG_BASE        /* 0xE2700000 */
        mov        r1, #0
        str        r1, [r0]

        /* SRAM(2MB) init for SMDKC110 */
        /* GPJ1 SROM_ADDR_16to21 */
        ldr        r0, =ELFIN_GPIO_BASE
       
        ldr        r1, [r0, #GPJ1CON_OFFSET]
        bic        r1, r1, #0xFFFFFF
        ldr        r2, =0x444444
        orr        r1, r1, r2
        str        r1, [r0, #GPJ1CON_OFFSET]

        ldr        r1, [r0, #GPJ1PUD_OFFSET]
        ldr        r2, =0x3ff
        bic        r1, r1, r2
        str        r1, [r0, #GPJ1PUD_OFFSET]

        /* GPJ4 SROM_ADDR_16to21 */
        ldr        r1, [r0, #GPJ4CON_OFFSET]
        bic        r1, r1, #(0xf<<16)
        ldr        r2, =(0x4<<16)
        orr        r1, r1, r2
        str        r1, [r0, #GPJ4CON_OFFSET]

        ldr        r1, [r0, #GPJ4PUD_OFFSET]
        ldr        r2, =(0x3<<8)
        bic        r1, r1, r2
        str        r1, [r0, #GPJ4PUD_OFFSET]


        /* CS0 - 16bit sram, enable nBE, Byte base address */
        ldr        r0, =ELFIN_SROM_BASE        /* 0xE8000000 */
        mov        r1, #0x1
        str        r1, [r0]

        /* PS_HOLD pin(GPH0_0) set to high */
        ldr        r0, =(ELFIN_CLOCK_POWER_BASE + PS_HOLD_CONTROL_OFFSET)
        ldr        r1, [r0]
        orr        r1, r1, #0x300       
        orr        r1, r1, #0x1       
        str        r1, [r0]

        /* when we already run in ram, we don't need to relocate U-Boot.
         * and actually, memory controller must be configured before U-Boot
         * is running in ram.
         */
        ldr        r0, =0xff000fff
        bic        r1, pc, r0                /* r0 <- current base addr of code */
        ldr        r2, _TEXT_BASE                /* r1 <- original base addr in ram */
        bic        r2, r2, r0                /* r0 <- current base addr of code */
        cmp     r1, r2                  /* compare r0, r1                  */
        beq     1f                        /* r0 == r1 then skip sdram init   */

        /* init PMIC chip */
        /*bl PMIC_InitIp*/

        /* init system clock */
        bl system_clock_init

        /* Memory initialize */
        bl mem_ctrl_asm_init
       
1:
        /* for UART */
        bl uart_asm_init

        bl tzpc_init

#if defined(CONFIG_ONENAND)
        bl onenandcon_init
#endif

#if defined(CONFIG_NAND)
        /* simple init for NAND */
        bl nand_asm_init
#endif

        /* check reset status  */
       
        ldr        r0, =(ELFIN_CLOCK_POWER_BASE+RST_STAT_OFFSET)
        ldr        r1, [r0]
        bic        r1, r1, #0xfffeffff
        cmp        r1, #0x10000
        beq        wakeup_reset_pre

        /* ABB disable */
        ldr        r0, =0xE010C300
        orr        r1, r1, #(0x1<<23)
        str        r1, [r0]

        /* Print 'K' */
        ldr        r0, =ELFIN_UART_CONSOLE_BASE
        ldr        r1, =0x4b4b4b4b
        str        r1, [r0, #UTXH_OFFSET]

        pop        {pc}
pc出栈后,继续执行前面函数,首先要判断运行地址和链接地址是否相等,不等进行重定位
ldr        r0, =0xE010E81C  /* PS_HOLD_CONTROL register */
        ldr        r1, =0x00005301         /* PS_HOLD output high        */
        str        r1, [r0]

        /* get ready to call C functions */
        ldr        sp, _TEXT_PHY_BASE        /* setup temp stack pointer */
        sub        sp, sp, #12
        mov        fp, #0                        /* no previous frame, so fp=0 */

        /* when we already run in ram, we don't need to relocate U-Boot.
         * and actually, memory controller must be configured before U-Boot
         * is running in ram.
         */
        ldr        r0, =0xff000fff
        bic        r1, pc, r0                /* r0 <- current base addr of code */
        ldr        r2, _TEXT_BASE                /* r1 <- original base addr in ram */
        bic        r2, r2, r0                /* r0 <- current base addr of code */
        cmp     r1, r2                  /* compare r0, r1                  */
        beq     after_copy                /* r0 == r1 then skip flash copy   */
下面将nandFlash的代码复制到ram里
nand_boot:
        mov        r0, #0x1000
        bl        copy_from_nand
        b        after_copy
然后跳转到after_copy地址去执行。。。
接下来请看uboot分析二

更多回帖

发帖
×
20
完善资料,
赚取积分