uboot 代码执行顺序

--- title: uboot 代码执行顺序 date: 2019-07-30 11:32:26 categories: tags: - uboot ---

uboot: 2014.07

ref : http://blog.chinaunix.net/uid-30352139-id-5128405.html

U-boot相关文件

boards.cfg:

ARCH = ARM

CPU = ARMv7

SOC = exynos

BOARD = smdkc210

VENDER = samsung 

files:

Include/configs/smdkc210.h

arch/$(ARCH)/cpu/$(CPU)/start.S

board/$(VENDER)/$(BOARD)/smdkc210.c

arch/$(ARCH)/lib/board.c

arch/$(ARCH)/lib/crto.S

arch/$(ARCH)/lib/relocate.S 

初始化流程

  1.   start.S -> _start 
    
  2.   start.S -> reset 
    
  3.   crt0.S -> _main ==>> board.c -> board_init_f 
    
  4.   relocate.S -> relocate_code 
    
  5.   crt0.S -> here 
    
  6.   board.c -> board_init_r 
    
  7.   main.c -> main_loop 
    

初始化实现(以ARM为例)

《ARM Cortex-A Series Programmer’s Guide》中列出了Cortex-A系列的初始化方法(第十三章:Boot Code)。

ARM启动时,会从异常向量表的reset异常处启动(0或0xffff0000)。对于u-boot,不需要实现所有启动流程,只需要实现几个必须的程:

  1. Initialize exception vectors.

  2. Initialize the memory system, including the MMU.

  3. Initialize core mode stacks and registers.

  4. Initialize any critical I/O devices.

  5. Call the main()application.

代码分析

初始化中断向量表 (Initialize exception vectors)

.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 
_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 
_pad:            .word 0x12345678 /* now 16*4=64 */ 
.global _end_vect 
_end_vect: 
.balignl
16,0xdeadbeef

禁止中断 (FIQ and IRQ), 设置CPU模式为SVC32 (Initialize core mode stacks and registers.)


reset: 
bl    save_boot_params 
/* 
 * disable interrupts (FIQ and IRQ), also set the cpu to SVC32 mode, 
 * except if in HYP mode already 
 */ 
mrs    r0, cpsr 
and    r1, r0, #0x1f        @ mask mode bits 
teq    r1, #0x1a        @ test for HYP mode 
bicne    r0, r0, #0x1f        @ clear all mode bits 
orrne    r0, r0, #0x13        @ set SVC mode 
orr    r0, r0, #0xc0        @ disable FIQ and IRQ 
msr    cpsr,r0

设置中断向量表 (Initialize exception vectors)

/* Set V=0 in CP15 SCTRL register - for VBAR to point to vector */ 

mrc    p15, 0, r0, c1, c0, 0    @ Read CP15 SCTRL Register 
bic    r0, #CR_V        @ V = 0 
mcr    p15, 0, r0, c1, c0, 0    @ Write CP15 SCTRL Register 

/* Setvector address in CP15 VBAR register */ 
ldr    r0, =_start 
mcr    p15, 0, r0, c12, c0, 0    @Set VBAR 

Invalidate L1 I/D cache (Initialize the memory system, including the MMU)

ENTRY(cpu_init_cp15) 

/* 
 * 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 
mcr    p15, 0, r0, c7, c5, 6    @ invalidate BP array 
mcr     p15, 0, r0, c7, c10, 4    @ DSB 
mcr     p15, 0, r0, c7, c5, 4    @ ISB 

禁止 MMU and caches (Initialize the memory system, including the MMU)

/* 
 * 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 11 (Z---) BTB 
orr    r0, r0, #0x00001000    @ set bit 12 (I) I-cache 
mcr    p15, 0, r0, c1, c0, 0 
mov    pc, lr            @ back to my caller 

设置C运行环境 (Initialize core mode stacks and registers.)

ENTRY(_main) 

/* 
 * Set up initial C runtime environment and call board_init_f(0). 
 */ 

