最近写一个程序,需要在用户模式下关中断,但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之路第六天,基础(8)-反射

    反射 利用字符串的形式去对象(模块)中操作(寻找/检查/删除/设置)成员(函数). Python中反射用到的4个内置函数:getattr(),setattr(),hasattr(),delattr() ...

  2. eclipsecpp从可执行程序员中导入源代码并调试

    如果寻找跨平台IDE及调试环境,那eclipse是最佳选择了,因为它有一项超强功能:可以从可执行程序员导入源代码并调试程序,这种特性是非常适合自定义MakeFile项目,不需要改变项目现有结果,即可自 ...

  3. c# 正则表达式对网页进行内容抓取

    原文 c# 正则表达式对网页进行内容抓取 搜索引擎中一个比较重要的环节就是从网页中抽取出有效内容.简单来说,就是吧HTML文本中的HTML标记去掉,留下我们用IE等浏览器打开HTML文档看到的部分(我 ...

  4. android邮件发送几种方式

    android中发送邮件我大概发现了3种,代码如下 package src.icetest; import org.apache.commons.mail.EmailException; import ...

  5. 100个linux常用命令

    1,echo “aa” > test.txt 和 echo “bb” >> test.txt //>将原文件清空,并且内容写入到文件中,>>将内容放到文件的尾部 2 ...

  6. 杭电oj 2719

    Tips:本程序没有什么难度,只要按照逻辑进行替换即可,需要注意的是,由于输入串中含有空格符号,所以不能使用scanf("%s",ch);来读取一串,可以使用gets()函数读取一 ...

  7. javascript第十五课:DOM

    dom就是文档,就是整个网页的简称,dom里面的标签就是对象 使用javascript进行DHMTL网页开发(Dynamic Html 动态网页) dom就是把html页面模拟成一个对象,顶级对象wi ...

  8. spring mvc <mvc:annotation-driven>配置使用出现故障

    我在使用converter进行全局的日期类型转换. 1.写converer public class CustomDateConverter implements Converter<Strin ...

  9. A Game with Colored Balls

    题目链接 题意: 给一个长度为n的字符串,每次删除字母同样切连续的串,假设有多个,删除最左边的.最长的串.每次删除输出串的字母,每一个字母的下标(1-n) N (1 ≤ N ≤ 106),串仅仅包含r ...

  10. Sublime 学习记录(四) Alignment 插件

    1)  Alignment 插件的安装 打开命令面板 输入pci 回车 输入Alignment 回车安装好即可 2)  Alignment 用处 用于代码对齐 3) Alignment 快捷键 默认为 ...