arm cortex-m架构 SVC指令详解以及其在freertos的应用

1. 前置知识

本文基于arm cortex-m架构描述, 关于arm cortex-m的一些基础知识可以参考我另外几篇文章:

  • arm cortex-m 架构简述
  • arm异常处理分析
  • c语言函数调用规范-基于arm 分析

2 SVC指令

2.1 SVC指令位域表示

在这里插入图片描述

  • bit15 - bit12:条件码(Condition Code),用于控制指令的条件执行(EQ,NE,… )。
  • bit11- bit8:固定编码0111,用于标识这是一个SVC指令。
  • bit7- bit0:8位立即数(imm8),svc指令一般用于实现系统调用,imm8用来指定系统调用号。

2.2 SVC指令用途简述

  • ARM中的SVC(Supervisor Call)指令,一般用于实现系统调用, 在执行SVC指令时会触发一个SVC异常。
  • 在cortex-m架构中,异常/中断服务 总是处于总是处于 Privileged(特权) 模式,系统调用也是利用这一特性从用户态 进入 内核态 ,然后根据系统调用号执行特定的系统调用。 关于cortex-m架构和中断的其他信息可以参考我的另外两篇文章:
    • arm cortex-m 架构简述
    • arm异常处理分析
  • 站在硬件的角度SVC指令就是实现了一个软件中断,SVC异常和其他异常处理并无不同,硬件并没有做类似 传递系统调用号 这样的操作,系统调用号imm8也只是和指令码"打包"在一起放在代码段,在进入内核态之后 获取系统调用号 的操作是由 软件完成 的。

2.3 SVC使用示例

  • SVC中断触发示例
    SVC #0x01  ; 执行SVC指令,SVC号为0x01
    SVC #0x02  ; 执行SVC指令,SVC号为0x02
    
  • SVC中断服务函数示例
    • 我在代码中加了注释,如果还是不理解,可以看看我 第一节 所推荐的文章。
    SVC_Handler:; TST指令解释:;	将 "LR" 与 "立即数4" 进行 "按位与" 操作;	结果更新条件标志寄存器(CPSR); 	注:在发生异常时 LR 存储的是 EXC_RETURN , 这条代码主要看在发生异常时使用的是哪个栈,MSP或者PSPTST LR, #4; 依据TST LR, #4 的执行结果选择将 MSP或PSP加载到R0中; ITE: "If-Then-Else" 的缩写,用于创建一个条件执行块(IT块)。; EQ: 条件码,表示 "Equal"(相等),即当条件码寄存器(CPSR)的零标志(Z)被设置时,条件为真。; 用C语言描述一下下面三行汇编:; if(Z) {; 	MRS R0, MSP; } else {; 	MRS R0, PSP; }; 举一反三: ITTE: "If-Then-Then-Else" ITE EQMRS R0, MSP		; LR&4 或者说 EXC_RETURN&4  为 0 ,说明在在执行SVC异常时使用的栈是 MSPMRS R0, PSP     ; LR&4 或者说 EXC_RETURN&4  为 0 ,说明在在执行SVC异常时使用的栈是 PSP;  获取返回地址 (原理是与发生异常时硬件压栈的顺序相关);  这里获得返回地址的原因是为了定位产生异常前执行的最后一条指令,也就是SVC指令LDR R1, [R0, #24] ; 获取SVC指令的低8位,也就是系统调用号,返回地址的上一条就是SVC指令,LDRB R1, [R1, #-2] ; 依据不同的系统调用号执行不同的系统调用CMP R1, #0x01BEQ SVC_01_HandlerCMP R1, #0x02BEQ SVC_02_HandlerSVC_01_Handler:; 处理SVC号为0x01的服务请求SVC_02_Handler:; 处理SVC号为0x02的服务请求
    

3. SVC指令在freertos中的应用

freertos只使用了一次 SVC指令 也可以理解为 freertos中只实现了一个系统调用,且只使用一次,就是在完成任务创建后发起的第一次任务调度时使用。

