ARM 软中断指令SWI

发布者:SparklingMoon最新更新时间:2020-04-03 来源: eefocus关键字:ARM  软中断指令  SWI 手机看文章 扫描二维码
随时随地手机看文章

前面我们学习ARM工作模式中,处理器模式切换可以通过软件控制进行切换,即修改CPSR模式位,但这是在特权模式下,当我们处于用户模式下,是没有权限实现模式转换的。若想实现模式切换,只能由另一种方法来实现,即通过外部中断或是异常处理过程进行切换。于是ARM指令集中提供了两条产生异常的指令,通过这两条指令可以用软件的方法实现异常,其中一个就是中断指令SWI 。

 

一、软件中断

软中断是利用硬件中断的概念,用软件方式进行模拟,实现从用户模式切换到特权模式并执行特权程序的机制。


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

    

软件中断指令(Software Interrupt, SWI)用于产生软中断,实现从用户模式变换到管理模式,CPSR保存到管理模式的SPSR中,执行转移到SWI向量。在其他模式下也可以使用SWI指令,处理器同样切换到管理模式。


1、SWI指令格式如下:

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号。


#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的语句
}


二、软中断处理

CPU执行到swi xxx执行后,产生软件中断,由异常处理部分知识可知,软中断产生后CPU将强制将PC的值置为异常向量表地址0x08,在异常向量表0x08处安放跳转指令b HandleSWI,这样CPU就跳往我们自己定义的HandleSWI处执行。


1--保护现场 

软中断处理中通过STMFD  SP!, {R0-R12,  LR}      要保存程序执行现场,将R0~R12通用寄存器数据保存在管理模式下SP栈内,LR由硬件自动保存软中断指令下一条指令的地址(后面利用LR的地址取得SWI指令编码),该寄存器值也保存在SP栈内,将来处理完毕之后返回;


2--获取SWI指令编码

