2.2 reset
reset 函数存在于 arch/arm/cpu/armv7/start.s 文件中,而 reset 函数跳转到 save_boot_params 函数,save_boot_params 函数又跳转到 save_boot_params_ret中,具体如下:
//第一段:reset跳转到save_boot_params
.globl reset
.globl save_boot_params_ret
reset:
/* Allow the board to save important registers */
b save_boot_params
save_boot_params_ret:
/*
* 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
//第二段:save_boot_params跳转到save_boot_params_ret
ENTRY(save_boot_params)
b save_boot_params_ret @ back to my caller
ENDPROC(save_boot_params)
.weak save_boot_params
2.3 cpsr和cp15 STCLR
reset 函数跳转到 save_boot_params_ret函数后,具体如下:
save_boot_params_ret:
/*
* 关闭 FIQ 和 IRQ 中断,设置 CPU 处于 SVC 特权模式
* except if in HYP mode already(除非已经处于HYP特权模式,比SVC低一点的特权)
*/
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
/*
*★SCTLR寄存器bit13清零(bit13控制中断向量表地址,0:可以重定位;1:默认为0xFFFF0000)将_start
*的数值写入该寄存器,也就是中断向量表的起始地址为0x87800000
*/
#if !(defined(CONFIG_OMAP44XX) && defined(CONFIG_SPL_BUILD))
/* Set V=0 in CP15 SCTLR register - for VBAR to point to vector */
mrc p15, 0, r0, c1, c0, 0 @ Read CP15 SCTLR Register
bic r0, #CR_V @ V = 0
mcr p15, 0, r0, c1, c0, 0 @ Write CP15 SCTLR Register
/* Set vector address in CP15 VBAR register */
ldr r0, =_start
mcr p15, 0, r0, c12, c0, 0 @Set VBAR
#endif
/* the mask ROM code should have PLL and others stable */
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_cp15
bl cpu_init_crit
#endif
bl _main
从上述代码能看出,代码包含5个部分:cpsr,cp15,cpu_init_cp15,cpu_init_crit和**_main**。
2.3.1 cpsr
/*
* 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
**cpsr:**给目标寄存器写入对应的数值(可以参考芯片手册),关闭 FIQ 和 IRQ,并且讲CPU设置为 SVC 特权模式。
为什么这样操作的原因:
**(1) 禁止 FIQ 和 IRQ:**uboot 作为芯片上电的第一道程序是至关重要的,而中断是很危险的,它的等级太高了,可以轻松打断程序的正常运行。所以,为了保证uboot的正常运行,需要关闭部分中断。
(2) 设置 SVC:uboot的运行避免不了对各类寄存器等操作,为了保证操作的正常,需要给CPU设置高特权模式。
2.3.2 cp15
/*
* Setup vector:
* (OMAP4 spl TEXT_BASE is not 32 byte aligned.
* Continue to use ROM code vector only in OMAP4 spl)
*/
#if !(defined(CONFIG_OMAP44XX) && defined(CONFIG_SPL_BUILD))
/* Set V=0 in CP15 SCTLR register - for VBAR to point to vector */
mrc p15, 0, r0, c1, c0, 0 @ Read CP15 SCTLR Register
bic r0, #CR_V @ V = 0
mcr p15, 0, r0, c1, c0, 0 @ Write CP15 SCTLR Register
/* Set vector address in CP15 VBAR register */
ldr r0, =_start
mcr p15, 0, r0, c12, c0, 0 @Set VBAR
#endif
**cp15 SCTLR:**SCTLR寄存器bit13清零(bit13控制中断向量表地址,0:可以重定位;1:默认为0xFFFF0000)将_start的数值写入该寄存器,也就是中断向量表的起始地址为0x87800000
2.4 cpu_init_cp15
cpu_init_cp15 存在于 arch/arm/cpu/armv7/start.s 文件中:
/*************************************************************************
*
* cpu_init_cp15
*
* Setup CP15 registers (cache, MMU, TLBs). The I-cache is turned on unless
* CONFIG_SYS_ICACHE_OFF is defined.
*
*************************************************************************/
ENTRY(cpu_init_cp15)
/*
* Invalidate L1 I/D
*/
mov r0, #0 @ set up for MCR
mcr p15, 0, r0, c8, c7, 0 @ invalidate TLBs /*禁止从TLB中取地址描述符,也就是禁止虚拟地址到物理地址的转换,因为刚开始操作的都是物理寄存器!*/
mcr p15, 0, r0, c7, c5, 0 @ invalidate icache /*关闭指令cache*/
mcr p15, 0, r0, c7, c5, 6 @ invalidate BP array /*关闭分支预测*/
mcr p15, 0, r0, c7, c10, 4 @ DSB /*多核cpu之间进行数据同步*/
mcr p15, 0, r0, c7, c5, 4 @ ISB /*进行指令同步,放弃流水线中已经取到的指令,重新取指令*/
/*
* 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