当前位置:网站首页>ARM系统调用异常 汇编
ARM系统调用异常 汇编
2022-07-17 22:55:00 【生活需要深度】
A7处理器异常swi和M3处理器异常svc
一个特殊的中断:SVCall
简述:一种由程序进行触发的中断,默认开启
起源:SVC(系统服务调用,亦简称系统调用)多用于在操作系统之上的软件开发中。SVC 用于产生系统函数的调用请求。例如,操作系统不让用户程序直接访问硬件,而是通过提供一些系统服务函数,用户程序使用 SVC 发出对系统服务函数的呼叫请求,以这种方法调用它们来间接访问硬件。因此,当用户程序想要控制特定的硬件时,它就会产生一个 SVC 异常,然后操作系统提供的 SVC 异常服务例程得到执行,它再调用相关的操作系统函数,后者完成用户程序请求的服务。
用途:可以通过设置,使得一段代码能够被某些中断打断,而不能被另外一些中断打断,比如可用于确保模拟IIC的时序不被打断而造成通信失败
注意:
- SVC 异常是必须立即得到响应的(若因优先级不比当前正处理的高,或是其它原因使之无法立即 响应,将引发HardFault)
- 主从优先级等等概念和普通中断相同(且地位相同,即该特殊中断其实也不特殊)//祝:默认情况下,除HardFault和NMI,其它中断的优先级均为0,0(附加提醒,group设置需先于priority设置),!!BUT!!,中断优先级的设置需要这么调用:NVIC_SetPriority(SVCall_IRQn,NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 1, 1));
在C中使用SVCall
SVC服务函数使用堆栈进行参数传递,故C语言版的SVC服务函数需要一个汇编操作,用于把堆栈中的参数提取到寄存器中


