《ARM的SWI异常中断处理程序设计.ppt》由会员分享,可在线阅读,更多相关《ARM的SWI异常中断处理程序设计.ppt(14页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、ARM的SWI异常中断处理程序设计 通过SWI异常中断指令,在用户模式下应用程序可以调用系统模式下的代码。在实时操作系统中,通常使用SWI异常中断为用户应用程序提供系统功能的调用。一一.SWI异常中断处理程序的实现异常中断处理程序的实现在SWI指令中包括一个24位的立即数(中断调用号),该立即数指示了用户要请求的特定功能,所以需要在SWI的异常中断中读取这个中断号,然后根据中断号,来调用相应的处理程序。处理过程:(1)SWI中断处理程序为汇编程序,用于确定SWI指令中的24位的立即数。(2)SWI异常中断处理的功能服务程序是具体实现SWI的各个功能,既可用汇编语言,也可用C语言编程。1.用汇编
2、语言编写的用汇编语言编写的SWI异常中断处理程序异常中断处理程序 由于SWI异常中断处理程序属于底层操作,所以必须用汇编语言编写。如下例所示:SWI异常中断处理程序中的bl swi_service_func指令用于调用第2步的SWI异常中断处理的功能服务程序,此函数用于实现SWI的各个功能。汇编语言编写的第1步SWI异常中断处理程序area top_swi code readonly ldmfd sp!,r0-r12,pcexport swi_headler endswi_headlerstmfd sp!,r0-r12,lrldr r0,lr,#-4bic r0,r0,#ff000000mov
3、 r1,sp;-bl swi_service_func;-2.SWI异常中断处理的中断服务程序异常中断处理的中断服务程序(用汇编写的用汇编写的)为了具体实现SWI的各个功能,须编写SWI异常中断处理的功能服务程序,它既可以是汇编语言又可以是C语言。area top_swi code readonly dcd SWIPro_1export swi_headler ;其它所有的软中断入口swi_headler SWIPro_0stmfd sp!,r0-r12,lr ;进入SWI对应立即数0的中断程序ldr r0,lr,#-4 ;对应立即数0的中断处理程序bic r0,r0,#ff000000 b
4、EndOfSWImov r1,sp SWIPro_1;判断立即数是否有效 ;进入SWI对应立即数1的中断程序cmp r0,#MaxOfSWI ;对应立即数1的中断处理程序ldrls pc,pc,r0,lsl#2 b EndOfSWI b OutOfSWIRange EndOfSWI JumpListofSWI ldmfd sp!,r0-r12,pcdcd SWIPro_0 end用用C语言编写语言编写的第2步SWI异常中断处理的中断服务程序。用C语言编写的第2步SWI异常中断处理的中断服务程序的函数原型如下:void swi_service_func(unsigned int number,u
5、nsigned int*reg)注:参数注:参数number是是SWI的中断调用号,是利用从中断处理的中断调用号,是利用从中断处理函数获得的中断调用号。函数获得的中断调用号。参数参数reg是是SWI 异常中断第异常中断第1步中中断处理程序传递来的步中中断处理程序传递来的数据栈指针。数据栈指针。在第1步的SWI异常中断处理程序调用第2步中断处理程序的操作如下:mov r1,sp ;根据ATPCS将r1中的值作为第二参数传入bl swi_service_func ;调用功能服务函数,中断调用号通 过r0传入,参数通过r1传入第2步SWI异常中断处理的中断服务程序代码如下:void swi_serv
6、ice_func(unsigned int number,unsiged int*reg)unsigned int reg1,reg2,reg3,reg4;/获取 SWI传入的参数reg1=reg0;reg2=reg1;reg3=reg2;reg4=reg3;switch(number)case 0:/do something break;case 1:/do somethingbreak;case n:/do somethingbreak;default:/do somethingreg0=updata_reg1;reg1=updata_reg2;reg2=updata_reg3;reg3=
7、updata_reg4;二、SWI异常中断调用异常中断调用1.特权模式下调用特权模式下调用SWI 执行SWI指令后,系统将会把CPSR寄存器的内容保存在寄存器SPSR_svc中,将返回地址保存在寄存器LR_svc中。如果在执行的SWI指令已经在svc模式下时,这时SPSR_svc和LR_svc中的内容就会被破坏。因此在特权模式下调用SWI功能(执行SWI指令),就必须将原始的寄存器SPSR_svc和LR_svc的值保存在数据栈中。area top_swi code readonly export swi_headler swi_headlerstmfd sp!,r0-r3,r12,lr;保存S
8、PSR_svcmov r1,spMRS r0,spsrstmfd sp!,r0;读取SWI指令ldr r0,lr,#-4bic r0,r0,#ff000000bl swi_service_funcldmfd sp!,r0;恢复调用前的r0MSR spsr_cf,r0ldmfd sp!,r0-r3,r12,pcend二、SWI异常中断调用异常中断调用2.从应用程序中调用从应用程序中调用SWI (1)使用汇编指令调用特定的SWI功能 (2)用C程序调用特定的SWI功能注意:汇编指令调用特定的SWI功能只要将所需的参数按ATPCS要求放置在相应的寄存器中,然后在指令SWI中指定相应24位立即数即可。
9、例:用汇编指令实现SWI的调用。SWI中断处理程序所需的参数放在寄存器r0中,然后调用功能号0 x0的SWI功能调用。MOV r0,#100SWI 0 x0二、SWI异常中断调用异常中断调用2.从应用程序中调用从应用程序中调用SWI C程序中调用特定的SWI功能比汇编语言调用要复杂一些,因为C语言中调用特定的SWI 特定功能需将C程序的子程序调用映射到一个SWI异常中断处理程序。这些被映射的C语言子程序使用编译器伪操作_ _SWI来声明。该子程序所需的参数和返回的结果放在R0R3中,则该SWI可以被视为inline,不需要使用子程序调用过程;否则必须告诉编译器通过结构数据类型来返回参数,这时需
10、要使用编译器伪操作_value_in_reg声明该C语言子程序。例:提供4个SWI功能调用,功能号分别为0 x00,0 x01,0 x02,0 x03。其中SWI 0 x0和SWI0 x1使用两个整型的输入参数,并返回一个结果值;SWI 0 x2使用4个输入参数,并返回一个结果值;SWI0 x3使用4个输入参数,并返回4个结果。C程序中调用特定的SWI功能程序代码:/*头文件swi.h*/_ _swi(0)int multiply_two(int,int);_ _swi(1)int add_two(int,int);_ _swi(2)int add_multiply_two(int,int,i
11、nt,int);struct four_resultsint a;int b;int c;int d;_swi(3)_ _value_in_regs struct four_resultsmany_operations(int,int,int,int);/*主程序main()*/#include#include swi.hunsigned*swi_vec=(unsigned*)0 x08;extern SWI_Handler;/*使用Install_Handler()安装 SWI异常中断处理程序*/unsigned Install_Handler(unsigned routine,unsign
12、ed*vector)unsigned vec,old_vec;vec=(routine-(unsigned)vector-8)2;if(vec&0 xff000000)printf(Handler greater than 32M from vector);vec=0 xea000000|vec;old_vec=*vector;*vector=vec;return(old_vec);unsigned Install_Handler(unsigned routine,unsigned*vector)unsigned vec,old_vec;vec=(routine-(unsigned)vecto
13、r-8)2;if(vec&0 xff000000)printf(Handler greater than 32M from vector);vec=0 xea000000|vec;old_vec=*vector;*vector=vec;return(old_vec);在中断向量表中使用跳转指令在中断向量表中使用跳转指令安装异常中断处理程序的操作如下:安装异常中断处理程序的操作如下:(1)读取中断处理程序的地址)读取中断处理程序的地址(2)从步骤()从步骤(1)得到的地址中减)得到的地址中减去该异常中断对应的中断向量的去该异常中断对应的中断向量的地址地址(3)从步骤()从步骤(2)得到的地址中减
14、)得到的地址中减去去8,以允许指令预取,以允许指令预取(4)将步骤()将步骤(3)得到的地址左移)得到的地址左移2位,得到字为单位的偏移量位,得到字为单位的偏移量(5)确保步骤()确保步骤(4)得到的地址值)得到的地址值的高的高8位为位为0,因为跳转指令只,因为跳转指令只允许允许24位的偏移量位的偏移量(6)将步骤()将步骤(5)得到的地址与数)得到的地址与数据据0Xea000000进行逻辑或,从进行逻辑或,从而得到将要写到中断向量表中的而得到将要写到中断向量表中的跳转指令的编码。跳转指令的编码。int main(void)int result1,result2;struct four_res
15、ults res_3;Install_Handler(unsigned)SWI_Handler,swi_vec);printf(result1=multiply_two(2,4)=%dn,result1=multiply_two(2,4);printf(result2=multiply_two(3,6)=%dn,result2=multiply_two(3,6);printf(add_two(result1,result2)=%dn,add_two(result1,result2);printf(add_multiply_two(2,4,3,6)=%dn,add_multiply_two(2,
16、3,4,6);res_3=many_operations(12,4,3,1);printf(res_3.a=%dn,res_3.a);printf(res_3.b=%dn,res_3.b);printf(res_3.c=%dn,res_3.c);printf(res_3.d=%dn,res_3.d);return 0;第1步SWI异常中断处理程序swi_handlerarea swi _area code readonly export c_swi_handler t_bit EQU 0 x20 swi_handlerstmfd sp!,r0-r3,r12,lrmov r1,spMRS r0,
17、spsrstmfd sp!,r0tst r0,#t_bitldrneh r0,lr,#-2bicne r0,r0,#0 xff00ldreq r0,lr,#-4biceq r0,r0,#0 xff000000bl c_swi_handlerldmfd sp!,r0msr spsr_cf,r0ldmfd sp!,r0-r3,r12,pcend;第2步SWI异常中断处理程序void c_swi_handler()switch(swi_num)case 0:regs0=regs0*regs1;break;case 1:regs0=regs0+regs1;break;case 2:regs0=(regs0*regs1)+(regs2*regs3);break;case 3:int w,x,y,z;w=regs0;x=regs1;y=regs2;z=regs3;regs0=w+x+y+z;regs1=w-x-y-z;regs2=w*x*y*z;regs3=(w+x)*(y-z);break;