今天学习了uC/OS II的任务切换,知道要实现任务的切换,要将原先任务的寄存器压入任务堆栈,再将新任务中任务堆栈的寄存器内容弹出到CPU的寄存器,其中的CS、IP寄存器没有出栈和入栈指令,所以只能引发一次中断,自动将CS、IP寄存器压入堆栈,再利用中断返回,将新任务的任务断点指针弹出到CPU的CS、IP寄存器中,实现任务切换。虽然明白个大概,但是其中的细节却有点模糊,为什么调用IRET中断返回指令后,弹入CPU的CS、IP寄存器的断点指针是新任务的断点指针,而不是当前任务的,UCOS II是如何实现这个过程的?网上的文章没有提及任务切换的细节,然而这些细节却是理解的重点,所以才有了今天这一篇文章!

    
    在uC/OS II中,任务的调度由任务调度器完成,其主要的工作有两项:
    1.在任务就绪表中查找最高优先级的就绪任务,该任务将是未来切换执行的任务;
    2.实现任务的切换。
    
    任务级的任务调度器,由OS_Sched()实现。
     //!!!为简单说明问题,OS_Sched中特意删减了一些语句
void OS_Sched (void)
{
INT8U y;
OS_ENTER_CRITICAL();
y =OSUnMapTbl[OSRdyGrp];
//得到最高优先级任务,OSPrioHighRdy从此为就绪表中最高优先级任务的优先级别
OSPrioHighRdy=(INT8U)((y <<)+OSUnMapTbl[OSRdyTbl[y]]);
//判断当前任务是否为就绪表中最高优先级任务
if(OSPrioHighRdy!=OSPrioCur)
{
//得到新任务的任务控制块的指针
OSTCBHighRdy=OSTCBPrioTbl[OSPrioHighRdy];
//统计任务切换次数的计数器加1
OSCtxSwCtr++;
//此句关键!使用软件中断切换任务,OS_TASK_SW()其实为INT 0x80,128号中断
//中断产生后,CPU依次将PSW状态寄存器、断点指针段地址:偏移地址压入当前任务的堆栈中
OS_TASK_SW();
}
OS_EXIT_CRITICAL();
}
    从上述代码,可以知道,OS_Sched的任务切换步骤分为两步:
    1.获得最高优先级任务的任务控制块指针;
    2.利用中断实现断点数据的切换。(当前任务中止运行时,CPU寄存器CS、IP、PSW和通用寄存器等中的数据就称为断点数据)
   
     在获得了新任务的任务控制块指针,相当于获得了任务控制块中包含的任务堆栈,而任务堆栈中又包含了该任务运行时,CPU寄存器的初始内容,即断点数据。前面已经提到过 “要实现任务的切换,要将原先任务的寄存器压入任务堆栈,再将新任务中任务堆栈的寄存器内容弹出到CPU的寄存器”,除了CS、IP寄存器,其他寄存器只需要利用出栈和入栈指令即可,而CS、IP寄存器的出栈、入栈要利用中断INT 0x80和IRET。好吧,那问题来了,uC/OS是如何利用中断实现断点指针CS、IP的切换?
    
     产生INT 0x80后,CPU做了什么,当然是去执行和INT 0x80相关的中断服务程序去了(说明:每个中断都有一个对应好的中断服务程序,每当产生该中断,则由CPU自动调用该对应的中断服务程序)。
    
    在uC/OS II中,INT 0x80对应的中断服务程序是
     _OSCtxSw PROC FAR