ldr    sp, =(CONFIG_SYS_INIT_SP_ADDR) 
bic    sp, sp, #7    /* 8-byte alignment for ABI compliance */ 
sub    sp, #GD_SIZE    /* allocate one GD above SP */ 
bic    sp, sp, #7    /* 8-byte alignment for ABI compliance */ 
mov    r9, sp        /* GD is above SP */ 

调用 board_init_f(0) 对串口进行初始化(Initialize any critical I/O devices)

mov    r0, #0 
bl    board_init_f 

设置临时运行环境

/* 
 * Set up intermediate environment (new sp and gd) and call 
 * relocate_code(addr_moni). Trick here is that we'll return 
 * 'here' but relocated. 
 */ 

ldr    sp, [r9, #GD_START_ADDR_SP]     /* sp = gd->start_addr_sp */ 
bic    sp, sp, #7    /* 8-byte alignment for ABI compliance */ 
ldr    r9, [r9, #GD_BD]        /* r9 = gd->bd */ 
sub    r9, r9, #GD_SIZE        /* new GD is below bd */ 

代码重定向,保证u-boot迁入内存后能够正常运行 (Relocate the code)

adr    lr, here 
ldr    r0, [r9, #GD_RELOC_OFF]     /* r0 = gd->reloc_off */ 
add    lr, lr, r0 

ldr    r0, [r9, #GD_RELOCADDR]     /* r0 = gd->relocaddr */ 
b    relocate_code 
here: 

接下来的这几步操作前面已经进行过,感觉可以去掉

ENTRY(c_runtime_cpu_setup) 

/* 
 * invalidate I-cache 
 */ 

mcr     p15, 0, r0, c7, c5, 0    @ invalidate icache 
mcr     p15, 0, r0, c7, c10, 4    @ DSB 
mcr     p15, 0, r0, c7, c5, 4    @ ISB 

由于u-boot经过了重定向,代码位置发生了改变,所以这里需要重新设置VBAR寄存器。

实际的代码如下: ldr r0, [pc, #736]

利用PC保证加载的是当前地址,而不是u-boot在ROM中的地址。


/* 
 * Move vector table 
 */ 

/* Set vector address in CP15 VBAR register */ 
ldr     r0, =_start 
mcr     p15, 0, r0, c12, c0, 0  @Set VBAR 

把 .bss 段清零

ldr    r0,
=__bss_start    /* This is auto-relocated!   */ 

ldr    r1, =__bss_end    /* this is auto-relocated! */ 
mov    r2, #0x00000000    /* prepare zero to clear BSS */ 
clbss_l:cmp    r0, r1        /* while not at end of BSS */ 
strlo    r2, [r0]        /* clear 32-bit BSS word */ 
addlo    r0, r0, #4        /* move to next */ 
blo    clbss_l 

调用 board_init_r(gd_t *id, ulong dest_addr它会初始化网口设备,然后调用main_loop进入u-boot控制台。(Call the main()application)

/* call board_init_r(gd_t *id, ulong dest_addr) */ 
mov     r0, r9                  /* gd_t */ 
ldr    r1, [r9, #GD_RELOCADDR]    /* dest_addr */ 
/* call board_init_r */ 
ldr    pc, =board_init_r    /* this is auto-relocated! */ 

board_init_f

下面是board_init_f执行的操作:

function comments
arch_cpu_init Do nothing on smdkc210
timer_init Do nothing on smdkc210
env_init 初始化环境变量, 实际上是把default_environment设置到gd->env_addr. default_environment是一个字符串数组,每一个字符串用一个宏表示,我们通过在“include/configs/smdkc210.h”定义这些宏的方式设置环境变量。
init_baudrate 设置波特率,其实它来自于 gd->baud.
serial_init 调用串口初始化函数
dram_init 设置RAM位置与大小
Set gd. The most 设置gd表,用于保存配置
原文地址:https://www.cnblogs.com/schips/p/13128992.html