3.1 在freertos中SVC中断的触发位置

  • freertos使用 SVC指令是在 prvPortStartFirstTask 函数中使用,目的是开始第一次调度,发生在创建任务完成后的第一次调度,我会为这段代码加上注释,如果还存在看不懂的情况,建议先看看我的其他文章或者自行查阅资料学习。
  • 在freertos中的调用关系是:
    		vTaskStartScheduler		--->
    ---> 	xPortStartScheduler		--->
    --->	prvPortStartFirstTask
    
    static void prvPortStartFirstTask( void )
    {__asm volatile (/* *	- 0xE000ED08是 SCB 模块 VTOR 寄存器的地址*	- 这句汇编目的是把 0xE000ED08(VTOR的地址) 保存到 R0 寄存器*	- 执行完这句指令(伪指令),后 R0 寄存器保存的是 0xE000ED08(VTOR的地址)*/" ldr r0, =0xE000ED08   \n"/* *	- 将 0xE000ED08 地址的值(中断向量表的地址) 放到 R0 寄存器中*	- 执行完这句指令,后 R0 寄存器保存的是 中断向量表的地址*/" ldr r0, [r0]          \n"/* *	- 将 中断向量表 第一项的值 放到 R0 寄存器中*	- 中断向量表第一个字保存的 是栈顶地址(cortex-m是满减栈,栈顶即栈的开始)*	- 初始转态下使用的是MSP*	- 执行完这句指令,后 R0 寄存器保存的是栈顶地址*/" ldr r0, [r0]          \n"/* *	- 将 R0的值写入 MSP 中。*	- 此时 R0 内存储的是 栈顶地址,这一步其实就是把 MSP 中已经存好的内容完全销毁。*	- 因为在这段代码中,在执行完SVC指令后,会由调度器完全接管代码,这里的SVC异常永远也不会返回*/" msr msp, r0           \n"/* *	- 将 control 寄存器清零*	- control 寄存器有三位,分别是:*		. FPCA	- 标志位,用于指示在前文中是否使用过 FPU(浮点运算单元),如果使用过,dang发生异常硬件压栈的时候,会基于此位决定是否保存浮点运算单元上下文,又此时使用的SVC异常是不会返回的,所以也不必保存,保存了也是浪费空间。*			0:前文没有使用浮点运算单元,产生异常时硬件不用保存浮点上下文*			1:前文使用了浮点运算单元,产生异常时硬件要保存浮点上下文*		. SPSEL - 控制位,控制在 Thread mode 下使用 MSP 还是 PSP , Handler mode 一定使用 PSP*			0: MSP*			1: PSP*		. nPRIV - 控制位,控制在 Thread mode 下是 Privileged(特权级) 还是 Unprivileged(非特权级) , Handler mode 下一定是 Privileged(特权级)*			0: Privileged(特权级)*			1: Unprivileged(非特权级)*/" mov r0, #0            \n"" msr control, r0       \n"/* 开启全局中断 */" cpsie i               \n"	/* 开启fpu */" cpsie f               \n"	/* 数据同步隔离,确保上面的配置生效 */" dsb                   \n"	/* 指令同步隔离,清空流水线 */" isb                   \n" /* 触发0号系统调用,永远也不会返回, 从此处开始代码由freertos全面接管 */	" svc 0                 \n"/* svc 不会返回,永远也不会运行到这里 */" nop                   \n"/* 这是一条伪指令,由汇编器处理,目的是告诉汇编器,把字面量池(常量)放到这个位置, 避免字面量池离使用它的指令太远,超出了寻址范围而导致错误。ARM的ldr指令寻址范围有限*/" .ltorg                \n");
    }
    

