RTX——第19章 SVC 中断方式调用用户函数(后期补历程)
以下内容转载自安富莱电子: http://forum.armfly.com/forum.php
本章节为大家讲解如何采用 SVC 中断方式调用用户函数。 当用户将 RTX 任务设置为工作在非特权级
模式时,任务中是不允许访问特权级寄存器的,这个时候使用 SVC 中断,此问题就迎刃而解了。
SVC 功能介绍
SVC 用于产生系统函数的调用请求。例如,操作系统通常不让用户程序直接访问硬件,而是通过提供
一些系统服务函数,让用户程序使用 SVC 发出对系统服务函数的呼叫请求,以这种方法调用它们来间接
访问硬件。因此,当用户程序想要控制特定的硬件时,它就要产生一个 SVC 异常,然后操作系统提供的
SVC 异常服务例程得到执行,它再调用相关的操作系统函数,后者完成用户程序请求的服务。
SVC 这种“提出要求——得到满足”的方式很好:
它使用户程序从控制硬件的繁文缛节中解脱出来,而是由 OS 负责控制具体的硬件。
OS 的代码可以经过充分的测试,从而能使系统更加健壮和可靠。
它使用户程序无需在特权级下执行,用户程序无需承担因误操作而瘫痪整个系统的风险。
通过 SVC 的机制,还让用户程序变得与硬件无关,因此在开发应用程序时无需了解硬件的操作细节,
从而简化了开发的难度和繁琐度,并且使应用程序跨硬件平台移植成为可能。开发应用程序唯一需要
知道的就是操作系统提供的应用编程接口(API),并且在了解了各个请求代号和参数表后,就可以
使用 SVC 来提出要求了(事实上,为使用方便,操作系统往往会提供一层封皮,以使系统调用的形
式看起来和普通的函数调用一致。各封皮函数会正确使用 SVC 指令来执行系统调用)。其实,严格
地讲,操作硬件的工作是由设备驱动程序完成的,只是对应用程序来说,它们也相当于操作系统的一
部分。如下图所示:

SVC 异常通过执行” SVC”指令来产生。该指令需要一个立即数,充当系统调用代号。 SVC 异常服务
例程稍后会提取出此代号,从而获知本次调用的具体要求,再调用相应的服务函数。例如,
SVC 0x3 ; 调用 3 号系统服务
在 SVC 服务例程执行后,上次执行的 SVC 指令地址可以根据自动入栈的返回地址计算出。找到了 SVC
指令后,就可以读取该 SVC 指令的机器码,从机器码中萃取出立即数,就获知了请求执行的功能代号。
如果用户程序使用的是 PSP,服务例程还需要先执行 MRS Rn, PSP 指令来获取应用程序的堆栈指针。通
过分析 LR 的值,可以获知在 SVC 指令执行时,正在使用哪个堆栈。
注意,我们不能在 SVC 服务例程中嵌套使用 SVC 指令(事实上这样做也没意义),因为同优先级的
异常不能抢占自身。这种作法会产生一个用法 fault。同理,在 NMI 服务例程中也不得使用 SVC,否则将
触发硬 fault。
SVC 触发方式
SVC 的异常号是 11,支持可编程。 SVC 异常可以由 SVC 指令来触发,也可以通过 NVIC 来软件触发
(通过寄存器 NVIC->STIR 触发软中断)。这两种方式触发 SVC 中断有一点不同:软件触发中断是不精
确的,也就是说,抢占行为不一定会立即发生,即使当时它没有被掩蔽,也没有被其它 ISR 阻塞,也不能
保证马上响应。这也是写缓冲造成的,会影响到与操作 NVIC STIR 相临的后一条指令:如果它需要根据中
断服务的结果来决定如何工作(如条件跳转),则该指令可能会误动作——这也可以算是紊乱危象的一种
表现形式。为解决这个问题,必须使用一条 DSB 指令,如下例所示:
MOV R0, #SOFTWARE_INTERRUPT_NUMBER
LDR R1,=0xE000EF00 ; 加载 NVIC 软件触发中断寄存器的地址
STR R0, [R1] ; 触发软件中断
DSB ; 执行数据同步隔离指令
...
但是这种方式还有另一种隐患:如果欲触发的软件中断被除能了,或者执行软件中断的程序自己也是个异
常服务程序,软件中断就有可能无法响应。因此,必须在使用前检查这个中断已经在响应中了。为达到此
目的,可以让软件中断服务程序在入口处设置一个标志。而 SVC 要精确很多,SVC 指令后,只要此时没
有其它高优先级的异常也发生了,SVC 中断服务程序可以得到立即执行。
SVC 的使用
SVC 是用于呼叫 OS 所提供的 API(RTX 是采用的这种方式)。用户程序只需知道传递给 OS 的参数,
而不必知道各 API 函数的地址。 SVC 指令带一个 8 位的立即数,可以视为是它的参数,被封装在指令本身
中,如:
SVC 3 ;呼叫 3 号系统服务
则 3 被封装在这个 SVC 指令中。因此在 SVC 服务例程中,需要读取本次触发 SVC 异常的 SVC 指令,并
提取出 8 位立即数所在的位段,来判断系统调用号。
RTX 使用的 SVC 中断服务号
SVC 的 0 号系统服务被 RTX 系统占用,即 SVC 0,用户只能使用从 1 开始的服务号。而且用户使
用的时候一定要保证从 1 开始,连续递增使用,范围 1 – 255。
RTX 中 SVC 中断方式调用函数方法
用户实现 SVC 中断方式调用函数方法如下(下面以添加两个 SVC 中断为例):
第 1 步:添加 SVC_Table.s 文件。
我们在前面讲解 RTX 的源码移植方式时这个文件已经加上。
第 2 步:使用属性__svc(x)声明函数,x 从 1 开始,范围 1-255。函数名随便命名,但是 x 的数值一
定要保证是连续递增的。
void __svc(1) SVC_1_FunCall(uint8_t _arg1, uint16_t _arg2, uint32_t _arg3, uint64_t *_arg4);
void __svc(2) SVC_2_FunCall(void);
第 3 步:写上面两个函数的实际代码,并将函数名更改成__SVC_x 格式(统一改成这种命名方式是为
了跟 RTX 系统的调用方式__SVC_0 统一),x 是从 1 开始,范围 1-255。 上面声明的两个函数不要动,
这里修改的是实际函数名。 另外用户可以根据需要加上中断开关操作,因为 SVC 中断可以被其它高
优先级的中断抢占。