;
;保存当前任务寄存器内容,将它们压入当前任务堆栈,AX、CX、DX、BX、SP(原始值)、BP、SI 及 DI
PUSHA ;
PUSH ES ;
PUSH DS ;
;
;将当前任务的任务控制块的指针段地址赋值给DS寄存器
MOV AX, SEG _OSTCBCur;Reload DS in case it was altered
MOV DS, AX ;
;
; LES指令作用,取得OSTCBCur变量内容(因为任务控制块的第一个成员为任务堆栈指针,所以ES:[BX+0]表示的地址不仅是任务控制块的首地址,也是任务堆栈指针的地址),低字存放于BX,高字存放于ES,有关LES详细查看另一篇文章!
;同时由于任务控制块的第一成员为任务堆栈指针变量,所以任务堆栈指针成员变量的地址和任务控制块的地址一样
LES BX, DWORD PTR DS:_OSTCBCur; OSTCBCur->OSTCBStkPtr = SS:SP!!!
MOV ES:[BX+], SS ;将当前SS(栈的基地址)寄存器值存放至当前任务控制块的2,3内存单元
MOV ES:[BX+], SP ;将当前SP(栈顶的偏移量)存放至当前任务控制块的0,1内存单元
;
CALL FAR PTR _OSTaskSwHook;Call user defined task switch hook
;
;存储器寻址,DS:_OSTCBHighRdy+2存放的是新任务的栈基址SS,DS:_OSTCBHighRdy存放的是栈顶偏移量SP
MOV AX, WORD PTR DS:_OSTCBHighRdy+;将OSTCBHighRdy赋值给OSTCBCur,使OSTCBCur指向新的任务控制块
MOV DX, WORD PTR DS:_OSTCBHighRdy;OSTCBCur=OSTCBHighRdy
MOV WORD PTR DS:_OSTCBCur+, AX ;
MOV WORD PTR DS:_OSTCBCur, DX ;
;
MOV AL, BYTE PTR DS:_OSPrioHighRdy;OSPrioCur=OSPrioHighRdy
MOV BYTE PTR DS:_OSPrioCur, AL ;
;
;将最高级优先级任务的任务控制块包含的SS和SP寄存器值,CPU的SS和SP指向了新的任务堆栈
LES BX, DWORD PTR DS:_OSTCBHighRdy; SS:SP =OSTCBHighRdy->OSTCBStkPtr
MOV SS, ES:[BX+];
MOV SP, ES:[BX];
;
;注意:这里弹出的是新任务的堆栈,而不是旧的,因为CPU的SS和SP已经指向了新的任务堆栈
POP DS ;Loadnew task's context
POP ES ;
POPA ;
;
;当新任务的堆栈都弹出的时候,只剩下新任务的CS、IP指针,刚好运行IRET弹到CPU的CS、IP寄存器,开始新任务的运行
IRET ;Return to new task
;
_OSCtxSw ENDP
    请仔细将上面代码对照着注释看一遍,注释已经说得很清楚了,_OSCtxSw的堆栈操作,可以看下面两幅图
(0)在调用_OSCtxSw中断服务程序前,CPU将PSW和任务断点指针CS、IP压入当前任务堆栈
(1)将CPU寄存器AX、CX、DX、BX、SP(原始值)、BP、SI 及 DI压入当前任务堆栈
(2)将当前CPU的堆栈指针SS和SP存入当前任务控制块的任务堆栈指针变量(FAR指针变量占4字节)
说明:至此,当前任务的断点数据已经全部保存,所以在每一个新任务运行之前,uC/OS都会将旧任务的断点数据全部按照顺序压入私有堆栈中,同时每一个新任务的任务堆栈都已保存初始化好的或以前任务中止时,CPU保存的断点数据。
(3)OSTCBCur = OSTCBHighRdy、OSPrioCur = OSPrioHighRdy
(4)使CPU的SS和SP堆栈指针指向新的任务堆栈
(5)将新的任务堆栈的内容弹出到CPU寄存器,顺序为DS、ES、DI、SI、BP、SP、BX、DX、CX、AX。
说明:注意是新任务堆栈在进行弹栈操作,而新任务堆栈在弹栈前,和旧任务的断点数据全部压栈后的结构一模一样,都是顺序为DS、ES、DI、SI、BP、SP、BX、DX、CX、AX、IP、CS、PSW。经过POP DS POP ES POPA,这3条指令之后,新任务堆栈便只剩下IP、CS、PSW,IP和CS这断点指针指向新任务的任务代码,只要将它们弹出到CPU的CS、IP寄存器,就可以实现任务切换。
(6)运行IRET,将新任务断点指针弹出到CPU的CS、IP指针寄存器,PSW弹出到CPU的PSW寄存器
(7)至此,uC/OS开始运行新任务
参考链接:
μC-OS-Ⅱ中通过中断返回指令实现任务切换  http://www.docin.com/p-223857136.html
我对OSCtxSW()任务级任务切换函数的理解(以图例的方式) http://blog.163.com/muren20062094%40yeah/blog/static/1618444162011727102557489/
uCOSii中断处理过程详解 http://www.doc88.com/p-1498746979512.html
uC/OS-II任务栈处理的一种改进方法 http://www.3edu.net/lw/qrs/lw_46692.html

本文链接:http://www.cnblogs.com/cposture/p/4291503.html

