历史上的今天
今天是:2025年04月25日(星期五)
2019年04月25日 | UCOIII中任务的调度和切换
2019-04-25 来源:eefocus
一、UCOSIII任务调度
1、可剥夺型任务调度
定义:任务调度就是中止当前正在运行的任务转而去执行其他的任务(UCOSIII是可剥夺型内核,因此当一个高优先级的任务准备就绪,并且此时发生了任务调度,那么这个高优先级的任务就会获得CPU的使用权)
UCOSIII中的任务调度是由任务调度器来完成的,任务调度器有2种:任务级调度器和中断级调度器。
任务级调度器为函数OSSched()。
//OSSched为任务级调度器,如果在中断服务函数中不能使用
void OSSched (void)
{
CPU_SR_ALLOC();
//判断OSSched是否在中断服务函数中使用
if (OSIntNestingCtr > (OS_NESTING_CTR)0)
{
return;
}
//调度器是否上锁
if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0)
{
return;
}
CPU_INT_DIS(); //关中断
OSPrioHighRdy = OS_PrioGetHighest();//获取任务就绪表中最高优先级任务
//获取下次任务切换要运行的任务,OSTCBHighRdyPtr指向将要切换任务的OS_TCB
OSTCBHighRdyPtr = OSRdyList[OSPrioHighRdy].HeadPtr;
//判断要运行的任务是否是正在运行的任务,是就不用切换
if (OSTCBHighRdyPtr == OSTCBCurPtr)
{
CPU_INT_EN();
return;
}
#if OS_CFG_TASK_PROFILE_EN > 0u
OSTCBHighRdyPtr->CtxSwCtr++;
#endif
OSTaskCtxSwCtr++;
#if defined(OS_CFG_TLS_TBL_SIZE) && (OS_CFG_TLS_TBL_SIZE > 0u)
OS_TLS_TaskSw();
#endif
OS_TASK_SW(); //执行任务切换
CPU_INT_EN(); //开中断
}
中断级调度器为函数OSIntExit(),当退出外部中断服务函数的时候使用中断级任务调度。
void OSIntExit (void)
{
CPU_SR_ALLOC();
if (OSRunning != OS_STATE_OS_RUNNING) //判断UCOSIII,未运行就跳出
{
return;
}
CPU_INT_DIS();
if (OSIntNestingCtr == (OS_NESTING_CTR)0) //OSIntNestingCtr中断嵌套计数器,判断是否为0,确保退出时调用OSIntExit()后不会等于负数
{
CPU_INT_EN();//记录中断嵌套次数
return;
}
OSIntNestingCtr--;//3
if (OSIntNestingCtr > (OS_NESTING_CTR)0)//>0说明还有其他中断发生,不做任务切换
{
CPU_INT_EN();
return;
}
if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0) //调度器是否加锁
{
CPU_INT_EN();
return;
}
OSPrioHighRdy = OS_PrioGetHighest(); //取出最高优先级任务的控制块
OSTCBHighRdyPtr = OSRdyList[OSPrioHighRdy].HeadPtr;
if (OSTCBHighRdyPtr == OSTCBCurPtr)
{
CPU_INT_EN();
return;
}
#if OS_CFG_TASK_PROFILE_EN > 0u
OSTCBHighRdyPtr->CtxSwCtr++;
#endif
OSTaskCtxSwCtr++;
#if defined(OS_CFG_TLS_TBL_SIZE) && (OS_CFG_TLS_TBL_SIZE > 0u)
OS_TLS_TaskSw();
#endif
OSIntCtxSw(); //调用中断级任务切换函数
CPU_INT_EN();//开中断
}
2、任务调度点(重点红色)
(1)、释放信号量或者发送消息,也可通过配置相应的参数不发生任务调度。
(2)、使用延时函数OSTimeDly()或者OSTimeDlyHMSM()。
(3)、任务等待的事情还没发生(等待信号量,消息队列等)。
(4)、任务取消等待。
(5)、创建任务。
(6)、删除任务。
(7)、删除一个内核对象。
(8)、任务改变自身的优先级或者其他任务的优先级。
(9)、任务通过调用OSTaskSuspend()将自身挂起。
(10)、任务解挂某个挂起的任务。
(11)、退出所有的嵌套中断。
(12)、通过OSSchedUnlock()给调度器解锁。
(13)、任务调用OSSchedRoundRobinYield()放弃其执行时间片。
(14)、用户调用OSSched()。
3、调度器上锁和解锁:
有时候我们并不希望发生任务调度,因为始终有一些代码的执行过程是不能被打断的。此时我们就可以使用函数OSSchedLock()对调度器加锁,当我们想要恢复任务调度的时候就可以使用函数OSSchedUnlock()给已经上锁的任务调度器解锁
4、时间片轮转调度
UCOSIII允许一个优先级下有多个任务,每个任务可以执行指定的时间(时间片),然后轮到下一个任务,这个过程就是时间片轮转调度,当一个任务不想在运行的时候就可以放弃其时间片。
时间片轮转调度器为:OS_SchedRoundRobin()。
时间片轮转调度示例:


