arm7下swi中断模拟程序步步学

本文介绍了中断使用的swi模式,包括USER状态可用寄存器、特权模式PC处理情况、中断返回工作等。还提到SWI中断产生时PC值的特点及_swi修饰的使用。最后给出示例,涵盖swi.h文件、handle.s文件、lib.c文件的代码编写及主处理函数,展示了SWI中断的调用与处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

介绍个中断使用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;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值