嵌入式Linux之swi异常处理

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版权协议,转载请附上原文出处链接和本声明。