首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

ARM 软件中断指令SWI讲解(1)

ARM 软件中断指令SWI讲解(1)

一、软件中断
       软中断是利用硬件中断的概念,用软件方式进行模拟,实现从用户模式切换到特权模式并执行特权程序的机制。
       硬件中断是由电平的物理特性决定,在电平变化时引发中断操作,而软中断是通过一条具体指令SWI,引发中断操作,也就是说用户程序里可以通过写入SWI指令来切换到特权模式,当CPU执行到SWI指令时会从用户模式切换到管理模式下,执行软件中断处理。由于SWI指令由操作系统提供的API封装起来,并且软件中断处理程序也是操作系统编写者提前写好的,因此用户程序调用API时就是将操作权限交给了操作系统,所以用户程序还是不能随意访问硬件。

    软件中断指令(Software Interrupt, SWI用于产生软中断,实现从用户模式变换到管理模式,CPSR保存到管理模式的SPSR中,执行转移到SWI向量。在其他模式下也可以使用SWI指令,处理器同样切换到管理模式。
1SWI指令格式如下:
   SWI{cond} immed_24
其中:
immed_24  24位立即数,值为从0――16777215之间的整数。
       SWI指令后面的24立即数是干什么用的呢?用户程序通过SWI指令切换到特权模式,进入软中断处理程序,但是软中断处理程序不知道用户程序到底想要做什么?SWI指令后面的24位用来做用户程序和软中断处理程序之间的接头暗号。通过该软中断立即数来区分用户不同操作,执行不同内核函数。如果用户程序调用系统调用时传递参数,根据ATPCSC语言与汇编混合编程规则将参数放入R0~R4即可。

2、指令举例
      使用SWI指令时,通常使用以下两种方法进行参数传递,SWI异常处理程序可以提供相关的服务,这两种方法均是用户软件协定。SWI异常中断处理程序要通过读取引起软件中断的SWI指令,以取得24为立即数。
1)、指令中24位的立即数指定了用户请求的服务类型,中断服务的参数通过通用寄存器传递。
如下面这个程序产生一个中断号位12 的软中断:
MOV R0,#34                    ;设置功能号为34
SWI 12                              ;产生软中断,中断号为12
2)、指令中的24位立即数被忽略,用户请求的服务类型有寄存器R0的值决定,参数通过其他的通用寄存器传递。
如下面的例子通过R0传递中断号,R1传递中断的子功能号:
MOV R0, #12                  ;设置12号软中断
MOV R1, #34                  ;设置功能号为34
SWI  0

      下面的例子通过系统调用函数int led_on(int led_no)实现点亮第led_no LED灯,由于C语言里没有SWI 指令对应的语句,因此这儿要用到C语言与汇编混合编程,led_on函数里将参数led_no的值传递给R0,通过软中断SWI指令切换到软中断管理模式,同时R0 软中断方式点亮LED灯,用户通过SWI  #1指令可以点灯,具体点亮哪个灯,通过R0保存参数传递,如果亮灯成功返回对应LED号。


[cpp] view plain copy


  • #define __led_on_swi_no         1                 // 软中断号1,调用管理模式下的do_led_on函数
  • int led_on(int led_no){  

  •          int ret;                                 // 返回值
  •           __asm{                                   // 由于C程序中没有SWI对应表达式,所以使用混合编程
  •                    mov  r0, led_no                  // 根据ATPCS规则,r0存放第一个参数
  •                    swi    __led_on_swi_no           // 产生SWI软中断,中断号为__led_on_swi_no

  •                    mov  ret, r0                   // 软中断处理结束,取得中断处理返回值,传递给ret变量
  •          }  

  •          return ret;                              // 将ret返回给调用led_on的语句
  • }  
返回列表