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阶段





原文地址:https://www.cnblogs.com/biaohc/p/6368341.html