zoukankan      html  css  js  c++  java
  • uboot——start.S

    uboot中start.S文件详解

    1:第一段代码

    #include <config.h>
    #include <version.h>
    #if defined(CONFIG_ENABLE_MMU)
    #include <asm/proc/domain.h>
    #endif
    #include <regs.h>
    
    #ifndef CONFIG_ENABLE_MMU
    #ifndef CFG_PHY_UBOOT_BASE
    #define CFG_PHY_UBOOT_BASE    CFG_UBOOT_BASE
    #endif
    #endif

    头文件包含config.h在mkconfig脚本中生成,内容为#include <configs/x210.h>

    头文件包含version.h文件中的内容是#include "version_autogenerated.h"

    version_autogenerated.h文件是在主Makefile中自动生成的

    生成代码为

    $(VERSION_FILE):
            @( printf '#define U_BOOT_VERSION "U-Boot %s%s"
    ' "$(U_BOOT_VERSION)" 
             '$(shell $(CONFIG_SHELL) $(TOPDIR)/tools/setlocalversion $(TOPDIR))' 
             ) > $@.tmp
            @cmp -s $@ $@.tmp && rm -f $@.tmp || mv -f $@.tmp $@

    生成的内容为

    #define U_BOOT_VERSION "U-Boot 1.3.4"

    包含regs.h:regs.h在之前makefile中分析过来 连接的s5pc110.h
    因为定义了CONFIG_ENABLE_MMU所以包含asm/proc/domain.h
    同样asm、proc也是符号连接实际文件为:includeasm-armproc-armdomain.h文件


    2:第二段代码:
    #if defined(CONFIG_EVT1) && !defined(CONFIG_FUSED)
        .word 0x2000
        .word 0x0
        .word 0x0
        .word 0x0
    #endif
    
    

    因为if语句成立,所以定义了4字,值为0x2000、0x0、0x0、0x0 .word是arm汇编的伪指令:含义是当前地址的值为XX,

    XX的内容一般为数值或者地址;

    如:.word 0x2000表示当前地址的值为0x2000;

      .word _start 表示当前地址的值为_start函数

    
    

    3:第三段代码

     1 .globl _start
     2 _start: b    reset
     3     ldr    pc, _undefined_instruction
     4     ldr    pc, _software_interrupt
     5     ldr    pc, _prefetch_abort
     6     ldr    pc, _data_abort
     7     ldr    pc, _not_used
     8     ldr    pc, _irq
     9     ldr    pc, _fiq
    10 
    11 _undefined_instruction:
    12     .word undefined_instruction
    13 _software_interrupt:
    14     .word software_interrupt
    15 _prefetch_abort:
    16     .word prefetch_abort
    17 _data_abort:
    18     .word data_abort
    19 _not_used:
    20     .word not_used
    21 _irq:
    22     .word irq
    23 _fiq:
    24     .word fiq
    25 _pad:
    26     .word 0x12345678 /* now 16*4=64 */
    27 .global _end_vect
    28 _end_vect:
    29 
    30     .balignl 16,0xdeadbeef

    这段代码的作用是建立异常向量表;

    比如说uboot在sd卡中,先复制前16K到0xD0020010地址处,建立异常向量表的位置也应该在这个位置,初始化内存以后把整个uboot复制到内存中以后,异常向量表应该在内存的地址处0x23e00000处,

     所以说这个异常向量表应该只是虚有其表,实际上是没有什么用的;(注:个人理解可能有误);

     1 _TEXT_BASE:
     2     .word    TEXT_BASE
     3 
     4 /*
     5  * Below variable is very important because we use MMU in U-Boot.
     6  * Without it, we cannot run code correctly before MMU is ON.
     7  * by scsuh.
     8  */
     9 _TEXT_PHY_BASE:
    10     .word    CFG_PHY_UBOOT_BASE
    11 
    12 .globl _armboot_start
    13 _armboot_start:
    14     .word _start
    15 
    16 /*
    17  * These are defined in the board-specific linker script.
    18  */
    19 .globl _bss_start
    20 _bss_start:
    21     .word __bss_start
    22 
    23 .globl _bss_end
    24 _bss_end:
    25     .word _end
    26 
    27 #if defined(CONFIG_USE_IRQ)
    28 /* IRQ stack memory (calculated at run-time) */
    29 .globl IRQ_STACK_START
    30 IRQ_STACK_START:
    31     .word    0x0badc0de
    32 
    33 /* IRQ stack memory (calculated at run-time) */
    34 .globl FIQ_STACK_START
    35 FIQ_STACK_START:
    36     .word 0x0badc0de
    37 #endif

    下面这段代码的意思:  

    _TEXT_BASE(4字节)这个内存地址出的值为TEXT_BASE:0xc3e00000
    _TEXT_PHY_BASE(4字节)这个内存存放的值为 CFG_PHY_UBOOT_BASE(uboot的物理基地址):

    (定义在x210_sd.h中)CFG_PHY_UBOOT_BASE MEMORY_BASE_ADDRESS + 0x3e00000                
    (定义在x210_sd.h中)#define MEMORY_BASE_ADDRESS 0x20000000
    CFG_PHY_UBOOT_BASE 的值为0x23e00000  同样后面的代码 把_start、__bss_start、_end的值放到相应的内存地址处

    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

    reset:设置为SVC模式,禁止irq、frq中断;

    4:第四段代码

       /*
             * 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
    因为在x210_sd.h中定义了 CONFIG_EVT1,所以这段代码是不执行的;
     1    bl    disable_l2cache
     2 
     3     bl    set_l2cache_auxctrl_cycle
     4 
     5     bl    enable_l2cache
     6     
     7        /*
     8         * Invalidate L1 I/D
     9         */
    10         mov    r0, #0                  @ set up for MCR
    11         mcr    p15, 0, r0, c8, c7, 0   @ invalidate TLBs
    12         mcr    p15, 0, r0, c7, c5, 0   @ invalidate icache
    13 
    14        /*
    15         * disable MMU stuff and caches
    16         */
    17         mrc    p15, 0, r0, c1, c0, 0
    18         bic    r0, r0, #0x00002000     @ clear bits 13 (--V-)
    19         bic    r0, r0, #0x00000007     @ clear bits 2:0 (-CAM)
    20         orr    r0, r0, #0x00000002     @ set bit 1 (--A-) Align
    21         orr    r0, r0, #0x00000800     @ set bit 12 (Z---) BTB
    22         mcr     p15, 0, r0, c1, c0, 0

    上面这段代码是作用是cpu 的初始化

    disable_l2cache对应代码如下:

    disable_l2cache:
    mrc p15, 0, r0, c1, c0, 1
    bic r0, r0, #(1<<1)
    mcr p15, 0, r0, c1, c0, 1
    mov pc, lr

     set_l2cache_auxctrl_cycle:设置L2cache

    .global set_l2cache_auxctrl_cycle
    set_l2cache_auxctrl_cycle:
    mrc p15, 1, r0, c9, c0, 2
    bic r0, r0, #(0x1<<29)
    bic r0, r0, #(0x1<<21)
    bic r0, r0, #(0x7<<6)
    bic r0, r0, #(0x7<<0)
    mcr p15, 1, r0, c9, c0, 2
    mov pc,lr

     enable_l2cache:使能L2 cache

    enable_l2cache:
    mrc p15, 0, r0, c1, c0, 1
    orr r0, r0, #(1<<1)
    mcr p15, 0, r0, c1, c0, 1
    mov pc, lr

    第五段代码:读取启动信息

    /读取ompin引脚寄存器的值放入r0中 ,留下bit2—bit6中的值,并赋值给r2;

     1 /* NAND BOOT */
     2     cmp    r2, #0x0        @ 512B 4-cycle
     3     moveq    r3, #BOOT_NAND
     4 
     5     cmp    r2, #0x2        @ 2KB 5-cycle
     6     moveq    r3, #BOOT_NAND
     7 
     8     cmp    r2, #0x4        @ 4KB 5-cycle    8-bit ECC
     9     moveq    r3, #BOOT_NAND
    10 
    11     cmp    r2, #0x6        @ 4KB 5-cycle    16-bit ECC
    12     moveq    r3, #BOOT_NAND
    13 
    14     cmp    r2, #0x8        @ OneNAND Mux
    15     moveq    r3, #BOOT_ONENAND
    16 
    17     /* SD/MMC BOOT */
    18     cmp     r2, #0xc
    19     moveq   r3, #BOOT_MMCSD    
    20 
    21     /* NOR BOOT */
    22     cmp     r2, #0x14
    23     moveq   r3, #BOOT_NOR    
    24 
    25     /* Uart BOOTONG failed */
    26     cmp     r2, #(0x1<<4)
    27     moveq   r3, #BOOT_SEC_DEV
    * Read booting information */
    ldr    r0, =PRO_ID_BASE
    ldr    r1, [r0,#OMR_OFFSET]
    bic    r2, r1, #0xffffffc1

      ldr r0, =INF_REG_BASE
      str r3, [r0, #INF_REG3_OFFSET]

     

    通过判断r2中的值,来确定是从哪里启动的,如我们从SD卡启动的话r2中的值应该为0xc,然后把#BOOT_MMCSD 赋值给r3

    #define INF_REG_BASE 0xE010F000
    #define INF_REG3_OFFSET 0x0c
    把BOOT_MMCSD这个值放入寄存器 0xE010F00C中。
     1   ldr    sp, =0xd0036000 /* end of sram dedicated to u-boot */
     2     sub    sp, sp, #12    /* set stack */
     3     mov    fp, #0
     4     
     5     bl    lowlevel_init    /* go setup pll,mux,memory */
     6     /* To hold max8698 output before releasing power on switch,
     7      * set PS_HOLD signal to high
     8      */
     9     ldr    r0, =0xE010E81C  /* PS_HOLD_CONTROL register */
    10     ldr    r1, =0x00005301     /* PS_HOLD output high    */
    11     str    r1, [r0]
    12 
    13     /* get ready to call C functions */
    14     ldr    sp, _TEXT_PHY_BASE    /* setup temp stack pointer */
    15     sub    sp, sp, #12
    16     mov    fp, #0            /* no previous frame, so fp=0 */

    这段代码是设置栈,因为接下来调用lowlevel_init函数中还要调用其他函数,lr中保存pc的话,在调用其他函数就无法保存pc了,所以先要把lr入栈,调用完函数以后在出栈然后在pop {pc}

    lowlevel_init 函数:如下

      1 _TEXT_BASE:
      2     .word    TEXT_BASE
      3 
      4     .globl lowlevel_init
      5 lowlevel_init:
      6     push    {lr}                                //先把lr入栈
      7 
      8     /* check reset status  */
      9     
     10     ldr    r0, =(ELFIN_CLOCK_POWER_BASE+RST_STAT_OFFSET)    //#define ELFIN_CLOCK_POWER_BASE 0xE0100000 #define RST_STAT_OFFSET 0xa000
     11     ldr    r1, [r0]                          //这个寄存器为reset状态寄存器,
     12     bic    r1, r1, #0xfff6ffff
     13     cmp    r1, #0x10000
     14     beq    wakeup_reset_pre
     15     cmp    r1, #0x80000
     16     beq    wakeup_reset_from_didle
     17 
     18     /* IO Retention release */                          //I/O相关的一些初始化
     19     ldr    r0, =(ELFIN_CLOCK_POWER_BASE + OTHERS_OFFSET)
     20     ldr    r1, [r0]
     21     ldr    r2, =IO_RET_REL
     22     orr    r1, r1, r2
     23     str    r1, [r0]
     24 
     25     /* Disable Watchdog */                              //关看门狗
     26     ldr    r0, =ELFIN_WATCHDOG_BASE    /* 0xE2700000 */
     27     mov    r1, #0
     28     str    r1, [r0]
     29 
     30     /* SRAM(2MB) init for SMDKC110 */                  // #define ELFIN_GPIO_BASE 0xE0200000
     31     /* GPJ1 SROM_ADDR_16to21 */                      //SRAM和SROM相关的一些初始化
     32     ldr    r0, =ELFIN_GPIO_BASE
     33     
     34     ldr    r1, [r0, #GPJ1CON_OFFSET]                  // #define GPJ1CONPDN_OFFSET  0x270  寄存器为0xE0200270
     35     bic    r1, r1, #0xFFFFFF
     36     ldr    r2, =0x444444
     37     orr    r1, r1, r2
     38     str    r1, [r0, #GPJ1CON_OFFSET]
     39 
     40     ldr    r1, [r0, #GPJ1PUD_OFFSET]
     41     ldr    r2, =0x3ff
     42     bic    r1, r1, r2
     43     str    r1, [r0, #GPJ1PUD_OFFSET]
     44 
     45     /* GPJ4 SROM_ADDR_16to21 */
     46     ldr    r1, [r0, #GPJ4CON_OFFSET]
     47     bic    r1, r1, #(0xf<<16)
     48     ldr    r2, =(0x4<<16)
     49     orr    r1, r1, r2
     50     str    r1, [r0, #GPJ4CON_OFFSET]
     51 
     52     ldr    r1, [r0, #GPJ4PUD_OFFSET]
     53     ldr    r2, =(0x3<<8)
     54     bic    r1, r1, r2
     55     str    r1, [r0, #GPJ4PUD_OFFSET]
     56 
     57 
     58     /* CS0 - 16bit sram, enable nBE, Byte base address */
     59     ldr    r0, =ELFIN_SROM_BASE    /* 0xE8000000 */
     60     mov    r1, #0x1
     61     str    r1, [r0]
     62 
     63     /* PS_HOLD pin(GPH0_0) set to high */                          //供电锁存 同裸机中的一致
     64     ldr    r0, =(ELFIN_CLOCK_POWER_BASE + PS_HOLD_CONTROL_OFFSET)
     65     ldr    r1, [r0]
     66     orr    r1, r1, #0x300    
     67     orr    r1, r1, #0x1    
     68     str    r1, [r0]
     69 
     70     /* when we already run in ram, we don't need to relocate U-Boot.      
     71      * and actually, memory controller must be configured before U-Boot
     72      * is running in ram.
     73      */                                    
     74     ldr    r0, =0xff000fff                              //这几行的代码是判断现在程序是在内存中执行还是在SRAM中执行,
     75     bic    r1, pc, r0        /* r0 <- current base addr of code */      //如果在内存中执行的话不用初始化时钟和sdram直接跳转到1去执行
     76     ldr    r2, _TEXT_BASE        /* r1 <- original base addr in ram */
     77     bic    r2, r2, r0        /* r0 <- current base addr of code */
     78     cmp     r1, r2                  /* compare r0, r1                  */
     79     beq     1f            /* r0 == r1 then skip sdram init   */
     80 
     81     /* init system clock */
     82     bl system_clock_init                                //如果没有在内存中执行首先要初始化时钟
     83 
     84     /* Memory initialize */
     85     bl mem_ctrl_asm_init                                //然后初始化内存
     86     
     87 1:
     88     /* for UART */
     89     bl uart_asm_init                                //初始化uart在结尾输出了一个'O'字符
     90 
     91     bl tzpc_init                                    //trust zone的初始化
     92 
     93 #if defined(CONFIG_ONENAND)
     94     bl onenandcon_init
     95 #endif
     96 
     97 #if defined(CONFIG_NAND)
     98     /* simple init for NAND */
     99     bl nand_asm_init
    100 #endif
    101 
    102     /* check reset status  */
    103     
    104     ldr    r0, =(ELFIN_CLOCK_POWER_BASE+RST_STAT_OFFSET)
    105     ldr    r1, [r0]
    106     bic    r1, r1, #0xfffeffff
    107     cmp    r1, #0x10000
    108     beq    wakeup_reset_pre
    109 
    110     /* ABB disable */
    111     ldr    r0, =0xE010C300
    112     orr    r1, r1, #(0x1<<23)
    113     str    r1, [r0]
    114 
    115     /* Print 'K' */                                       //UTXH_OFFSET寄存器中写入0x4b4b4b4b即输出K
    116     ldr    r0, =ELFIN_UART_CONSOLE_BASE                            //所以说输出OK就说明lowlevel_init初始化成功
    117     ldr    r1, =0x4b4b4b4b
    118     str    r1, [r0, #UTXH_OFFSET]
    119 
    120     pop    {pc}                                        //pc 出栈

     第六段代码

     1 ldr    r0, =0xE010E81C  /* PS_HOLD_CONTROL register */              //电源锁存
     2     ldr    r1, =0x00005301     /* PS_HOLD output high    */
     3     str    r1, [r0]
     4 
     5     /* get ready to call C functions */
     6     ldr    sp, _TEXT_PHY_BASE    /* setup temp stack pointer */        //重新这是栈,因为初始化了内存以后执行代码就要在内存中执行代码了
     7     sub    sp, sp, #12                                  
     8     mov    fp, #0            /* no previous frame, so fp=0 */          //设置的地址为0x23e00000因为arm的栈为慢减栈,所以是向下增长的
     9 
    10     /* when we already run in ram, we don't need to relocate U-Boot.
    11      * and actually, memory controller must be configured before U-Boot
    12      * is running in ram.
    13      */
    14     ldr    r0, =0xff000fff                              //判断现在是否在内存中执行,如果在内存中执行的话就不需要重定位了
    15     bic    r1, pc, r0        /* r0 <- current base addr of code */      //如果不是在内存中执行的话则需要重定位
    16     ldr    r2, _TEXT_BASE        /* r1 <- original base addr in ram */
    17     bic    r2, r2, r0        /* r0 <- current base addr of code */
    18     cmp     r1, r2                  /* compare r0, r1                  */
    19     beq     after_copy        /* r0 == r1 then skip flash copy   */

    下面这段代码的作用是判断启动是从哪里启动的,然后采用相应的复制函数把uboot复制到内存中;

     1 #if defined(CONFIG_EVT1)                             //定义了 CONFIG_EVT1的值为1
     2     /* If BL1 was copied from SD/MMC CH2 */                  
     3     ldr    r0, =0xD0037488                            
     4     ldr    r1, [r0]                                //把内存0xD0037488中的值放入r1中,r2的值为0xEB200000
     5     ldr    r2, =0xEB200000
     6     cmp    r1, r2
     7     beq     mmcsd_boot                     //如果相等则跳转到 mmcsd_boot中,这个函数是从sd卡中复制内容到内存中,代码执行结果直接跳转
    8 #endif 9 10 ldr r0, =INF_REG_BASE                  //在上面的代码中设置了INF_REG3_OFFSET中的值,对应的位SD启动的值 11 ldr r1, [r0, #INF_REG3_OFFSET]            //所以这段代码的作用也是跳转到mmcsd_boot函数中 12 cmp r1, #BOOT_NAND /* 0x0 => boot device is nand */ 13 beq nand_boot 14 cmp r1, #BOOT_ONENAND /* 0x1 => boot device is onenand */ 15 beq onenand_boot 16 cmp r1, #BOOT_MMCSD 17 beq mmcsd_boot 18 cmp r1, #BOOT_NOR 19 beq nor_boot 20 cmp r1, #BOOT_SEC_DEV 21 beq mmcsd_boot 22 23 nand_boot: 24 mov r0, #0x1000 25 bl copy_from_nand 26 b after_copy 27 28 onenand_boot: 29 bl onenand_bl2_copy 30 b after_copy 31 32 mmcsd_boot:                              //上面一段代码的作用就是判断启动方式,然后跳转到相应的复制函数中 33 #if DELETE                              //因为我们采用的是sd卡启动,所以最后进入了mmcsd_boot函数中 34 ldr sp, _TEXT_PHY_BASE                35 sub sp, sp, #12 36 mov fp, #0 37 #endif                                 //函数的作用是跳转到    movi_bl2_copy函数中,把uboot从sd卡复制到内存地址中 38 bl movi_bl2_copy 39 b after_copy                      //然后在跳转到 after_copy函数中;

    下面分析一下 movi_bl2_copy函数,和裸机中的重定位是一致的。

      1 extern raw_area_t raw_area_control;
      2 
      3 typedef u32(*copy_sd_mmc_to_mem)
      4 (u32 channel, u32 start_block, u16 block_size, u32 *trg, u32 init);
      5 
      6 void movi_bl2_copy(void)
      7 {
      8     ulong ch;
      9 #if defined(CONFIG_EVT1)
     10     ch = *(volatile u32 *)(0xD0037488);
     11     copy_sd_mmc_to_mem copy_bl2 =
     12         (copy_sd_mmc_to_mem) (*(u32 *) (0xD0037F98));
     13 
     14     #if defined(CONFIG_SECURE_BOOT)
     15     ulong rv;
     16     #endif
     17 #else
     18     ch = *(volatile u32 *)(0xD003A508);
     19     copy_sd_mmc_to_mem copy_bl2 =
     20         (copy_sd_mmc_to_mem) (*(u32 *) (0xD003E008));
     21 #endif
     22     u32 ret;
     23     if (ch == 0xEB000000) {
     24         ret = copy_bl2(0, MOVI_BL2_POS, MOVI_BL2_BLKCNT,
     25             CFG_PHY_UBOOT_BASE, 0);
     26 
     27 #if defined(CONFIG_SECURE_BOOT)
     28         /* do security check */
     29         rv = Check_Signature( (SecureBoot_CTX *)SECURE_BOOT_CONTEXT_ADDR,
     30                       (unsigned char *)CFG_PHY_UBOOT_BASE, (1024*512-128),
     31                           (unsigned char *)(CFG_PHY_UBOOT_BASE+(1024*512-128)), 128 );
     32         if (rv != 0){
     33                 while(1);
     34             }
     35 #endif
     36     }
     37     else if (ch == 0xEB200000) {
     38         ret = copy_bl2(2, MOVI_BL2_POS, MOVI_BL2_BLKCNT,
     39             CFG_PHY_UBOOT_BASE, 0);
     40         
     41 #if defined(CONFIG_SECURE_BOOT)
     42         /* do security check */
     43         rv = Check_Signature( (SecureBoot_CTX *)SECURE_BOOT_CONTEXT_ADDR,
     44                       (unsigned char *)CFG_PHY_UBOOT_BASE, (1024*512-128),
     45                           (unsigned char *)(CFG_PHY_UBOOT_BASE+(1024*512-128)), 128 );
     46         if (rv != 0) {
     47             while(1);
     48         }
     49 #endif
     50     }
     51     else
     52         return;
     53 
     54     if (ret == 0)
     55         while (1)
     56             ;
     57     else
     58         return;
     59 }
    

    第七段代码:最后一段代码,作用是配置MMU、重新设置栈、清bss、跳转到start_armboot函数中去执行BL2阶段;

    下面详细分析一下代码:初始化mmu这一段请看另一篇专门关于mmu的博客

     1 after_copy:
     2 
     3 #if defined(CONFIG_ENABLE_MMU)
     4 enable_mmu:
     5     /* enable domain access */
     6     ldr    r5, =0x0000ffff
     7     mcr    p15, 0, r5, c3, c0, 0        @load domain access register
     8 
     9     /* Set the TTB register */
    10     ldr    r0, _mmu_table_base
    11     ldr    r1, =CFG_PHY_UBOOT_BASE
    12     ldr    r2, =0xfff00000
    13     bic    r0, r0, r2
    14     orr    r1, r0, r1
    15     mcr    p15, 0, r1, c2, c0, 0
    16 
    17     /* Enable the MMU */
    18 mmu_on:
    19     mrc    p15, 0, r0, c1, c0, 0
    20     orr    r0, r0, #1
    21     mcr    p15, 0, r0, c1, c0, 0
    22     nop
    23     nop
    24     nop
    25     nop
    26 #endif
    27 
    28 skip_hw_init:                         //重新设置栈:0x23e00000 + 2M - 0x1000 = 0x23e00000 + 0x200000 - 0x1000 = 0x240FF000
    29     /* Set up the stack                            */        //最后设置sp = 0x240FF000
    30 stack_setup:
    31 #if defined(CONFIG_MEMORY_UPPER_CODE)
    32     ldr    sp, =(CFG_UBOOT_BASE + CFG_UBOOT_SIZE - 0x1000)      
    33 #else                                                  
    34     ldr    r0, _TEXT_BASE        /* upper 128 KiB: relocated uboot   */
    35     sub    r0, r0, #CFG_MALLOC_LEN    /* malloc area                      */
    36     sub    r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo                        */
    37 #if defined(CONFIG_USE_IRQ)
    38     sub    r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
    39 #endif
    40     sub    sp, r0, #12        /* leave 3 words for abort-stack    */  
    41 
    42 #endif
    43 
    44 clear_bss:                                               //清bss代码同裸机中一样
    45     ldr    r0, _bss_start        /* find start of bss segment        */
    46     ldr    r1, _bss_end        /* stop here                        */
    47     mov     r2, #0x00000000        /* clear                            */
    48 
    49 clbss_l:
    50     str    r2, [r0]        /* clear loop...                    */
    51     add    r0, r0, #4
    52     cmp    r0, r1
    53     ble    clbss_l
    54     
    55     ldr    pc, _start_armboot                                    //跳转执行bl2阶段start_armboot函数。
    56 57 _start_armboot: 58 .word start_armboot

    总结:

      uboot的第一阶段到这里算是执行完成了,uboot在第一阶段中做的事包括:

    1:建立异常向量表

    2:cpu的初始化

    3:判断启动方式

    4:初始化 i/o、关看门狗、初始化SROM、初始化时钟、初始化sdram、初始化uart、初始化trust zone

    5:供电锁存、重定位、MMU配置、清bss、跳转到star_armboot执行BL2阶段





  • 相关阅读:
    Java初学者:for循环介绍
    Java初学者:条件判断及其语句
    Java初学者:基本数据类型的强制类型转换
    eclipse+gradle+nodejs搭建web开发环境
    桑基图(sankey)
    tomcat性能优化
    数据库概览与选择
    在linux上装 postgresql 在 windows或 linux 连不上的问题的解决方法
    mosquitto的TLS功能测试,客户端使用paho.mqtt.golang(附JAVA版客户端实现)
    两步使用arm-linux-androideabi-addr2line定位JNI动态库中C代码错误位置
  • 原文地址:https://www.cnblogs.com/biaohc/p/6368341.html
Copyright © 2011-2022 走看看