最近写一个程序,需要在用户模式下关中断,但ARM 7的体系结构决定了中断必须在特权模式下才可以更改,所以想到使用ARM的软中断来实现关中断和开中断.

使用软中断,首先要有硬件指令的支持.ARM有条指令是SWI.

SWI 指令的格式为:

SWI {条件} 24 位的立即数

SWI 指令用于产生软件中断,以便用户程序能调用操作系统的系统例程。操作系统在 SWI 的异常处理程序中提供相应的系统服务,指令中 24 位的立即数指定用户程序调用系统例程的类型,相关参数通过通用寄存器传递,当指令中 24 位的立即数被忽略时,用户程序调用系统例程的类型由通用寄存器 R0 的内容决定,同时,参数通过其他通用寄存器传递。

指令示例:

SWI  0x02       ;该指令调用操作系统编号位02的系统例程。

在keil MDK中,关键字__svc可以产生硬件SWI指令,使得处理器能响应软件中断.关键字__svc,keil MDK帮助文件中这样描述:

__svc 关键字声明超级用户调用 (SVC) 函数,该函数最多使用四个类似于整数的参数,并通过 value_in_regs 结构最多返回四个结果。
__svc 是一个函数限定符。它影响函数的类型。

语法
__svc(int svc_num) return-type function-name([argument-list]);
其中:
    svc_num 是在 SVC 指令中使用的立即值。
    它是一个表达式,其计算结果为以下范围内的整数:
         • 在 ARM 指令中为 0 到 224–1 (24 位值)
         • 在 16 位 Thumb 指令中为 0-255 (8 位值)。

要在keil MDK中使用软件中断,要做好两件事:第一件,更改启动文件,编写软件中断的汇编入口.在这个汇编入口中主要根据软件中断命令号进行相应的函数跳转.第二件,编写相应命令号的C语言服务函数.下面举例怎么样用软件中断实现开中断和关中断.

第一步:更改启动代码

keil MDK自带的启动代码有类似下面的语句:

Vectors         LDR     PC, Reset_Addr         
                     LDR     PC, Undef_Addr
                     LDR     PC, SWI_Addr
                     LDR     PC, PAbt_Addr
                     LDR     PC, DAbt_Addr

蓝色语句是程序复位后要执行的第一条指令,即复位异常入口;而红色语句就是执行一个软件中断指令后,要跳转到的软件中断异常入口.通过语句"SWI_Addr        DCD     SWI_Handler"进行中转,软件中断会跳转到标号为SWI_Handler的语句处,该处即处理软件中断的命令号.源代码如下:

EXPORT    SWI_Handler
      extern  EnableIrqFunc          ;使能中断函数名,用C语言实现
      extern  DisableIrqFunc         ;禁止中断函数名,用C语言实现