__asm void SVC_Handler(void) //该函数名在Keil中同USART2_IRQHandler等等
{
// 汇编操作,用于提出堆栈帧的起始位置,并放到R0中,然后跳转至实际的SVC服务例程中
IMPORT svc_handler
TST LR, #4
ITE EQ
MRSEQ R0, MSP
MRSNE R0, PSP
B svc_handler
}
// “真正”的服务函数,接受一个指针参数(pwdSF):堆栈栈的起始地址。
// pwdSF[0] = R0 , pwdSF[1] = R1
// pwdSF[2] = R2 , pwdSF[3] = R3
// pwdSF[4] = R12, pwdSF[5] = LR
// pwdSF[6] = 返回地址(入栈的PC)
// pwdSF[7] = xPSR
unsigned long svc_handler(unsigned int* pwdSF)
{
unsigned int svc_number;
unsigned int svc_r0;
unsigned int svc_r1;
unsigned int svc_r2;
unsigned int svc_r3;
int retVal; //用于存储返回值
svc_number = ((char *) pwdSF[6])[-2]; // 没想到吧,C的数组能用得这么绝!
svc_r0 = ((unsigned long) pwdSF[0]);
svc_r1 = ((unsigned long) pwdSF[1]);
svc_r2 = ((unsigned long) pwdSF[2]);
svc_r3 = ((unsigned long) pwdSF[3]);
printf (“SVC number = %xn”, svc_number);
printf (“SVC parameter 0 = %x\n”, svc_r0);
printf (“SVC parameter 1 = %x\n”, svc_r1);
printf (“SVC parameter 2 = %x\n”, svc_r2);
printf (“SVC parameter 3 = %x\n”, svc_r3);
//做一些工作,并且把返回值存储到retVal中
pwdSF[0]=retVal;
return 0;
}
//注意,这个函数返回的其实不是0!进一步地,灰色的文字只是用于哄编译器开心的,具体参考Cortex-M3权威指南P169
如何触发中断?
step1. 声明函数(__svc会自动生成对应函数)//__svc时keil里的一个宏
unsigned long __svc(0x03) CallSvc3(unsigned long svc_r0, unsigned long svc_r1, unsigned long svc_r2, unsigned long svc_r3);
step2. 调用函数
unsigned long svcRet; //系统服务的返回值 svcRet=CallSvc3(p0, p1, p2, p3); // 呼叫3号系统服务,并且传递4个参数,依次为:p1,p2,p3,p4,再接收返回值到svcRet中(别忘了,这个返回值的来历不寻常)
flyangchina 2016-08-19 17:25
不错,在svc_handler中应该有调用相应函数的代码。
可以在前面加一个SVC_Table数组来保存函数指针,比如这样:
extern int __SVC_0(int, int);
extern int __SVC_1(int);
void * SVCTable[256] = {
__SVC_0,
__SVC_1
};
然后再这样写svc_handler中这样写:
void svc_handler(unsigned int* pwdSF) {
// 使用栈中的r0~r3为参数调用对应的函数,
// 并且把返回值存储到调用者的栈中r0处
pwdSF[0] = ((int (*)(int, int, int, int))SVCTable[((char *) pwdSF[6])[-2]])
(
pwdSF[0],
pwdSF[1],
pwdSF[2],
pwdSF[3]
);
}
再补充一下__SVC_0的定义,在随意的某个文件中,__SVC_1不管了啊:
int __SVC_0 (int i1, int i2) {
return (i1 + i2);
}
使用如下:
int __svc(0) add (int i1, int i2);
...
void test() {
add(1,1);
}
int main() { ... }
这样就有了一个整体的使用svc实现系统调用的简单架构了
Serval 2015-02-10 16:10
关于“svc_number = ((char *) pwdSF[6])[-2]; // 没想到吧,C的数组能用得这么绝! ”的用法,看了半天,贴出来大家看理解的对不对:
首先这行代码的最终目的是取得svc #num中的Num。在Thumb代码(STM32应该多数是Cortex的吧)中,一条指令通常是16位,svc #num的指令通常翻译为0xDFxx --> 其中xx就是#num。所以,Keil手册有如下解释:
0 to 224–1 (a 24-bit value) in an ARM instruction.
0-255 (an 8-bit value) in a Thumb instruction.
代码可以翻译为好懂一点的:
*((char *)pwdSF[6] - 2)
举例:
假设系统配置为小端,低位放低字节。
指令为:svc #1 ---> 二进制为0xDF01,所在地址为0x286。
那么实际上,堆栈里压入的PC,存放的是0x288。因为PC压入的是下一条指令。
0x286: DF01 ;svc #1
0x288: ......
Stack: 88 02 00 00
那行奇特的代码就是为了得到这个01。分几步:
1. 转换为(char*)pwdSF[6],并减2
这一步是为了让指针可以精确指到88 02的位置。
(char*)pwdSF[6] - 2
2. 指针取值
*((char *)pwdSF[6] - 2)
3. 指针访问改为下表访问形式
指针取值可以写为下标形式,例如:*(p + i)等同于p[i],个人建议指针使用时都按第二种写法
((char *) pwdSF[6])[-2]
边栏推荐
- 2021.07.13【B站】是这样崩的
- P1004 [noip2000 improvement group] grid access
- Compositionapi component development paradigm
- Li Hongyi machine learning 2022.7.15 -- gradient descent
- 2、MYSQL介绍
- FMC sub card: 4-channel 12bit 3.2g, 2-channel 12bit, 6.4g AD acquisition / 5G acquisition card /6g acquisition card
- 最大堆与堆排序和优先队列
- [GYM103660] The 19th Zhejiang University City College Programming Contest 浙大城市学院校赛VP/S
- Cross domain and CORS
- 2. MySQL introduction
猜你喜欢

Google Earth Engine——无人机影像进行分类处理

2021.07.13【B站】是这样崩的

csrf防护机制

【微服务】 微服务学习笔记三:利用Feign替换RestTemplate完成远程调用

kube-proxy & Service & Endpoint

Li Hongyi machine learning 2022.07.15 -- error

Wechat applet 8 cloud function

ZABBIX realizes the monitoring of redis

Single channel 6Gsps 12 bit AD acquisition and single channel 6Gsps 16 bit Da (ad9176) output sub card based on vita57.1 standard

ORA-08103
随机推荐
MySQL 安装
JVM常用调优配置参数
GYM103660H. Distance
3438. 数制转换
Knapsack problem
Leetcode 1275. 找出井字棋的获胜者
第1章 预备知识
Chang'an chain learning research - storage analysis wal mechanism
新基民在支付宝上买基金安全吗
Wechat applet 6 cloud development cloud database
MySQL CPU usage is soaring. How to locate who is occupying it
06_服务调用Feign
揭开服务网格~Istio Service Mesh神秘的面纱
Several points to be analyzed in the domestic fpga/dsp/zynq scheme
vscod
session管理
微信小程序6-云开发-云数据库
Li Hongyi machine learning 2022.07.15 -- error
天勤第九章课后习题代码
人脸技术:不清楚人照片修复成高质量高清晰图像框架(附源代码下载)