介绍个中断使用swi模式
特权模式superisor svc供OS使用的一个保护模式
其实也是一个中断,对于硬件用户不可干扰确切的来说是用户定义中断模式
1.了解正常状态USER状态的可用寄存器
R0~R7通用 R8~R12独立寄存器[有些模式寄存器组是独立] R13-SP[各自独立] R14-LR[独立] PC[通用] CPSR[独立]
r0~r7通用寄存器同PC下的通用寄存器一样
R8~R12 作为备份寄存器 ,可以使用r0~r7均可使用他们
r13作为堆栈指针
r14作为连接寄存器存放当前子程序返回的地址
PC ARM是三级流水线所以PC总是为当前执行指令+8处 ARM下指令是字对齐所以低两位为0
CPSR 就是当前状态寄存器保存当前执行的各种情况
2.了解一下特权模式在PC处理时发生的事情
正常执行指令PC+4(均指ARM状态下)发生函数调用时STMFD SP!, {REGISTER, LR} STMFD SP!, { REGISTER, PC }
来进行寄存器入栈和LR连接寄存器函数返回地址入栈
完成后进行寄存器出栈和将LR的值即返回地址赋给PC返回
遇到中断指SWI(FIQ, IRQ)有所不同时
(a)保存CPU当前状态 将CPSR->特权模式下的SPSR
(B)设置当前模式下CPRS的相应的位 比如进FIQ模式禁止FIQ中断...
(c)特权模式下独立连接寄存器 LR保存中断返回地址
(d)PC设置为当前中断向量地址跳转执行中断代码
3. 中断返回时的工作
(a)恢复当前处理器状态SPSR->正常模式的CPSR
(b)恢复PC,LR->当前PC
4.SWI中断是本身执行指令产生 所以当产生中断时PC值不会更新为当前指令+8地址处
所以PC-4为恢复中断地址。这里是要注意的
5._swi 修饰用于SWI中断调用
中断不返回形式 void _swi(swi_num) swi_name(arguments);
返回一个结果R0中 int _swi(swi_num) swi_name(arguments);
可以用结构最多返回四个结果r0-r3
struct type{ int a, b, c, d; };
type(返回类型) _value_in_regs(返回多个结果的修饰符) _swi(swi_num) swi_name(arguments);
然后开始EXAMPLE
建立swi.h文件存放结构和swi函数声明
__swi(0) int test1(int,int); //两个参数返回r0,地址偏移为0
struct mystruct //定义返回结构体
{
int a;
int b;
int c;
int d;
};
__swi(1) __value_in_regs struct mystruct
test2(int,int,int,int); //声明1自定义中断
建立中断一及处理文件handle.s
IMPORT c_handle_swi //引入二及中断 处理
EXPORT SWI_Handle //到出中断处理函数
AREA SWIHandle,CODE,READONLY
SWI_Handle
STMFD SP!, {r0-r3, r12, lr}
;保存SPSR_svc
mov r1, sp
MRS r0, spsr //保存spsr
STMFD sp!, {r0} //入栈
LDR r0, [lr, #-4]
BIC r0, r0, #0xFF000000//得到24立即数放到R0中
BL c_handle_swi //二及调用
LDMFD SP!, {r0}
MSR spsr_cf, r0
LDMFD SP!, {r0-r3, r12, pc}^
END
建立lib.c文件提供中断函数处理代码
void c_handle_swi( int swi_num, int *regs )
{
switch(swi_num)
{
case 0: //_swi(0)
regs[0] = regs[0]*regs[1];
break;
case 1: //_swi(1)
{
int x, y, z, p;
x = regs[0];
y = regs[1];
z = regs[2];
p = regs[3];
regs[0] = x + y + z + p;
regs[1] = x + y - z - p;
regs[2] = x*y + z*p;
regs[3] = (x + y)*(z + p);
}
default:
break;
}
提供主处理函数
#include <stdio.h>
#include "swi.h"
unsigned *swi_vec = (unsigned*) 0x08;
extern void SWI_Handle(void);
unsigned Install_Handler( unsigned routine, unsigned *vector)
{
unsigned vec, old_vec;
vec = ( routine - (unsigned)vector - 8)>>2;
if(vec&0xFF000000)
printf("Handler greater than 32MByte from vector!");
vec = 0xea000000 | vec;
old_vec = *vector;
*vector = vec;
return old_vec;
}
int main()
{
int result1;
struct mytype res_3;
Install_Handler( (unsigned) SWI_Handle, swi_vec ); //加载信息
result1 = test1( 2, 4 ); //中断一
res_3 = test2( 12, 4, 3, 1 ); //中断二 通过watch观察结果
return 0;
}