第一阶段:
a -- 设置cpu工作模式为SVC模式
第一阶段的文件:
arch/arm/cpu/arm926ejs /start.S 平台相关,CPU工作模式设为SVC模式,关MMU,关icahce(CPU相关)
设置异常向量表
-
.globl是globl是把_start这个标号全局化,是编译器的操作,并不是汇编指令。_start代表程序start.S的入口。
-
这段代码的功能是设置异常向量表。b reset 所处的位置是与异常向量表基地址偏移量为的0的地方,所以当复位异常发生时(开机也属于复位异常),CPU会自动跳转入异常表基址偏移量为0处执行复位异常程序,即跳转执行reset部分的代码。
-
这部分代码只是构建了异常向量表,当每个异常向量指向的内容为空(除reset异常外)。因为U-Boot比较简单,只是作为引导程序,所以不需要很细致的处理各种异常。
-
.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
禁能IRQ和FIQ,使能SVC模式
-
开机后程序从此时正式开始运行。
-
程序上电之初,异常向量表未初始化,故先禁能IRQ(普通中断)和FIQ(快速中断)。
-
使能SVC模式,即超级用户模式。SVC 模式,主要用于 SWI(软件中断)和 OS(操作系统)。这个模式有额外的特权,允许你进一步控制计算机。例如,你必须进入超级用户模式来读取一个插件(podule)。这不能在用户模式下完成。
b -- 关闭中断,mmu,cache
禁用Cache和MMU
-
caches是CPU的缓冲区,它的作用是存放常用的数据和指令,提高cpu与内存之间数据与指令的传输速率。
-
MMU是CPU的内存管理单元,它的作用是转换虚拟地址与物理地址。
-
关闭caches的原因:上电初始,DDR未初始化,当CPU从cache中取数据时,可能导致数据预取异常。另一方面,当汇编指令读取缓存数据,而实际物理地址对应的数据发生变化,导致CPU不能获取最新的数据。在C语言中无需关闭caches,因为C语言中可以使用volatile关键字避免上述情况。
-
关闭MMU的原因:U-Boot的作用是硬件初始化和引导操作系统,纯粹的初始化阶段,开启MMU会导致这个过程更复杂。
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
cpu_init_crit:
/*
* flush D cache before disabling it
*/
ldr r0, =0xB0000218
mov r1, #0x8
str r1, [r0]
ldr r0, =0xB8003180
mov r1, #0x1
str r1, [r0]
mov r0, #0
flush_dcache:
mrc p15, 0, r15, c7, c10, 3
bne flush_dcache
mcr p15, 0, r0, c8, c7, 0 /* invalidate TLB */
mcr p15, 0, r0, c7, c5, 0 /* invalidate I Cache */
/*
* disable MMU and D cache
* enable I cache if SYS_ICACHE_OFF is not defined
*/
mrc p15, 0, r0, c1, c0, 0
bic r0, r0, #0x00000300 /* clear bits 9:8 (---- --RS) */
bic r0, r0, #0x00000087 /* clear bits 7, 2:0 (B--- -CAM) */
#ifdef CONFIG_SYS_EXCEPTION_VECTORS_HIGH
orr r0, r0, #0x00002000 /* set bit 13 (--V- ----) */
#else
bic r0, r0, #0x00002000 /* clear bit 13 (--V- ----) */
#endif
orr r0, r0, #0x00000002 /* set bit 1 (A) Align */
#if !CONFIG_IS_ENABLED(SYS_ICACHE_OFF)
orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache */
ldr r0, =0xB8003180
mov r1, #0x1
str r1, [r0]
#endif
mcr p15, 0, r0, c1, c0, 0
#ifndef CONFIG_SKIP_LOWLEVEL_INIT_ONLY
/*
* Go setup Memory and board specific bits prior to relocation.
*/
ldr r0, =0xB8003180
mov r1, #0x4
str r1, [r0]
mov r4, lr /* perserve link reg across call */
bl lowlevel_init /* go setup pll,mux,memory */
mov lr, r4 /* restore link */
#endif
mov pc, lr /* back to my caller */
#endif /* CONFIG_SKIP_LOWLEVEL_INIT */