3.2 freertos中断服务函数解析

  • 我会为这段代码加上注释,如果还存在看不懂的情况,建议先看看我的其他文章或者自行查阅资料学习。
    void vPortSVCHandler( void )
    {/** 思考:在汇编中能用C语言的变量吗,为什么,C语言中的变量和符号在汇编中代表了什么* 答案:应考虑如下几点* 	- C语言和汇编在整个编译过程中是在不同的阶段进行的* 	- C语言是在 编译阶段 进行处理的,C语言会被编译为汇编* 	- 汇编 是在汇编阶段进行的,会生成可重定位的目标文件,最终会在 链接阶段 由链接器为所有符号分配 绝对地址。* 	- 我们在写汇编时,会用一些符号代表地址,那些符号会由 链接器 最终分配绝对地址。* 	- c语言中定义的 变量名 函数名 在经过 编译器 编译为 汇编 之后,那些变量名, 函数名都代表一个地址,最后由 链接器 分配绝对地址。* 	所以,在汇编中使用的C语言符号,可以理解为那个变量或者函数的 地址。*//** 先看一下最后一句汇编 "pxCurrentTCBConst2: .word pxCurrentTCB             \n"* 	- pxCurrentTCB:在c语言中定义,它是一个指针,一个描述 任务 的结构体指针* 	- 在汇编中使用 pxCurrentTCB 这个符号, 就相当于使用这个符号的地址,在这里可以理解为一个二重指针* 	- 上述汇编可以这么理解:* 		. 使用 .word 分配一个字的空间,用来放 “下一个要执行的任务结构体” 指针的指针(二重指针).* 		. 将这个二重指针 使用符号 pxCurrentTCBConst2 表示*/__asm volatile (/* * - 将要执行任务的结构体 的 指针的指针(二重指针) 保存到 R3寄存器 */"   ldr r3, pxCurrentTCBConst2      \n"/* * - 将要执行任务的结构体 的 指针(一重指针) 保存到 R1寄存器 * - 也可以理解为将 要执行任务的结构体 的第一个元素的地址保存到 R1 寄存器* - 结构体第一个元素 保存将要执行任务的栈指针* - 所以这一句是将 栈指针(SP) 的地址(是栈指针的存放地址,而不是栈指针) 放到R1中。*/"   ldr r1, [r3]                    \n"/* * - 将栈指针 SP 保存到 R0寄存器 */"   ldr r0, [r1]                    \n"/* * - 将栈指针中的地址按顺序弹栈(要执行的任务的栈)到{r4-r11, r14}* - 这里是要弹栈的内容是 创建任务时 伪造的上下文 (此处先不展开,后面降到任务的创建过程会展开来讲)*/"   ldmia r0!, {r4-r11, r14}        \n"/* 将 PSP 指向弹完栈后的地址 */"   msr psp, r0                     \n"/* 指令同步隔离,清空流水线 */"   isb                             \n"/* 将basepri寄存器设为0,打开所有中断 */"   mov r0, #0                      \n""   msr basepri, r0                 \n"/* * - 异常返回, 这时r14(LR)中存放的是一个 EXC_RETURN 值,这个值是在创建任务时伪造的。* - EXC_RETURN 的值决定了任务使用的栈* - 伪造栈的内容会在后面将创建任务时讲*/"   bx r14                          \n""                                   \n""   .align 4                        \n""pxCurrentTCBConst2: .word pxCurrentTCB             \n");
    }
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/846112.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SOFA-RPC学习记录

文章目录 需求分析模块划分微服务模块交互模块 可拓展架构插件机制 功能分析交互模块 学习微服务模块交互模块 dubbo与nacos集成学习Nacos配置中心实战 dubbo与apollo集成学习配置中心组件与k8s的抉择参考资料 结论 本报告旨在深入学习SOFA-RPC框架,特别是其动态配置…

Linux综合实践(Ubuntu)

