BootLoader(U-Boot)启动过程记录
定义
Bootloader终极目的是引导内核,加载内核到内存然后跳转到内核的地方执行,在加载之前也会做一些硬件的初始化等等操作。启动模式分为两种:启动加载模式(产品形式,自启动),下载模式(开发模式,适用于开发人员调试使用);以下记录都是以U-Boot为例。
源码下载地址
ftp://ftp.denx.de/pub/u-boot/
启动分析
本次记录是以hi3536启动流程为例进行的。
概述
U-Boot启动分析我大致分为两个阶段:汇编代码阶段,C语言阶段; 汇编代码阶段主要是对芯片内部的初始化,主要是异常向量表、中断的禁用、初始化栈、MMU和Cache的禁用等;C语言阶段主要是板级的初始化,大量的移植修改就是在此阶段。
具体分析
第一阶段汇编代码阶段
通过uboot的连接器脚本/u-boot/arch/arm/cpu/u-boot.lds可以看到输出的可执行文件的起始代码段为ENTRY(_start)。所以我们来看第一个汇编代码程序arch\arm\cpu\hi3536\start.S
设置异常向量表
1、_start就是上面所提到的起始代码段,.globl将其全局化,标识为start.S的入口。
2、reset段是复位代码段,当发生异常时,代码会跳转到此处执行reset代码。
3、构建异常向量表,发生异常事件跳转到到相应的位置执行。
.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
...................
.align 5
undefined_instruction:
get_bad_stack
bad_save_user_regs
bl do_undefined_instruction
设置为SVC32模式
因为uboot启动需要权限问题,所以在uboot启动会进入CPU的特权模式进行工作
/*
* set the cpu to SVC32 mode
*/
mrs r0, cpsr
bic r0, r0, #0x1f
orr r0, r0, #0xd3
msr cpsr,r0
禁用Cache
保证所取指令与flash中的一致,不是之前存留下来的。Caches是CPU内部的一个2级缓存,它的作用是将常用的数据和指令放在CPU内部。Caches是通过CP15管理的,刚上电的时候,CPU还不能管理Caches。上电的时候指令Cache可关闭,也可不关闭,但数据Cache一定要关闭,否则可能导致刚开始的代码里面,去取数据的时候,从Cache里面取,而这时候RAM中数据还没有Cache过来,导致数据预取异常
/*
* 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
/* Invalidate L1 D-cache */
mov r0, #0
mcr p15, 2, r0, c0, c0, 0
mrc p15, 1, r0, c0, c0, 0
ldr r1, =0x7fff
and r2, r1, r0, lsr #13
ldr r1, =0x3ff
and r3, r1, r0, lsr #3 @ NumWays - 1
add r2, r2, #1 @ NumSets
and r0, r0, #0x7
add r0, r0, #4 @ SetShift
clz r1, r3 @ WayShift
add r4, r3, #1 @ NumWays
1: sub r2, r2, #1 @ NumSets--
mov r3, r4 @ Temp = NumWays
2: subs r3, r3, #1 @ Temp--
mov r5, r3, lsl r1
mov r6, r2, lsl r0
orr r5, r5, r6 @ Reg = (Temp<<WayShift)|(NumSets<<SetShift)
mcr p15, 0, r5, c7, c6, 2
bgt 2b
cmp r2, #0
bgt 1b
dsb
isb
禁用MMU
程序开始启动没有做虚拟地址映射,现在不能操作相关的地址,所以禁用掉MMU