【原创】uC/OS II 任务切换原理的更多相关文章

  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. uC/OS II 函数说明 之–OSTaskCreate()与OSTaskCreateExt()

    1. OSTaskCreate()    OSTaskCreate()建立一个新任务,能够在多任务环境启动之前,或者执行任务中建立任务.注意,ISR中禁止建立任务,一个任务必须为无限循环结构.    ...

  4. uc/os iii移植到STM32F4---IAR开发环境

    也许是先入为主的原因,时钟用不惯Keil环境,大多数的教程都是拿keil写的,尝试将官方的uc/os iii 移植到IAR环境. 1.首先尝试从官网上下载的官方移植的代码,编译通过,但是执行会报堆栈溢 ...

  5. 【原创】uC/OS 中LES BX,DWORD PTR DS:_OSTCBCur的作用及原理

    LES BX, DWORD PTR DS:_OSTCBCur ;OSTCBCur->OSTCBStkPtr = SS:SP!!! ], SS ;将当前SS(栈的基地址)寄存器值存放至当前任务控制 ...

  6. 在STM32F401上移植uC/OS的一个小问题 [原创]

    STM32F401xx是意法半导体新推出的Cortex-M4内核的MCU,相较于已经非常流行的STM32F407xx和STM32F427xx等相同内核的MCU而言,其特点是功耗仅为128uA/MHz, ...

  7. 关于uC/OS的简单学习(转)

    1.微内核 与Linux的首要区别是,它是一个微内核,内核所实现的功能非常简单,主要包括: 一些通用函数,如TaskCreate(),OSMutexPend(),OSQPost()等. 中断处理函数, ...

  8. uc/os任务创建

    问题描述:      uc/os中任务创建 问题解决: 创建一个任务,任务从无到有.任务创建函数分两种, 一种是基本的创建函数OSTaskCreate, 另一种是扩展的任务创建函数OSTaskCrea ...

  9. uC/OS 的任务调度解析 (转)

    uC/OS 的任务调度解析 1.任务调度器启动之后(初始化,主要是TCB的初始化),就可以创建任务,开始任务调度了,实际上第一个任务准确的说不是进行任务切换,而是进行启动当前最高优先级任务.uC/OS ...

随机推荐

  1. 利用insertd查出更新记录

    DROP TABLE #tableCREATE TABLE #table(CompanyID VARCHAR(20),BillNo VARCHAR(40))UPDATE dbo.SD_Inv_Move ...

  2. REdis MASTER aborted replication NOAUTH Authentication required

    对于REdis集群,如果设置了requirepass,则一定要设置masterauth,否则从节点无法正常工作,查看从节点日志可以看到哪下内容:19213:S 22 Apr 2019 10:52:17 ...

  3. 洛谷P2689 东南西北

    https://www.luogu.org/problemnew/show/P2689 #include<iostream> #include<algorithm> using ...

  4. js获取当前页面的url网址信息小汇总

    在WEB开发中,时常会用到javascript来获取当前页面的url网址信息,在这里是我的一些获取url信息的小总结. 下面我们举例一个URL,然后获得它的各个组成部分:http://i.cnblog ...

  5. python网络爬虫开发实战(崔庆才)_14页_chromedriver环境配置和加载

    自己1,环境配置,我下载了相对应的Chromedriver(其实我也不知道对不对应,都是下载最新版的我猜应该会对应),然后在任何文件夹下输入command+shift+G,打开输入窗口,任何输入  / ...

  6. Linux 查找文件内容、替换

    有的时候我们经常性的需要在 linux 某一个目录下查找那些文件里包含我们需要查找的字符,那么这个时候就可以使用一些命令来查找,比如说 grep 1.grep 查询 1.1. 主要参数 [option ...

  7. Exp5MSF基础应用——20164325王晓蕊

    1.实验要求 一个主动攻击实践,ms08_067; 一个针对浏览器的攻击,MS11-003(唯一): 一个针对客户端的攻击,adobe_toolbutton: 成功应用任何一个辅助模块Ipidseq( ...

  8. some knowledge of the IT world

    IT世界一切皆是可信息化(数据的转换)即信息记录一切,对信息的控制{存储,运算,传输{信息的位置转移},转换}就是对一切的控制{硬件(实质维)以信息的控制{软件形式(存在维)}进行操作} 信息本身的实 ...

  9. js-图片轮播(极简)

    <!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8" ...

  10. 中间件 activeMQ Jms Java Demo

    一.什么是ActiveMQ 百度解释: ActiveMQ 是Apache出品,最流行的,能力强劲的开源消息总线.ActiveMQ 是一个完全支持JMS1.1和J2EE 1.4规范的 JMS Provi ...