关于中断部分系列篇将用三篇详细说明整个过程.
- 中断概念篇 中断概念很多,比如中断控制器,中断源,中断向量,中断共享,中断处理程序等等.本篇做一次整理.先了解透概念才好理解中断过程.用海公公打比方说明白中断各个概念.
- 中断管理篇 从中断初始化
HalIrqInit
开始,到注册中断的LOS_HwiCreate
函数,到消费中断函数的HalIrqHandler
,剖析鸿蒙内核实现中断的过程,很像设计模式中的观察者模式. - 中断切换篇(本篇) 用自下而上的方式,从中断源头纯汇编代码往上跟踪代码细节.说清楚保存和恢复中断现场
TaskIrqContext
过程.
中断环境下的任务切换
在鸿蒙的内核线程就是任务,系列篇中说的任务和线程当一个东西去理解.
一般二种场景下需要切换任务上下文:
- 在中断环境下,从当前线程切换到目标线程,这种方式也称为硬切换.它们通常由硬件产生或是软件发生异常时的被动式切换.哪些情况下会出现硬切换呢?
- 中断源可分外部和内部中断源两大类,比如 鼠标,键盘外部设备每次点击和敲打,屏幕的触摸,USB的插拔等等这些都是外部中断源.存储器越限、缺页,核间中断,断点中断等等属于内部中断源.由此产生的硬切换都需要换栈运行,硬切换硬在需切换工作模式(中断模式).所以会比线程环境下的切换更复杂点,但道理还是一样要保存和恢复切换现场寄存器的值, 而保存寄存器顺序格式结构体叫:任务中断上下文(
TaskIrqContext
).
- 在线程环境下,从当前线程切换到目标线程,这种方式也称为软切换,能由软件控制的自主式切换.哪些情况下会出现软切换呢?
- 运行的线程申请某种资源(比如各种锁,读/写消息队列)失败时,需要主动释放CPU的控制权,将自己挂入等待队列,调度算法重新调度新任务运行.
- 每隔10ms就执行一次的
OsTickHandler
节拍处理函数,检测到任务的时间片用完了,就发起任务的重新调度,切换到新任务运行. - 不管是内核态的任务还是用户态的任务,于切换而言是统一处理,一视同仁的,因为切换是需要换栈运行,寄存器有限,需要频繁的复用,这就需要将当前寄存器值先保存到任务自己的栈中,以便别人用完了轮到自己再用时恢复寄存器当时的值,确保老任务还能继续跑下去. 而保存寄存器顺序格式结构体叫:任务上下文(
TaskContext
).
本篇说清楚在中断环境下切换(硬切换)的实现过程.
ARM的七种工作模式中,有两个是和中断相关.
- 普通中断模式(irq):一般中断模式也叫普通中断模式,用于处理一般的中断请求,通常在硬件产生中断信号之后自动进入该模式,该模式可以自由访问系统硬件资源。
- 快速中断模式(fiq):快速中断模式是相对一般中断模式而言的,用来处理高优先级中断的模式,处理对时间要求比较紧急的中断请求,主要用于高速数据传输及通道处理中。
此处分析普通中断模式下的任务切换过程.
普通中断模式相关寄存器
这张图一定要刻在脑海里,系列篇会多次拿出来,目的是为了能牢记它.
- 普通中断模式(图中IRQ列)是一种异常模式,有自己独立运行的栈空间.一个(IRQ)中断发生后,硬件会将CPSR寄存器工作模式置为IRQ模式.并跳转到入口地址
OsIrqHandler
执行.
OsIrqHandler
汇编代码实现过程,就干了三件事:
- 1.保存任务中断上下文
TaskIrqContext
- 2.执行中断处理程序
HalIrqHandler
,这是个C函数,由汇编调用 - 3.恢复任务中断上下文
TaskIrqContext
,返回被中断的任务继续执行
TaskIrqContext 和 TaskContext
先看本篇结构体 TaskIrqContext
- 两个结构体很简单,目的更简单,就是用来保存寄存器现场的值的.
TaskContext
把17个寄存器全部保存了,TaskIrqContext
保存的少些,在栈中并没有保存R4-R11寄存器的值,这说明在整个中断处理过程中,都不会用到R4-R11寄存器.不会用到就不会改变,当然就没必要保存了.这也说明内核开发者的严谨程度,不造成时间和空间上的一丁点浪费.效率的提升是从细节处入手的,每个小地方优化那么一丢丢,整体性能就上来了. -
TaskIrqContext
中有两个变量有点奇怪unsigned int USP;
unsigned int ULR;
指的是用户模式下的SP和LR值, 这个要怎么理解? 因为对一个正运行的任务而言,中断的到来是颗不定时炸弹,无法预知,也无法提前准备,中断一来它立即被打断,压根没有时间去保存现场到自己的栈中,那保存工作只能是放在IRQ栈或者SVC栈中.而IRQ栈非常的小,只有64个字节,16个栈空间,指望不上了,就保存在SVC栈中,SVC模式栈可是有 8K空间的. - 从接下来的
OsIrqHandler
代码中可以看出,鸿蒙内核整个中断的工作其实都是在SVC模式下完成的,而irq的栈只是个过渡栈.具体看汇编代码逐行注解分析.
普通中断处理程序
逐句解读
- 跳转到
OsIrqFromKernel
硬件会自动切换到__irq_stack
执行 - 1句:
SUB LR, LR, #4
在arm执行过程中一般分为取指,译码,执行阶段,而PC是指向取指,正在执行的指令为 PC-8 ,译码指令为PC-4.当中断发生时硬件自动执行 mov lr pc, 中间的PC-4译码指令因为没有寄存器去记录它,就会被丢失掉.所以SUB LR, LR, #4
的结果是lr = PC -4 ,定位到了被中断时译码指令,将在栈中保存这个位置,确保回来后能继续执行. - 2句:
STMFD SP, {R0-R3}
当前4个寄存器入__irq_stack
保存 - 3句:
SUB R0, SP, #(4 * 4)
因为SP没有自增,R0跳到保存R0内容地址 - 4,5句:读取SPSR,LR寄存器内容,目的是为了后面在SVC栈中保存
TaskIrqContext
- 6句:
CPSID i, #0x13
禁止中断和切换SVC模式,执行完这条指令后工作模式将切到 SVC模式 - @TaskIrqContext 开始保存中断现场 …
- 中间代码需配合
TaskIrqContext
来看,不然100%懵逼.结合看就秒懂,代码都已经注释,不再做解释,注解中提到的 翻看276行 是指源码的第276行,请对照注解源码看理解会更透彻. - @TaskIrqContext 结束保存中断现场 …
-
TaskIrqContext
保存完现场后就真正的开始处理中断了.
- 这段代码都是跳转到C语言去执行,分别是
HalIrqHandler
OsTaskProcSignal
OsSchedPreempt
OsSaveSignalContextIrq
C语言部分内容很多,将在中断管理篇中说明. - @TaskIrqContext 开始恢复中断现场 …
- 同样的中间代码需配合
TaskIrqContext
来看,不然100%懵逼.结合看就秒懂,代码都已经注释,不再做解释,注解中提到的 翻看287行 是指源码的第287行,请对照注解源码看理解会更透彻.进入源码注解地址查看 - @TaskIrqContext 结束恢复中断现场 …
经常有很多小伙伴抱怨说:不知道学习鸿蒙开发哪些技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?
为了能够帮助到大家能够有规划的学习,这里特别整理了一套纯血版鸿蒙(HarmonyOS Next)全栈开发技术的学习路线,包含了鸿蒙开发必掌握的核心知识要点,内容有(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、WebGL、元服务、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、OpenHarmony驱动开发、系统定制移植等等)鸿蒙(HarmonyOS NEXT)技术知识点。
《鸿蒙 (Harmony OS)开发学习手册》(共计892页)
如何快速入门?
1.基本概念
2.构建第一个ArkTS应用
3.……
开发基础知识:
1.应用基础知识
2.配置文件
3.应用数据管理
4.应用安全管理
5.应用隐私保护
6.三方应用调用管控机制
7.资源分类与访问
8.学习ArkTS语言
9.……
基于ArkTS 开发
1.Ability开发
2.UI开发
3.公共事件与通知
4.窗口管理
5.媒体
6.安全
7.网络与链接
8.电话服务
9.数据管理
10.后台任务(Background Task)管理
11.设备管理
12.设备使用信息统计
13.DFX
14.国际化开发
15.折叠屏系列
16.……
鸿蒙开发面试真题(含参考答案)
OpenHarmony 开发环境搭建
《OpenHarmony源码解析》
- 搭建开发环境
- Windows 开发环境的搭建
- Ubuntu 开发环境搭建
- Linux 与 Windows 之间的文件共享
- ……
- 系统架构分析
- 构建子系统
- 启动流程
- 子系统
- 分布式任务调度子系统
- 分布式通信子系统
- 驱动子系统
- ……
OpenHarmony 设备开发学习手册
写在最后
如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
- 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
- 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。