2.Reset_Handler中断服务函数
/******编写复位中断服务函数Reset_Handler,内容如下:*******/
Reset_Handler:
/*1)关闭I,D Cache和MMU。
CP15寄存器:
MRC将CP15协处理器中的寄存器数据读到ARM寄存器中。
MRC就是读CP15寄存器,MCR就是写CP15寄存器,MCR指令格式如下:*/
MCR{cond} p15,<opc1>,<Rt>,<CRn>,<CRm>,<opc2>
MRC p15,0,r0,c0,c0,0
/*现在要关闭I,D Cache和MMU,打开Cortex-A7参考手册到105页,找到SCTLR寄存器。也就是系统控制寄存器,此寄存器bit0用于打开和关闭MMU,bit1 对其控制位,bit2控制D Cache的打开与关闭。bit11用于控制分支预测,bit12用于控制I Cache。*/
/* 关闭I,DCache和MMU
* 采取读-改-写的方式。
*/
mrc p15, 0, r0, c1, c0, 0 /* 读取CP15的C1寄存器到R0中 */
bic r0, r0, #(0x1 << 12) /* 清除r0寄存器的bit12位(I位),关闭I Cache */
bic r0, r0, #(0x1 << 2) /* 清除r0寄存器的bit2(C位),关闭D Cache */
bic r0, r0, #0x2 /* 清除r0寄存器的bit1(A位),关闭对齐 */
bic r0, r0, #(0x1 << 11) /* 清除r0寄存器的bit11(Z位),关闭分支预测 */
bic r0, r0, #0x1 /* 清除r0寄存器的bit0(M位),关闭MMU */
mcr p15, 0, r0, c1, c0, 0 /* 将r0寄存器中的值写入到CP15的C1寄存器中 */
/*2)设置中断向量表偏移
将新的中断向量表首地址写入到CP15协处理器的VBAR寄存器。*/
MCR{cond} p15,<opc1>,<Rt>,<CRn>,<CRm>,<opc2>
MRC p15,0,r0,c12,c0,0 //读CP15寄存器
MCR p15,0,r0,c12,c0,0 //写CP15寄存器
/* 汇编版本设置中断向量表偏移,一定要在中断发生之前设置! */
//注:此处屏蔽掉是因为在C语言进行中断初始化中进行了中断向量表的偏移,因此汇编和C只需初始化一个即可
ldr r0, =0X87800000
dsb /* 数据同步指令 */
isb /* 指令同步指令 */
mcr p15, 0, r0, c12, c0, 0 /* 将r0寄存器中的值写入到CP15的C12寄存器中,设置VBAR寄存器=0x87800000*/
dsb /* 数据同步指令 */
isb /* 指令据同步指令 */
/*3)设置处理器9种工作模式对应的SP指针。要使用中断那么必须设置IRQ模式下的SP指针。索性直接设置所有模式下的SP指针。*/
/* 设置各个模式下的栈指针(SP指针),
* 注意:IMX6UL的堆栈是向下增长的!
* 堆栈指针地址一定要是4字节地址对齐的!!!
* DDR范围:0X80000000~0X9FFFFFFF
*/
/* 进入IRQ模式 */
mrs r0, cpsr
bic r0, r0, #0x1f /* 将r0寄存器中的低5位清零,也就是cpsr的M0~M4 */
orr r0, r0, #0x12 /* r0或上0x12,表示使用IRQ模式 */
msr cpsr, r0 /* 将r0 的数据写入到cpsr_c中 */
ldr sp, =0x80600000 /* 设置IRQ模式下的栈首地址为0X80600000,大小为2MB */
/* 进入SYS模式 */
mrs r0, cpsr
bic r0, r0, #0x1f /* 将r0寄存器中的低5位清零,也就是cpsr的M0~M4 */
orr r0, r0, #0x1f /* r0或上0x1f,表示使用SYS模式 */
msr cpsr, r0 /* 将r0 的数据写入到cpsr_c中 */
ldr sp, =0x80400000 /* 设置SYS模式下的栈首地址为0X80400000,大小为2MB */
/* 进入SVC模式 */
mrs r0, cpsr
bic r0, r0, #0x1f /* 将r0寄存器中的低5位清零,也就是cpsr的M0~M4 */
orr r0, r0, #0x13 /* r0或上0x13,表示使用SVC模式 */
msr cpsr, r0 /* 将r0 的数据写入到cpsr_c中 */
ldr sp, =0X80200000 /* 设置SVC模式下的栈首地址为0X80200000,大小为2MB */
/*这里只设置了三种模式的栈指针,至于其余六种模式可自行设置!*/
/*4)跳到c函数,也就是main函数。*/
b main /* 跳转到 main 函数 */
可以看出,系统初始化工作也是在Reset_Handler复位中断中完成的,并且在完成系统初始化之后就会跳转到main函数执行,且不会再返回。
|