RTX——第19章 SVC 中断方式调用用户函数(后期补历程)的更多相关文章
- 通过队列实现进程间的通信(使用阻塞方式调用func函数)
#_author:来童星#date:2019/12/17#通过队列实现进程间的通信from multiprocessing import Poolimport osimport timedef fun ...
- 如何在tornado中以异步的方式调用同步函数
问题 如何在tornado的coroutine中调用同步阻塞的函数 解决方案 使用python内置标准库的concurrent.futures.ThreadPoolExecutor和tornado.c ...
- RTX——第18章 内存管理
以下内容转载自安富莱电子: http://forum.armfly.com/forum.php 内存管理介绍在 ANSI C 中,可以用 malloc()和 free()2 个函数动态的分配内存和释放 ...
- 以WCF安全认证方式调用通用权限管理系统获取基础信息资料
在B/S开发中,涉及到获取系统基础资料的问题,因为是在不同平台下的开发,采用了WCF方式获取. 下面是一个调用通用权限管理系统(吉日嘎拉)基础信息资料的一个demo供参考 调用原理图: web.con ...
- JavaScript中以构造函数的方式调用函数
转自:http://www.cnblogs.com/Saints/p/6012188.html 构造器函数(Constructor functions)的定义和任何其它函数一样,我们可以使用函数声明. ...
- 《深入Java虚拟机学习笔记》- 第19章 方法的调用与返回
<深入Java虚拟机学习笔记>- 第19章 方法的调用与返回
- RTX——第11章 临界段,任务锁和中断锁
以下内容转载自安富莱电子: http://forum.armfly.com/forum.php 临界段代码的临界段也称为临界区,一旦这部分代码开始执行,则不允许任何中断打断.为确保临界段代码的执行不被 ...
- 【RL-TCPnet网络教程】第19章 RL-TCPnet之BSD Socket服务器
第19章 RL-TCPnet之BSD Socket服务器 本章节为大家讲解RL-TCPnet的BSD Socket,学习本章节前,务必要优先学习第18章的Socket基础知识.有了这些基础知 ...
- RTX——第9章 任务运行在特权级或非特权级模式
以下内容转载自安富莱电子: http://forum.armfly.com/forum.php 本章教程为大家讲解 RTX 运行模式的一个重要知识点,特权级模式和非特权级模式,有些资料或者书籍将非特权 ...
随机推荐
- Ubuntu终端命令行播放音乐(mp3)
有很多在终端命令行播放mp3的工具,有的甚至可以生成播放列表.也只有命令行重度使用者有这个需求,下面我们来看一看这些工具. Sox Sox(Sound eXchange)是操作声音文件的瑞士军刀,它可 ...
- Centos6.5使用yum安装mysql——快速上手必备(转)
第1步.yum安装mysql[root@stonex ~]# yum -y install mysql-server安装结果:Installed: mysql-server.x86_64 0: ...
- magento直接操作数据库
查: $read = Mage::getSingleton("core/resource")->getConnection('core_read'); $sq ...
- Oracle 12C -- clone a remote pdb
Connect to the remote CDB and prepare the remote PDB for cloning. SQL> select con_id,dbid,name,op ...
- Linux共享内存使用常见陷阱与分析
所谓共享内存就是使得多个进程可以访问同一块内存空间,是最快的可用IPC形式.是针对其他通信机制运行效率较低而设计的.往往与其它通信机制,如 信号量结合使用,来达到进程间的同步及互斥.其他进程能把同一段 ...
- go test命令參数问题
go test命令參数问题 在使用go test对go代码进行单元測试的时候,遇到关于命令參数的问题.google了一下,没有找到非常好的说明,其实就是一些细节而已. 问题是这种,在进行单元測试的时候 ...
- Android NDK r9的配置与使用
Android NDK 配置: 网上有很多教程,但大部分是旧版本的内容,最新版本的已经改变,为了让大家少走弯路,在这里针对r9的配置进行记录分享. 要玩NDK,你或多或少要用到以下一些东西,所以先做一 ...
- [转]使用spring中的@Transactional注解时,可能需要注意的地方
前情提要 在编写业务层方法时,会遇到很多需要事务提交的操作,spring框架为我们提供很方便的做法,就是在需要事务提交的方法上添加@Transactional注解,比起我们自己开启事务.提交以及控制回 ...
- [转]python数据持久存储:pickle模块的基本使用
python的pickle模块实现了基本的数据序列和反序列化.通过pickle模块的序列化操作我们能够将程序中运行的对象信息保存到文件中去,永久存储:通过pickle模块的反序列化操作,我们能够从文件 ...
- glide 镜像
运行glide install 失败 国内墙的原因, 某些网站上不去 [ERROR]Update failed for golang.org/x/crypto: Cannot detect VCS ...