百度怎么优化网站关键词,网站制作排名,南京高端网站制作公司,模具外贸网站建设关于中断部分系列篇将用三篇详细说明整个过程. 中断概念篇 中断概念很多#xff0c;比如中断控制器#xff0c;中断源#xff0c;中断向量#xff0c;中断共享#xff0c;中断处理程序等等.本篇做一次整理.先了解透概念才好理解中断过程.用海公公打比方说明白中断各个概念…关于中断部分系列篇将用三篇详细说明整个过程. 中断概念篇 中断概念很多比如中断控制器中断源中断向量中断共享中断处理程序等等.本篇做一次整理.先了解透概念才好理解中断过程.用海公公打比方说明白中断各个概念. 中断管理篇 从中断初始化HalIrqInit开始到注册中断的LOS_HwiCreate函数到消费中断函数的 HalIrqHandler剖析鸿蒙内核实现中断的过程很像设计模式中的观察者模式. 中断切换篇(本篇) 用自下而上的方式从中断源头纯汇编代码往上跟踪代码细节.说清楚保存和恢复中断现场TaskIrqContext过程.
中断环境下的任务切换
在鸿蒙的内核线程就是任务系列篇中说的任务和线程当一个东西去理解.
一般二种场景下需要切换任务上下文: 在中断环境下从当前线程切换到目标线程这种方式也称为硬切换.它们通常由硬件产生或是软件发生异常时的被动式切换.哪些情况下会出现硬切换呢? 中断源可分外部和内部中断源两大类比如 鼠标键盘外部设备每次点击和敲打屏幕的触摸USB的插拔等等这些都是外部中断源.存储器越限、缺页核间中断断点中断等等属于内部中断源.由此产生的硬切换都需要换栈运行硬切换硬在需切换工作模式(中断模式).所以会比线程环境下的切换更复杂点但道理还是一样要保存和恢复切换现场寄存器的值 而保存寄存器顺序格式结构体叫:任务中断上下文(TaskIrqContext). 在线程环境下从当前线程切换到目标线程这种方式也称为软切换能由软件控制的自主式切换.哪些情况下会出现软切换呢? 运行的线程申请某种资源(比如各种锁读/写消息队列)失败时需要主动释放CPU的控制权将自己挂入等待队列调度算法重新调度新任务运行.每隔10ms就执行一次的OsTickHandler节拍处理函数检测到任务的时间片用完了就发起任务的重新调度切换到新任务运行.不管是内核态的任务还是用户态的任务于切换而言是统一处理一视同仁的因为切换是需要换栈运行寄存器有限需要频繁的复用这就需要将当前寄存器值先保存到任务自己的栈中以便别人用完了轮到自己再用时恢复寄存器当时的值确保老任务还能继续跑下去. 而保存寄存器顺序格式结构体叫:任务上下文(TaskContext).
本篇说清楚在中断环境下切换(硬切换)的实现过程.
ARM的七种工作模式中有两个是和中断相关.
普通中断模式irq一般中断模式也叫普通中断模式用于处理一般的中断请求通常在硬件产生中断信号之后自动进入该模式该模式可以自由访问系统硬件资源。快速中断模式fiq快速中断模式是相对一般中断模式而言的用来处理高优先级中断的模式处理对时间要求比较紧急的中断请求主要用于高速数据传输及通道处理中。
此处分析普通中断模式下的任务切换过程.
普通中断模式相关寄存器
这张图一定要刻在脑海里系列篇会多次拿出来目的是为了能牢记它. 普通中断模式(图中IRQ列)是一种异常模式有自己独立运行的栈空间.一个(IRQ)中断发生后硬件会将CPSR寄存器工作模式置为IRQ模式.并跳转到入口地址OsIrqHandler执行.
#define OS_EXC_IRQ_STACK_SIZE 64 //中断模式栈大小 64个字节
__irq_stack:.space OS_EXC_IRQ_STACK_SIZE * CORE_NUM
__irq_stack_top:OsIrqHandler汇编代码实现过程就干了三件事: 1.保存任务中断上下文TaskIrqContext2.执行中断处理程序HalIrqHandler这是个C函数由汇编调用3.恢复任务中断上下文TaskIrqContext返回被中断的任务继续执行
TaskIrqContext 和 TaskContext
先看本篇结构体 TaskIrqContext
#define TASK_IRQ_CONTEXT \unsigned int R0; \unsigned int R1; \unsigned int R2; \unsigned int R3; \unsigned int R12; \unsigned int USP; \unsigned int ULR; \unsigned int CPSR; \unsigned int PC;typedef struct {//任务中断上下文
#if !defined(LOSCFG_ARCH_FPU_DISABLE)UINT64 D[FP_REGS_NUM]; /* D0-D31 */UINT32 regFPSCR; /* FPSCR */UINT32 regFPEXC; /* FPEXC */
#endifUINT32 resved;TASK_IRQ_CONTEXT
} TaskIrqContext;typedef struct {//任务上下文已在任务切换篇中详细说明放在此处是为了对比
#if !defined(LOSCFG_ARCH_FPU_DISABLE)UINT64 D[FP_REGS_NUM]; /* D0-D31 */UINT32 regFPSCR; /* FPSCR */UINT32 regFPEXC; /* FPEXC */
#endifUINT32 resved; /* Its stack 8 aligned */UINT32 regPSR; //保存CPSR寄存器UINT32 R[GEN_REGS_NUM]; /* R0-R12 */UINT32 SP; /* R13 */UINT32 LR; /* R14 */UINT32 PC; /* R15 */
} TaskContext;两个结构体很简单目的更简单就是用来保存寄存器现场的值的. 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的栈只是个过渡栈.具体看汇编代码逐行注解分析.
普通中断处理程序
OsIrqHandler: 硬中断处理此时已切换到硬中断栈SUB LR LR #4 记录译码指令地址以防切换过程丢失指令/* push r0-r3 to irq stack */ irq栈只是个过渡栈STMFD SP {R0-R3} r0-r3寄存器入 irq 栈SUB R0 SP #(4 * 4)r0 sp - 16目的是记录{R0-R3}4个寄存器保存的开始位置届时从R3开始出栈MRS R1 SPSR 获取程序状态控制寄存器MOV R2 LR r2lr/* disable irq switch to svc mode */超级用户模式(SVC 模式)主要用于 SWI(软件中断)和 OS(操作系统)。CPSID i #0x13 切换到SVC模式此处一切换后续指令将在SVC栈运行CPSID i为关中断指令对应的是CPSIETaskIrqContext 开始保存中断现场 ...... /* push spsr and pc in svc stack */STMFD SP! {R1 R2} 实际是将 SPSR和PC入栈对应TaskIrqContext.PCTaskIrqContext.CPSRSTMFD SP {LR} LR再入栈SP不自增如果是用户模式LR值将被 282行:STMFD SP {R13 R14}^覆盖 如果非用户模式将被 286行:SUB SP SP #(2 * 4) 跳过.AND R3 R1 #CPSR_MASK_MODE 获取CPU的运行模式CMP R3 #CPSR_USER_MODE 中断是否发生在用户模式BNE OsIrqFromKernel 非用户模式不用将USPULR保存在TaskIrqContext/* push user sp lr in svc stack */STMFD SP {R13 R14}^ 将用户模式的sp和LR入svc栈OsIrqFromKernel: 从内核发起中断/* from svc not need save sp and lr */svc模式下发生的中断不需要保存sp和lr寄存器值SUB SP SP #(2 * 4) 目的是为了留白给 TaskIrqContext.USPTaskIrqContext.ULRTaskIrqContext.ULR已经在 276行保存了276行用的是SP而不是SP!所以此处要跳2个空间/* pop r0-r3 from irq stack*/LDMFD R0 {R0-R3} 从R0位置依次出栈 /* push caller saved regs as trashed regs in svc stack */STMFD SP! {R0-R3 R12} 寄存器入栈对应 TaskIrqContext.R0~R3R12/* 8 bytes stack align */SUB SP SP #4 栈对齐 对应TaskIrqContext.resved/** save fpu regs in case in case those been* altered in interrupt handlers.*/PUSH_FPU_REGS R0 保存fpu regs以防中断处理程序中的fpu regs被修改。TaskIrqContext 结束保存中断现场...... 开始执行真正的中断处理函数了.
#ifdef LOSCFG_IRQ_USE_STANDALONE_STACK 是否使用了独立的IRQ栈PUSH {R4} R4先入栈保存接下来要切换栈需保存现场MOV R4 SP R4SPEXC_SP_SET __svc_stack_top OS_EXC_SVC_STACK_SIZE R1 R2 切换到svc栈
#endif/*BLX 带链接和状态切换的跳转*/BLX HalIrqHandler /* 调用硬中断处理程序无参 说明HalIrqHandler在svc栈中执行 */#ifdef LOSCFG_IRQ_USE_STANDALONE_STACK 是否使用了独立的IRQ栈MOV SP R4 恢复现场sp R4 POP {R4} 弹出R4
#endif/* process pending signals */ 处理挂起信号BL OsTaskProcSignal 跳转至C代码 /* check if needs to schedule */检查是否需要调度CMP R0 #0 是否需要调度R0为参数保存值BLNE OsSchedPreempt 不相等即R0非0一般是 1MOV R0SP 参数MOV R1R7 参数BL OsSaveSignalContextIrq 跳转至C代码 /* restore fpu regs */POP_FPU_REGS R0 恢复fpu寄存器值ADD SP SP #4 sp sp 4 OsIrqContextRestore: 恢复硬中断环境LDR R0 [SP #(4 * 7)] R0 sp 7目的是跳到恢复中断现场TaskIrqContext.CPSR位置刚好是TaskIrqContext倒数第7的位置.MSR SPSR_cxsf R0 恢复spsr 即:spsr TaskIrqContext.CPSRAND R0 R0 #CPSR_MASK_MODE 掩码找出当前工作模式CMP R0 #CPSR_USER_MODE 是否为用户模式?TaskIrqContext 开始恢复中断现场 ...... LDMFD SP! {R0-R3 R12} 从SP位置依次出栈 对应 TaskIrqContext.R0~R3R12此时已经恢复了5个寄存器接来下是TaskIrqContext.USPTaskIrqContext.ULRBNE OsIrqContextRestoreToKernel 看非用户模式怎么恢复中断现场./* load user sp and lr and jump cpsr */LDMFD SP {R13 R14}^ 出栈恢复用户模式sp和lr值 即:TaskIrqContext.USPTaskIrqContext.ULRADD SP SP #(3 * 4) 跳3个位置跳过 CPSR 因为上一句不是 SP!所以跳3个位置刚好到了保存TaskIrqContext.PC的位置/* return to user mode */LDMFD SP! {PC}^ 回到用户模式整个中断过程完成TaskIrqContext 结束恢复中断现场(用户模式下) ...... OsIrqContextRestoreToKernel:从内核恢复中断/* svc mode not load sp */ADD SP SP #4 其实是跳过TaskIrqContext.USP因为在内核模式下并没有保存这个值翻看 287行LDMFD SP! {LR} 弹出LR/* jump cpsr and return to svc mode */ADD SP SP #4 跳过cpsrLDMFD SP! {PC}^ 回到svc模式整个中断过程完成TaskIrqContext 结束恢复中断现场(内核模式下) ......
逐句解读
跳转到 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内容地址45句:读取SPSRLR寄存器内容目的是为了后面在SVC栈中保存TaskIrqContext6句:CPSID i #0x13禁止中断和切换SVC模式执行完这条指令后工作模式将切到 SVC模式TaskIrqContext 开始保存中断现场 …中间代码需配合TaskIrqContext来看不然100%懵逼.结合看就秒懂代码都已经注释不再做解释注解中提到的 翻看276行 是指源码的第276行请对照注解源码看理解会更透彻.TaskIrqContext 结束保存中断现场 …TaskIrqContext保存完现场后就真正的开始处理中断了. /*BLX 带链接和状态切换的跳转*/BLX HalIrqHandler /* 调用硬中断处理程序无参 说明HalIrqHandler在svc栈中执行 */
#ifdef LOSCFG_IRQ_USE_STANDALONE_STACK 是否使用了独立的IRQ栈MOV SP R4 恢复现场sp R4 POP {R4} 弹出R4
#endif/* process pending signals */ 处理挂起信号BL OsTaskProcSignal 跳转至C代码 /* check if needs to schedule */检查是否需要调度CMP R0 #0 是否需要调度R0为参数保存值BLNE OsSchedPreempt 不相等即R0非0一般是 1MOV R0SP 参数MOV R1R7 参数BL OsSaveSignalContextIrq 跳转至C代码 /* restore fpu regs */POP_FPU_REGS R0 恢复fpu寄存器值ADD SP SP #4 sp sp 4 这段代码都是跳转到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页:https://gitcode.com/HarmonyOS_MN
如何快速入门
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.…… 鸿蒙开发面试真题含参考答案:https://gitcode.com/HarmonyOS_MN OpenHarmony 开发环境搭建 《OpenHarmony源码解析》:https://gitcode.com/HarmonyOS_MN
搭建开发环境Windows 开发环境的搭建Ubuntu 开发环境搭建Linux 与 Windows 之间的文件共享……系统架构分析构建子系统启动流程子系统分布式任务调度子系统分布式通信子系统驱动子系统…… OpenHarmony 设备开发学习手册:https://gitcode.com/HarmonyOS_MN 写在最后
如果你觉得这篇内容对你还蛮有帮助我想邀请你帮我三个小忙
点赞转发有你们的 『点赞和评论』才是我创造的动力。关注小编同时可以期待后续文章ing不定期分享原创知识。想要获取更多完整鸿蒙最新学习资源请移步前往