首先贴出今天要与大家分享的内容源码(位于内核源码的 os_cpu_a.asm 中):

PendSV_Handler
  CPSID I
  MRS R0, PSP
  CBZ R0, PendSV_Handler_Nosave

  SUBS R0, R0, #0x20
  STM R0, {R4-R11}

  LDR R1, =OSTCBCur
  LDR R1, [R1]
  STR R0, [R1]

PendSV_Handler_Nosave
  PUSH {R14}
  LDR R0, =OSTaskSwHook
  BLX R0
  POP {R14}

  LDR R0, =OSPrioCur
  LDR R1, =OSPrioHighRdy
  LDRB R2, [R1]
  STRB R2, [R0]

  LDR R0, =OSTCBCur
  LDR R1, =OSTCBHighRdy
  LDR R2, [R1]
  STR R2, [R0]

  LDR R0, [R2]
  LDM R0, {R4-R11}
  ADDS R0, R0, #0x20
  MSR PSP, R0
  ORR LR, LR, #0x04
  CPSIE I
  BX LR

这两段代码尤为重要,内核中任务的切换主要就是由它们实现的。接下来,我将逐行为大家解析其中的奥秘。

这两段代码是中断服务程序(ISR),那么由谁来触发中断呢?我们以OSCtxSw()这个函数为入手点。
它其实就是C程序中的OS_TASK_SW()

#define OS_TASK_SW() OSCtxSw()

开始分析OSCtxSw()

OSCtxSw
  PUSH {R4, R5}
  LDR R4, =NVIC_INT_CTRL
  LDR R5, =NVIC_PENDSVSET
  STR R5, [R4]
  POP {R4, R5}
  BX LR

1.首先进入函数,将R4,R5入栈,保护寄存器。
2.给R4,R5分别赋值,文件中这样定义:
NVIC_INT_CTRL EQU 0xE000ED04
NVIC_PENDSVSET EQU 0x10000000
NVIC_INT_CTRL为中断控制寄存器的地址,NVIC_PENDSVSET为PendSV中断的触发值
3.将触发值写入控制寄存器
4.弹出R4,R5

因为我们一般调用任务切换的时候,都是在临界区调用(禁止中断),所以不会产生中断。之后调用OS_EXIT_CRITICAL()函数退出临界区后,中断才会发生,这样就产生了PendSV异常。

接下来才是我们的重点,开始分析ISR!

CPSID I
#关中断,防止切换任务期间被打扰

MRS R0, PSP
#取出PSP(程序栈指针)赋值给R0

CBZ R0, PendSV_Handler_Nosave
#若R0为0,则跳转到PendSV_Handler_Nosave函数继续执行,这里我们讲述的就是由延时导致的任务切换,PSP都是有值的,所以继续执行

SUBS R0, R0, #0x20
#将R0 - 0x20 则R0与PSP之间空出8个单位(每个单位4个字节)

STM R0, {R4-R11}
#将寄存器的R4-R11存入空出的8个单位

LDR R1, =OSTCBCur
#将当前TCB的地址赋给R1

LDR R1, [R1]
#取出地址处的数据(即OSTCBCur->SP的地址,因为OSTCB结构体的第一个数据就是SP)赋给R1

STR R0, [R1]
#将R0(栈顶数据的地址)赋值给OSTCBCur->SP,则OSTCBCur->SP与R0指向的位置相同

!!这段程序的OSTCBCur指的都是old_task的指针

这段程序的图解:

PUSH {R14}
LDR R0, =OSTaskSwHook
BLX R0
POP {R14}
#这小段代码就是执行OSTaskSwHook这个C的函数

LDR R0, =OSPrioCur
LDR R1, =OSPrioHighRdy
LDRB R2, [R1]
STRB R2, [R0]
#这小段代码就将OSPrioHighRdy赋给OSPrioCur

LDR R0, =OSTCBCur
LDR R1, =OSTCBHighRdy
LDR R2, [R1]
STR R2, [R0]
#这小段代码就将OSTCBHighRdy->SP赋给OSPrioCur->SP

LDR R0, [R2]
#将OSTCBHighRdy->SP的值(指向新任务栈中的地址,也就是新任务的栈顶)赋值给R0

LDM R0, {R4-R11}
#以R0为基址,读出8个单位的数据给CPU的寄存器

ADDS R0, R0, #0x20
#R0地址 + 0x20,指向几个重要的寄存器值(当前栈顶)

MSR PSP, R0
#将当前R0的值赋值给PSP

ORR LR, LR, #0x04
#确保异常返回后,新任务使用PSP指针

CPSIE I
#开启中断

!!这段程序的OSTCBCur指的都是new_task的指针

这段程序的图解:

这样也就完成了old_task到new_task的切换!

