uboot/arch/arm/cpu/start.s
mrs、msr读写ARM状态寄存器指令
bit(bit clear)位清除指令
orr 位或指令
LDR{条件} 目的寄存器 <存储器地址>
1、上电跳转
start.s:
_start:
b reset
I、F中断禁止位,置1中断禁止
M[4:0] | 处理器模式 | ARM模式可访问的寄存器 | THUMB模式可访问的寄存器 |
0b10000 | 用户模式 | PC,CPSR,R0~R14 | PC,CPSR,R0~R7,LR,SP |
0b10001 | FIQ模式 | PC,CPSR,SPSR_fiq,R14_fiq~R8_fiq,R0~R7 | PC,CPSR,SPSR_fiq,LR_fiq,SP_fiq,R0~R7 |
0b10010 | IRQ模式 | PC,CPSR,SPSR_irq,R14_irq~R13_irq,R0~R12 | PC,CPSR,SPSR_irq,LR_irq,SP_irq,R0~R7 |
0b10011 | 管理模式 | PC,CPSR,SPSR_svc,R14_svc~R13_svc,R0~R12 | PC,CPSR,SPSR_svc,LR_svc,SP_svc,R0~R7 |
0b10111 | 中止模式 | PC,CPSR,SPSR_abt,R14_abt~R13_abt,R0~R12 | PC,CPSR,SPSR_abt,LR_abt,SP_abt,R0~R7 |
0b11011 | 未定义模式 | PC,CPSR,SPSR_und,R14_und~R13_und,R0~R12 | PC,CPSR,SPSR_und,LR_und,SP_und,R0~R7 |
0b11111 | 系统模式 | PC,CPSR,R0~R14 | PC,CPSR,LR,SP,R0~R74 |
2、关闭普通中断和快速中断,状态位清零,进入管理员模式
reset:
/*
* set the cpu to SVC32 mode
*/
mrs r0,cpsr
bic r0,r0,#0x1f
orr r0,r0,#0xd3 /*11010011*/
msr cpsr,r0
我们只在重新启动时进行系统关键初始化,从ram启动时不会
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_crit /*跳转到3*/
#endif
3、清空D cache、关闭D cache、关闭I cache、关闭MMU系统保护和ROM保护、关闭MMU、关闭对齐检查、关闭TLB(TLB是啥)、选择高端异常中断向量、使能地址对齐、使能I cache
cpu_init_crit:
在禁用缓存之前刷新D cache
mov r0, #0
flush_dcache:
mrc p15, 0, r15, c7, c10, 3/*清空D cache*/
bne flush_dcache
mcr p15, 0, r0, c8, c7, 0 /* 关闭TLB */
mcr p15, 0, r0, c7, c5, 0 /* 关闭I cache */
/*
* disable MMU and D cache
* enable I cache if CONFIG_SYS_ICACHE_OFF is not defined
*/
配置C1协处理器
mrc p15, 0, r0, c1, c0, 0 /*读C1协处理器到R0*/
bic r0, r0, #0x00000300 /* clear bits 9:8 (---- --RS) 关闭MMU系统保护和ROM保护*/
bic r0, r0, #0x00000087 /* clear bits 7, 2:0 (B--- -CAM) 关闭MMU 关闭对齐检查 关闭D cache */
#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 2 (A) Align 使能地址对齐*/
#ifndef CONFIG_SYS_ICACHE_OFF
orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache 使能icache*/
#endif
mcr p15, 0, r0, c1, c0, 0 /*把R0写进C1*/
配置完毕
mov ip, lr /* 将返回地址寄存器内容放到指令地址寄存器中,LRbl cpu_init_crit 后面的地址*/
bl lowlevel_init /* go setup pll,mux,memory */
mov lr, ip /* restore link */
mov pc, lr /* back to my caller */ 跳回2 bl cpu_init_crit 后面
lowlevel_init:
#ifdef CONFIG_SOC_DM644X
#else /* CONFIG_SOC_DM644X */
mov pc, lr(相当于啥也没做,又跳回去了,LR是bl后面的地址)
#endif
4、上接1reset函数的bl cpu_init_crit
/* Set stackpointer in internal RAM to call board_init_f */
call_board_init_f:
#ifdef CONFIG_NAND_SPL /* deprecated, use instead CONFIG_SPL_BUILD disable*/
ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
#else
#ifdef CONFIG_SPL_BUILD /*disable*/
ldr sp, =(CONFIG_SPL_STACK)
#else
ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) /*设置堆栈寄存器、堆栈的偏移地址*/
#endif
#endif
bic sp, sp, #7 /* 8-byte alignment for ABI compliance 8字节对齐*/
ldr r0,=0x00000000 /*设置参数,r0-r3参数寄存器*/
bl board_init_f /*设置堆栈之后,就能进入C语言世界 ,为什么C语言需要堆栈,请参考unix高级环境编程进程部分/arch/arm/lib/board.c*/