目录 一、配置任务 1.1 配置该服务器的软件源为中科大软件源 1.2 安装相关软件openssh-server和vim 1.3 设置双网卡,网卡1为NAT模式,网卡2为桥接模式(桥接模式下,使用静态ip,该网卡数据跟实验室主机网络设置相似,除…

如何搜索[仅有1个文件]或[指定个数范围、名称、类型文件等复杂情况]的文件夹

首先,需要用到的这个工具: 度娘网盘 提取码:qwu2 蓝奏云 提取码:2r1z 打开工具,切换到批量复制板块,用Ctrl5可以快速切换 然后鼠标移动到工具的贴边的右侧,不是移出工具外面,还在…

【赠书第22期】AI绘画全面精通

文章目录 前言 1 AI绘画基础知识 2 AI绘画技术应用 2.1 风格迁移 2.2 自动绘画 2.3 辅助绘画 3 AI绘画发展前景 3.1 艺术创作领域的变革 3.2 跨领域融合与创新 3.3 个性化艺术创作的普及 4 结语 5 推荐图书 6 粉丝福利 前言 随着科技的飞速发展,人工智…

自学 Java 怎么入门?

关于自学 Java 如何入门这一重要课题,在此为大家进行详细阐述。 在此之前,如果大家有兴趣的话,可以看看我自己精心整理的嵌入式入门资料,这些资料将全部免费送给大家。其中包含了编程教学内容、详细的视频讲解、实用的数据库资料…

锅炉智能制造工厂工业物联数字孪生平台,推进制造业数字化转型

在制造业快速发展的今天,数字化转型已经成为企业提升竞争力的关键途径。锅炉智能制造工厂工业物联数字孪生平台,作为一种创新的技术解决方案,正以其独特的优势,为制造业的数字化转型提供强大动力。锅炉智能制造工厂工业物联数字孪…

libevent源码跨平台编译(windows/macos/linux)

1.windows编译: 克隆: git clone https://github.com/libevent/libevent.git 克隆成功 生成makefile 生成成功 默认不支持OpenSSL,MbedTLS,ZLIB这三个库 编译: cmake --build . --config release

深入分析 Android Service (完)

文章目录 深入分析 Android Service (完)1. Service 的生命周期管理2. Service 的生命周期方法2.1 onCreate()2.2 onStartCommand(Intent intent, int flags, int startId)2.3 onBind(Intent intent)2.4 onUnbind(Intent intent)2.5 onRebind(Intent intent)2.6 onDestroy() 3.…

子集树与排列树的构造

排列树的构造: 无重复画法:一条线前面出现的不再出现。 有重复画法:一条线前面出现的不再出现,如果仅仅只是相似可以出现;兄弟不能相似。 目标函数是:cnt 总元素个数分支策略是全遍历,不过存…

二级指针简单介绍

我们之前学习的&#xff1a;变量的地址是存入指针变量中的&#xff0c;然而指针变量也是变量&#xff0c;是变量就有地址&#xff0c;那么指针变量的地址存放在哪里 &#xff1f; 这也就是二级指针 #include<stdio.h> int main() {int a10;int*p&a;int**pp&p;re…

微软如何打造数字零售力航母系列科普12 - 使用Microsoft Fabric将客户数据带入人工智能时代

【世界上充斥着数据&#xff0c;在过去的2年里&#xff0c;我们都看到了人工智能如何有潜力彻底改变我们的日常业务。人们对利用生成性人工智能体验的力量的需求越来越大&#xff0c;但这样做需要一个干净的数据庄园&#xff0c;而且可能会因为各种技术堆栈、分散的团队和无处不…

如何让Google快速收录?

要让Google快速收录你的网站&#xff0c;可以考虑使用GSI服务&#xff0c;这是一种专门设计来加速网站被Google搜索引擎收录的服务&#xff0c;下面详细解释GSI服务的基本原理和具体好处&#xff1a; GSI服务通过一种名为GPC爬虫池的系统实现&#xff0c;这个系统是基于对Goog…

eBPF可观测之网络流量控制和管理traffic control浅尝

目录 工程背景 环境准备 安装工具​​​ 安装依赖包 安装C依赖库 操作步骤 目录结构 代码展示 效果展示 拓展提升 工程背景 首先发表一个"暴论" eBPF在可观测方面的应用&#xff0c;就是各种google。 不需要学习内核&#xff0c;只要掌握ebpf开发套路。…

什么是TLAB?

这个得从内存申请说起。 一般而言生成对象需要向堆中的新生代申请内存空间&#xff0c;而堆又是全局共享的&#xff0c;像新生代内存又是规整的&#xff0c;是通过一个指针来划分的。 内存是紧凑的&#xff0c;新对象创建指针就右移对象大小size即可&#xff0c;这叫指针加法…

怎么通过互联网远程控制电脑?

远程访问又称为网络远程控制&#xff0c;它使用户能够通过互联网连接两台设备以解决问题。进行控制的电脑称为控制端&#xff0c;被控制的电脑则称为被控端。在远程访问过程中&#xff0c;控制端电脑掌握整个连接的操作。远程控制软件会捕获被控端电脑的操作&#xff0c;并在主…

绘画智能体分享

这是您请求的故宫雪景图&#xff0c;角落有一只可爱的胖猫&#xff0c;采用了水墨画风格&#xff0c;类似于张大千的作品。希望您喜欢这幅画&#xff01; &#x1f3a8; 选项 1【转变风格】——将这幅画转变为梵高的后印象派风格&#xff0c;增添一些梵高特有的笔触和色彩。 &…

Superset二次开发之Github项目推送到GitLab仓库

以下是从GitHub克隆Superset项目并将其推送到GitLab的详细操作步骤 lab 地址: xxx lab 配置: 生成SSH密钥 ssh-keygen -t rsa -b 4096 -C "邮箱地址" 默认情况下密钥会生成在~/.ssh (/c/Users/Administrator/.ssh/id_rsa)目录下。 公钥添加到GitLab: 打开公钥文件…

短时间内如何顺利通过 Java 面试?

今天我们来探讨一个重要的话题&#xff1a;短时间内如何顺利通过 Java 面试&#xff1f; 在此之前&#xff0c;我正在精心编写一套完全面向小白的 Java 自学教程&#xff0c;我相信这套教程会非常适合正在努力提升的你。教程里面涵盖了丰富全面的编程教学内容、详细生动的视频…

上网行为监控软件大盘点:好用的上网行为管理软件一览

这是后台私信来的客户发来的图片&#xff0c;他们老板想要给自己公司安装上网行为监控软件。 可见&#xff0c;企业对员工上网行为的监控与管理已经是很多企业都开始重视的问题。 上网行为管理软件能够帮助企业确保网络资源得到合理分配&#xff0c;提升工作效率&#xff0c;…