SWI_Handler
    STMFD  SP!, {R0,R12,LR}       ;入栈
    LDR      R0, [LR,#-4]               ;取指令
    BIC       R0,R0,#0xFF000000  ;取软件中断命令号
    CMP      R0,#0                        ;和0比较,因为我的使能中断用了软件中断命令0,禁止中断使用了软件中断命令1
    BLEQ     EnableIrqFunc                ;为零调用使能中断函数
    BLNE    DisableIrqFunc                ;不为零调用禁止中断函数
    LDMFD  SP!,{R0,R12,PC}^    ;出栈

第二部:编写相应命令号的C语言服务函数.

声明软件中断:

__svc(0x00) void EnableIrq(void);  //使能中断
__svc(0x01) void DisableIrq(void);  //禁止中断

编写服务函数:

void DisableIrqFunc(void)
{
    int temp;
     __asm
    {
         MRS temp,SPSR
        ORR    temp,temp,#0x80
        MSR SPSR_c,temp
    }
}
void EnableIrqFunc(void)
{
     int temp;
    __asm
    {
         MRS temp,SPSR
        BIC    temp,temp,#0x80
        MSR SPSR_c,temp
    }
}

到此,使能和禁止中断的软中断就结束了,下面看一下执行过程.

在程序中,如果想关中断,只需使用:DisableIrq();

MDK编译器在执行这句函数时,自动用软中断指令代替,即: SWI 0x01

ARM执行这条软件中断指令后,发生软件中断异常,程序跳转到软件中断异常服务函数处,即汇编代码标号为SWI_Handler处,在这里判断软件中断命令号是0x01,然后执行 BLNE    DisableIrqFunc   语句,调用禁止中断函数,实现关中断.

ARM 7 用户模式下禁止/使能中断的一种方法--使用软中断 for Keil MDK的更多相关文章

  1. CentOS单用户模式下修改ROOT密码和grub加密

    Linux 系统处于正常状态时,服务器主机开机(或重新启动)后,能够由系统引导器程序自动引导 Linux 系统启动到多用户模式,并提供正常的网络服务.如果系统管理员需要进行系统维护或系统出现启动异常时 ...

  2. windows核心编程---第七章 用户模式下的线程同步

    用户模式下的线程同步 系统中的线程必须访问系统资源,如堆.串口.文件.窗口以及其他资源.如果一个线程独占了对某个资源的访问,其他线程就无法完成工作.我们也必须限制线程在任何时刻都能访问任何资源.比如在 ...

  3. 【windows核心编程】 第八章 用户模式下的线程同步

    Windows核心编程 第八章 用户模式下的线程同步 1. 线程之间通信发生在以下两种情况: ①    需要让多个线程同时访问一个共享资源,同时不能破坏资源的完整性 ②    一个线程需要通知其他线程 ...

  4. 在单用户模式下修改CentOS的root密码

    我们在使用CentOS的过程中可能会发生忘记root用户密码的情况,本文就从应用的角度简单介绍一下如何在单用户模式下修改root用户的密码. 开启CentOS,进入系统启动菜单 将光标停留在系统开机时 ...

  5. 设置GRUB密码以防止单用户模式下root密码被恶意更改

    在使用LInux系统的时候可能会发生忘记root密码的情况,通常管理员会进入单用户模式下进行重置root密码.那么问题来了,既然管理员可以进入单用户模式,如果恶意用户可以接触的到计算机的话毫无疑问也是 ...

  6. 线程同步——用户模式下线程同步——Interlocked实现线程同步

    线程同步分为用户模式下的线程同步和内核对象的线程同步. 当然用户模式下的线程同步实现速度比内核模式下快,但是功能也有局 //1.利用原子访问: Interlocked系列函数,关于Interlocke ...

  7. CentOS6.8单用户模式下修改密码

    CentOS6.8单用户模式下修改密码 1. 选择进入菜单menu界面,在开启系统出现如下界面时,按Esc键(只需按一下) 2. 然后进入到如下界面 3. 上图中红色矩形类的内容,按“a”键可以修改内 ...

  8. Windows核心编程:第8章 用户模式下的线程同步

    Github https://github.com/gongluck/Windows-Core-Program.git //第8章 用户模式下的线程同步.cpp: 定义应用程序的入口点. // #in ...

  9. Javascript 在严格模式下禁止指向 this

    如下代码, f() 输出的是 false,而 f2() 输出的是 true. 这是因为 f2 在严格模式下禁止 this 指向全局,所以 this 是 undefined, !this 当然是 tru ...

随机推荐

  1. 使用Python脚本获取指定格式文件列表的方法

    在Python环境下获取指定后缀文件列表的方式. 来源stackoverflow 这里简单以*.txt的作为例子. 使用glob(推荐) import glob, os os.chdir(" ...

  2. virtual box Failed to load unit ""pgm" 的error

    原因:没有正常的待机或者关机退出. 解决办法:右键清除保存状况.

  3. IDEA12 KeyGen Download List

    When you use IDEA to develop Java, you can use the following file to generate lincese. Because CNBlo ...

  4. sql server遍历表不用游标和临时表的方法

    表结果如图 )) ,'Sky,Blue,Water' ,'Book,Apple,Shirt' ,'Cup,Yellow,org' ,'box,phone,paper' GO SELECT id,SUB ...

  5. 【关于360极速浏览器的xx极速模式自动切换到兼容模式】

    原理上是可以的. 1  360基于Chromium 开源浏览器内核,它本身就是一个壳子.. 2  7.0之后的极速浏览器,不支持 它官方的那个声明标记.<meta name=”renderer” ...

  6. OSCHina技术导向:Java开源QQ工具iQQ

    iQQ 使用Java语言跨平台开发,基于腾讯WebQQ 3.0网络协议.可以使用于Java所支持的各种平台上运行.作者基于Linux(Ubuntu 12.04)系统,使用IDE NetBeans开发, ...

  7. UVA11988 Broken KeyBoard

    链表的思想很简单,要做到活用也不难.一般我是这样做得,从实际问题出发,先高度的概括符不符合链表的特点.能不能用链表简单解决.接着,就是编码.链表编码要理清细节性思路,最好是简单的画下图,正如改题的链表 ...

  8. poj 1742 coins_多重背包

    题意:给你N个种硬币,价值和数量,知道手表不大于m,问能组成(1~m)的价格有多少种情况 套套上次那题的模板直接就行了,http://blog.csdn.net/neng18/article/deta ...

  9. 搭建PhoneGap for Android开发环境

    一.确保Android开发环境正常. 二.下载PhoneGap.可到http://www.phonegapcn.com/去下载,速度快些. 三.新建一个PhoneGap项目 1.在eclipse中新建 ...

  10. UVA 1001 Say Cheese

    题意: 一只母老鼠想要找到她的玩具,而玩具就丢在一个广阔的3维空间上某个点,而母老鼠在另一个点,她可以直接走到达玩具的位置,但是耗时是所走过的欧几里得距离*10s.还有一种方法,就是靠钻洞,洞是球形的 ...