由SWI指令编码知识可知,SWI指令低24位保存有软中断号,通过LDR R4, [LR, #-4]指令,取得SWI指令编码(LR为硬件自动保存SWI xxx指令的下一条指令地址,LR – 4就是SWI指令地址),将其保存在R4寄存器中。通过BIC      R4, R4, #0xFF000000 指令将SWI指令高8位清除掉,只保留低24位立即数,取得SWI指令编码;


3--根据SWI指令做出相应操作

根据24位立即数中的软中断号判断用户程序的请求操作。如果24位立即数为1,表示led_on系统调用产生的软中断,则在管理模式下调用对应的亮灯操作do_led_on。如果24位立即数为2,表示led_off系统调用产生的软中断,则调用灭灯操作do_led_on,根据ATPCS调用规则,R0~R3做为参数传递寄存器,在软中断处理中没有使用这4个寄存器,而是使用R4作为操作寄存器的。


4--返回并恢复现场 

执行完系统调用操作之后,返回到swi_return(在调用对应系统操作时,通过LDREQ    LR, =swi_return设置了返回地址),执行返回处理,通过LDMIA    SP!, {R0-R12, PC}^ 指令将用户寄存器数据恢复到R0~R12,将进入软中断处理时保存的返回地址LR的值恢复给PC,实现程序返回,同时还恢复了状态寄存器。切换回用户模式下程序中继续执行。


; 异常向量表开始
; 0x00: 复位Reset异常
         b       Reset 
 
 
 
; 0x04: 未定义异常(未处理)
HandleUndef
 
           b       HandleUndef 
 
 
 
; 0x08: 软件中断异常,跳往软件中断处理函数HandleSWI
 
    b         HandleSWI
 
… …
 
; 省略其它异常向量和对应处理
… …
 
;***********************************************************************
 
; 软中断处理
;*********************************************************************** 
 
IMPORT do_led_on
 
IMPORT do_led_off
 
HandleSWI
 
         STMFD     SP!, {R0-R12,  LR}            ; 保存程序执行现场
         LDR R4, [LR, #-4]                                   ; LR - 4 为指令" swi xxx" 的地址,低24位是软件中断号
         BIC   R4, R4, #0xFF000000                    ; 取得ARM指令24位立即数
           
 
         CMP          R4, #1                                    ; 判断24位立即数,如果为1,调用do_led_on系统调用
         LDREQ     LR, =swi_return                    ; 软中断处理返回地址
         LDREQ     PC, = do_led_on                    ; 软中断号1对应系统调用处理
           
 
         CMP          R4, #2                                    ; 判断24位立即数,如果为2,调用do_led_off系统调用
         LDREQ     LR, =swi_return                    ; 软中断处理返回地址
         LDREQ     PC, = do_led_off                            ; 软中断号2对应系统调用处理
           
 
         MOVNE    R0, #-1                                   ; 没有该软中断号对应函数,出错返回-1
 
swi_return 
 
         LDMIA     SP!, {R0-R12, PC}^             ; 中断返回, ^表示将spsr的值复制到cpsr


其实讲到这,会产生一个疑问,什么时候需要我们从用户模式切换到管理模式?我们应该记得系统调用,就是用户态向内核态的切换。


三、系统调用

操作系统的主要功能是为应用程序的运行创建良好的环境,保障每个程序都可以最大化利用硬件资源,防止非法程序破坏其它应用程序执行环境,为了达到这个目的,操作系统会将硬件的操作权限交给内核来管理,用户程序不能随意使用硬件,使用硬件(对硬件寄存器进行读写)时要先向操作系统发出请求,操作系统内核帮助用户程序实现其操作,也就是说用户程序不会直接操作硬件,而是提供给用户程序一些具备预定功能的内核函数,通过一组称为系统调用的(system call)的接口呈现给用户,系统调用把应用程序的请求传给内核,调用相应的内核函数完成所需的处理,将处理结果返回给应用程序。


这好比我们去银行取款,用户自己的银行帐户不可能随意操作,必须要有一个安全的操作流程和规范,银行里的布局通常被分成两部分,中间用透明玻璃分隔开,只留一个小窗口,面向用户的是用户服务区,工作人员所在区域为内部业务操作区,取款时,将银行卡或存折通过小窗口交给业务员,并且告诉他要取多少钱,具体取钱的操作你是不会直接接触的,业务员会将银行帐户里减掉取款金额,将现金给你。上述操作流程可以很好保护银行系统,银行系统的操作全部由业务员来实现,用户只能向业务员提出自己的服务请求。银行里的小窗口就类似与操作系统的系统调用接口,是将用户请求传递给内核的接口。  

操作系统里将用户程序运行在用户模式下,并且为其分配可以使用内存空间,其它内存空间不能访问,内核态运行在特权模式下,对系统所有硬件进行统一管理和控制。从前面所学知识可以了解到,用户模式下没有权限进行模式切换,这也就意味着用户程序不可能直接通过切换模式去访问硬件寄存器,如果用户程序试图访问没有权限的硬件,会产生异常。这样用户程序被限制起来,如果用户程序想要使用硬件时怎么办呢?用户程序使用硬件时,必须调用操作系统提供的API接口才可以,而操作系统API接口通过软件中断方式切换到管理模式下,实现从用户模式下进入特权模式。


At91rm9200处理器对应的linux2.4.19内核系统调用对应的软中断定义如下:


#if defined(__thumb__)                             //thumb模式
#define __syscall(name)                          
    "push    {r7}nt"                          
    "mov    r7, #" __sys1(__NR_##name) "nt"    
    "swi    0nt"                              
    "pop    {r7}"
#else                                              //arm模式
#define __syscall(name) "swit" __sys1(__NR_##name) "nt"
#endif
 
#define __sys2(x) #x
#define __sys1(x) __sys2(x)
#define __NR_SYSCALL_BASE    0x900000               //此为OS_NUMBER << 20运算值
#define __NR_open            (__NR_SYSCALL_BASE+ 5) //0x900005 



举一个例子来说:open系统调用,库函数最终会调用__syscall(open),宏展开之后为swi #__NR_open,即,swi #0x900005触发中断,中断号0x900005存放在[lr,#-4]地址中,处理器跳转到arch/arm/kernel/entry-common.S中vector_swi读取[lr,#-4]地址中的中断号,之后查询arch/arm/kernel/entry-common.S中的sys_call_table系统调用表,该表内容在arch/arm/kernel/calls.S中定义,__NR_open在表中对应的顺序号为

__syscall_start: 

.long    SYMBOL_NAME(sys_open)                     //第5个
...
将sys_call_table[5]中内容传给pc,系统进入sys_open函数,处理实质的open动作
注:用到的一些函数数据所在文件,如下所示
arch/arm/kernel/calls.S声明了系统调用函数
include/asm-arm/unistd.h定义了系统调用的调用号规则
vector_swi定义在arch/arm/kernel/entry-common.S
vector_IRQ定义在arch/arm/kernel/entry-armv.S
vector_FIQ定义在arch/arm/kernel/entry-armv.S
arch/arm/kernel/entry-common.S中对sys_call_table进行了定义:
    .type    sys_call_table, #object
ENTRY(sys_call_table)
#include "calls.S"                                 //将calls.S中的内容顺序链接到这里

[1] [2]
关键字:ARM  软中断指令  SWI 引用地址:ARM 软中断指令SWI

上一篇:ARM中断异常处理的返回的问题
下一篇:ARM程序异常返回操作

推荐阅读最新更新时间:2024-11-16 22:47

就是要较这几纳米的劲儿
最近台积电与ARM公司联合宣布,基于他们在20nm和16nm工艺上成功的合作经验,未来双方将以10nm FinFET工艺合作打造ARMv8-A架构的64位ARM处理器,预计最快可在2015年第四季度开始就可以为客户提供基于10nm FinFET技术的64位ARM处理器的设计方案。 台积电与ARM公司已经开展多年合作,他们早前在20nm和16nm工艺上就已经有相当丰富的合作经验,双方确信未来10nm FinFET工艺将为ARM处理器行业带来更加的效能和功耗优势。早前台积电与ARM已经完成16nm FinFET工艺下的64位big.LITTLE架构ARM处理器的生产验证,华为海思也成为了台积电16nm FinFET工艺的首个客户。
[单片机]
利用单ARM7处理器对无刷电机实施磁场定向控制
电机驱动能效不论提高多少,都会节省大量的电能,这就是市场对先进的电机控制算法的兴趣日浓的部分原因。三相无刷电机主要指是交流感应异步电机和永磁同步电机。这些电机以能效高、可靠性高、维护成本低、产品成本低和静音工作而著称。感应电机已在水泵或风扇等工业应用中得到广泛应用,并正在与永磁同步电机一起充斥家电、空调、汽车或伺服驱动器等市场。推动三相无刷电机发展的主要原因有:电子元器件的价格降低,实现复杂的控制策略以克服本身较差的动态性能成为可能。 以异步电机为例。简单的设计需要给定子施加三个120°相移的正弦波电压,这些绕组的排列方式能够产生一种旋转磁通量。利用变压器效应,这个磁通量在转子笼内感应出一股电流,然后产生转子磁通量。就
[单片机]
基于ARM9和Linux的液晶驱动终端设计
1 引言 目前.已有的液晶驱动终端主要采用微控制器与前、后台软件结合的方法进行设计,该类终端只能够显示字模方式的图片.该种类型的终端显示数据存放在自带的NANDFlash中, 在人机界面设计过程中对NAND Flash中的数据管理是以扇区为基本操作单元,图片下载需要专用的软件工具完成,增加了界面设计的逻辑复杂性与操作性。这里采用ARM9微控制器与 Linux操作系统结合的方法,设计出一种新型的液晶驱动终端。该终端通过FAT文件系统管理CF卡中数据资源,利用多线程技术实现串口命令解析与图型界面的显示,不仅能够显示字模与图片等数据资源,而且利用该设计方法可以实现调用MiniGUI图型库等资源,适用于工业测控、智能仪表等领域的人机界
[单片机]
基于<font color='red'>ARM</font>9和Linux的液晶驱动终端设计
DCS控制器中采用ARM处理器的冗余设计
在自动化的许多领域,有效性的要求越来越高,因而对自动化系统的容错水平的要求也变得越来越高,尤其在设备停机代价非常大的场合。为了满足这些严格的要求,在DCS系统中通常采用冗余技术,这样才能够满足这些领域所需要的安全性、可靠性和有效性的标准。 在DCS控制系统中,分布处理单元是系统关键的部分。当前这些分布处理单元的控制器往往是基于86系列CPU建构的,这种架构目前被广泛采用。但是由于86系列分布处理单元的特点,导致现在的控制器处理单元存在很多的缺点,如放热量大等。而且在封闭的环境中,这些问题始终很难解决。随着很多低功耗技术的发展和低功耗控制器的出现,分布处理单元的CPU可以有更多的选择,尤其是低功耗的控制器产生很少的热量,且可以使系统
[嵌入式]
学习嵌入式系统(ARM)的一些想法
在学习单片机的时候学的比较快,在学51和AVR的时候都可以说是得心应手。可能就是手前面学习的影响,认为学ARM也会比较顺利。到开始学习ARM的时候才知道要入门是多么“痛苦”,每天就对着教程、资料折磨。没有多少是学的明白的,完全不知道怎么学起。它涉及的内容和知识太多了。我整理了一下这段时间的学习资料,我已经看完的和我接下来要用的,总共29 G,我前10年读书用的资料都可能没有这么多。 学ARM不能再和以前学单片机那样,刚开始时,不能说从哪里开始学。只有拿着资料、教程慢慢磨。久了就积累了一定的知识就会明白了,这个过程的滋味只有做过才能体会。前些天也实在很困惑无从下手。然后就下定决心从Entry入手,从CPU的第一条指令开始,跟着走下
[单片机]
Nordic Semiconductor 与 Arm 扩展合作关系
签署最新低功耗处理器设计、软件平台和安全 IP 许可协议 Nordic签署 Arm Total Access 授权许可协议,确保其现有和未来的多协议、Wi-Fi、蜂窝物联网和DECT NR+ 产品具备业界领先的处理器和安全技术 挪威奥斯陆 – 2024年2月20日 – Nordic Semiconductor宣布与世界领先的半导体设计和软件平台企业Arm签署一项多年期Arm Total Access (ATA)授权许可协议 。ATA 保证为Nordic当前和未来的产品 (包括多协议、Wi-Fi、蜂窝物联网和 DECT NR+ 解决方案) 提供广泛的Arm® IP、工具、支持和培训。 两家企业的合作始于 2012
[物联网]
Nordic Semiconductor 与 <font color='red'>Arm</font> 扩展合作关系
基于Keil MDK-ARM 和 IAR EWARM进行仿真打印的配置
1写在前面 很多初学者习惯使用软件仿真,应该是很多人都知道的一款仿真软件。 以前开发板相对较贵,且快递不方便,使用仿真软件可以理解。现在便宜的STM32开发板就十几块,还用仿真软件,我不是很理解。 有经验的人都知道,仿真和实际运行情况很多时候都不一样,相信不用我说,大家都明白。 因此,我个人不是很推荐大家仿真,本文内容可能存在纰漏,仅限个人学习。 下面讲述基于Keil MDK-ARM 和 IAR EWARM进行仿真打印的配置。 2Keil仿真打印配置 Keil MDK-ARM不能仿真,原因出在仿真参数出现了问题: 修改这两处参数为:DARMSTM.DLL -pSTM32F103ZE 基于前面使用STM32CubeMX生成工
[单片机]
基于Keil MDK-<font color='red'>ARM</font> 和 IAR EWARM进行仿真打印的配置
恩智浦四款32位ARM9 MCU
2008年3月28日,恩智浦半导体推出了全新的LPC3200系列微控制器,进一步扩展了其ARM7™ 和ARM9™ 微控制器产品线。恩智浦LPC3200系列基于ARM926EJ™ 处理器,针对消费电子、工业、医疗和汽车电子应用,为设计师提供一种高性能、高功耗效率的微控制器。恩智浦LPC3200微控制器系列包括LPC3220、LPC3230、LPC3240和LPC3250。 恩智浦LPC3200系列采用90纳米工艺设计,结合了一个ARM926EJ核、一个矢量浮点协处理器(VFP)、一个LCD控制器、一个以太网MAC、On-The-Go USB、一个高效的总线阵列以及大量的标准外设,使得嵌入式系统设
[新品]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved