App一般运行于usr Mode,此模式受限比如不可访问硬件。故App想访问硬件,必须发生异常切换模式。
故意加入一条命令触发异常:swi 0x123,如若运行到此指令,cpu将强制跳至0x8地址执行程序。
- 复位之后,cpu处于svc模式,先需要切换到usr模式
mrs r0,cpsr //读出cpsr
bic r0,r0,#0xf //修改M4-M0为0b10000,进入usr模式
msr cpsr,r0
- 设置sp_usr的栈
ldr sp,=0x33f00000
- swi处理函数
do_swi:
ldr sp,=0x33e00000 //设置栈
//保存现场
stmdb sp!,{r0-r12,lr}
//处理und异常
mrs r0,cpsr
ldr r1,=swi_string
bl printException
//恢复现场
ldmia sp!,{r0-r12,pc}^ //会把spsr的值恢复到cpsr里
swi_string:
.string "swi exception"
.align 4
如果想要知道发生异常指令的值是什么(例如:0x123),可将程序做以下修改:
//保存现场
stmdb sp!,{r0-r12,lr}
mov r4,lr //保存lr寄存器的地址
//处理und异常
mrs r0,cpsr
ldr r1,=swi_string
bl printException
sub r0,r4,#4
bl printSWIval //打印函数
void printSWIval(unsigned int *pSWI)
{
puts("SWI Val =");
puthex(*pSWI & ~0xff000000);
puts("\n\r");
}
- 根据ATPCS规则,r4寄存器不会被C函数破坏,故可以将lr寄存器的值存放在r4寄存器中。
- 由于lr寄存器保存有被中断模式的下一条指令的地址,故要打印的值的地址是lr寄存器保存的地址-4。
版权声明:本文为weixin_43413538原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。