二、UCOSIII任务切换
1、什么是任务切换?
当UCOSIII需要切换到另外一个任务时,它将保存当前任务的现场到当前任务的堆栈中,主要是CPU寄存器值,然后恢复新的现场并且执行新的任务,这个过程就是任务切换。
任务切换分为两种:任务级切换和中断级切换。
任务级切换函数为:OSCtxSw()。
中断级切换函数为:OSIntCtxSw()。
2、任务控制块结构
任务控制块是用来记录与任务相关的信息的数据结构,每个任务都要有自己的任务控制块。任务控制块由用户自行创建,如下代码为创建一个任务控制块:
OS_TCB StartTaskTCB; //创建一个任务控制块
OS_TCB为一个结构体,描述了任务控制块,任务控制块中的成员变量用户不能直接访问,更不可能改变他们。
OS_TCB为一个结构体,其中有些成员采用了条件编译的方式来确定
下一篇:UCOSIII系统初始化和启动
史海拾趣
|
在wince下,很多视频无法播放,mp4,wmv,mpeg,avi的也有不能播放的,公司要解决这问题,花钱也可以,要是有能解决此问题的,联系我dsl000522@hotmail.com… 查看全部问答> |
|
单片机ip210w(8051+Mac) 我要在该单片机上实现Tcp/IP协议,借助了一个uip的东西 uip最终的发送,需要mac来完成 驱动至少包括3个方法:mac_init,mac_send,mac_recv. 我没有写过这种驱动,请大家给点意见。 关于Mac的寄存器很多,看不太明白啊, ...… 查看全部问答> |
|
初学Zigbee(MiWi),有前辈给指点下如何快速上手不? -Micrchip MiWi solution. -Demo board都有了 -相关文档也看了不少,总觉得比较浅,望有经验的前辈指点下接下来怎样更全面的学习… 查看全部问答> |
|
虽然前面做的xds-mini算上人力成本,严重赔钱了 现在依然开始准备团购的事宜 团购产品考虑贴上EEWorld的标, SOSO帮问问看可不可以呀 团购说明: 目前,我的净器件成本约为100元左右,为什么不是五六十,咱没量,你懂的 团购打算出去贴,这样 ...… 查看全部问答> |
|
ADuC8XX UART Emulation Many customers have puzzles about the application of the ADuC8XX UART Emulation. This document introduces the steps about how to realize it. Using UART Emulation can save cost and make emulation easy ...… 查看全部问答> |
|
本帖最后由 digitaltek 于 2014-10-31 11:58 编辑 A:概述 在考试的时候,特别是英语考试的时候都有选择题,一般我们都是涂答题卡,然后上交后,由读卡器来读取答 ...… 查看全部问答> |
|
本帖最后由 daxigua 于 2015-10-26 16:50 编辑 大西瓜《FPGA开发实战手册》 大西瓜FPGA开发团队,自创8万多字图文教程,基于FPGA的基础+进阶+综合实验,助你一板一教程就将FPGA搞定!废话少说,直接上图 下载链接 ...… 查看全部问答> |