μC/OS-II 要点分析 ------ PendSV_Handler的更多相关文章

  1. uC/OS II原理分析及源码阅读(一)

    uC/OS II(Micro Control Operation System Two)是一个可以基于ROM运行的.可裁减的.抢占式.实时多任务内核,具有高度可移植性,特别适合于微处理器和控制器,是和 ...

  2. 【小梅哥SOPC学习笔记】NIOS II处理器运行UC/OS II

    SOPC开发流程之NIOS II 处理器运行 UC/OS II 这里以在芯航线FPGA学习套件的核心板上搭建 NIOS II 软核并运行 UCOS II操作系统为例介绍SOPC的开发流程. 第一步:建 ...

  3. [Spark性能调优] 第一章:性能调优的本质、Spark资源使用原理和调优要点分析

    本課主題 大数据性能调优的本质 Spark 性能调优要点分析 Spark 资源使用原理流程 Spark 资源调优最佳实战 Spark 更高性能的算子 引言 我们谈大数据性能调优,到底在谈什么,它的本质 ...

  4. 【原创】uC/OS II 任务切换原理

    今天学习了uC/OS II的任务切换,知道要实现任务的切换,要将原先任务的寄存器压入任务堆栈,再将新任务中任务堆栈的寄存器内容弹出到CPU的寄存器,其中的CS.IP寄存器没有出栈和入栈指令,所以只能引 ...

  5. spark 性能调优(一) 性能调优的本质、spark资源使用原理、调优要点分析

    转载:http://www.cnblogs.com/jcchoiling/p/6440709.html 一.大数据性能调优的本质 编程的时候发现一个惊人的规律,软件是不存在的!所有编程高手级别的人无论 ...

  6. 性能调优的本质、Spark资源使用原理和调优要点分析

    本课主题 大数据性能调优的本质 Spark 性能调优要点分析 Spark 资源使用原理流程 Spark 资源调优最佳实战 Spark 更高性能的算子 引言 我们谈大数据性能调优,到底在谈什么,它的本质 ...

  7. AS3和js相互通信要点分析

    目标:在html页面里可以使用事件来影响到swf文件的内容,swf文件也可以影响html里js代码的内容 一.新建flash文件,用Flash CC试用版新建一个TextArea.fla的源文件,不添 ...

  8. 混合事务分析处理“HTAP”的技术要点分析

    HTAP是近些年来比较火的一个概念,本文将聊聊HTAP的前世今生及技术特点. 一.数据应用类别 根据数据的使用特征,可简单做如下划分.在选择技术平台之前,我们需要做好这样的定位. 1.1 OLTP 联 ...

  9. Java 8 中 ConcurrentHashMap工作原理的要点分析

    简介: 本文主要介绍Java8中的并发容器ConcurrentHashMap的工作原理,和其它文章不同的是,本文重点分析了对不同线程的各类并发操作如get,put,remove之间是如何同步的,以及这 ...

随机推荐

  1. [小结]InnoDB体系结构及工作原理

    参阅:<innodb存储引擎内幕>原创文章,会不定时更新,转发请标明出处:http://www.cnblogs.com/janehoo/p/7717041.html 一.概述: innod ...

  2. kubernetes1.7.6 ha高可用部署

    写在前面:  1. 该文章部署方式为二进制部署. 2. 版本信息 k8s 1.7.6,etcd 3.2.9 3. 高可用部分 etcd做高可用集群.kube-apiserver 为无状态服务使用hap ...

  3. 《Serverless架构-无服务单页应用开发》读后感

    本书的作者是[美]Ben Rady,译者郑赞美.简传挺,书中作者详细的介绍了如何使用html.js以及amazon提供的诸多云服务(Simple Storage Service(S3).Cognito ...

  4. IDEA打开maven项目dependencies红线

    第一步:install报红的项目,从maven库下载需要的包,看看日志还缺哪些本地包,少了就去下,丢到库里.不缺包后,reimport一下一般就OK了,如果还是红的,重启一下就好了. 如果第一步还没好 ...

  5. Python之旅Day8 socket网络编程

    socket网络编程 Socket是网络编程的一个抽象概念.通常我们用一个Socket表示“打开了一个网络链接”,而打开一个Socket需要知道目标计算机的IP地址和端口号,再指定协议类型即可.soc ...

  6. [转]Understand QoS at OpenSwitch

    danny http://dannykim.me/danny/57771 2014.02.11 14:34:58 (*.193.128.184) 592 >>> Purpose Th ...

  7. 利用Module模块把构建的神经网络跑起来

    训练一个神经网络往往只需要简单的几步: 准备训练数据 初始化模型的参数 模型向往计算与向后计算 更新模型参数 设置相关的checkpoint 如果上述的每个步骤都需要我们写Python的代码去一步步实 ...

  8. 移动端调试神器-vConsole

    什么是vConsole?   官方说明是一个web前端开发者面板,可用于展示console日志,方便日常开发,调试. 简单来说相当于移动版的Chrome调试控制台,就是我们在PC端常用的F12 vCo ...

  9. Python find函数用法和概念

    概念: Python find() 方法检测字符串中是否包含子字符串 str ,如果指定 beg(开始) 和 end(结束) 范围,则检查是否包含在指定范围内,如果包含子字符串返回开始的索引值,否则返 ...

  10. mac中:不能完成此操作,因为找不到一个或多个需要的项目。(错误代码 -43)

    今天使用mac删除某文件时,遇到此错误: 不能完成此操作,因为找不到一个或多个需要的项目.(错误代码 -43) 于是采用命令行删除可以正确删除:在要删除的文件夹坐在目录下执行   rm -rf tes ...