OS_CORE.C(8)
本篇介绍的是OSStart()函数和OSStatInit()函数和OSTimeTick()函数。
OSStart()多任务开始函数:
/*$PAGE*/
/*
*********************************************************************************************************
* START MULTITASKING
* 启动多个任务
* Description: This function is used to start the multitasking process which lets uC/OS-II manages the
* task that you have created. Before you can call OSStart(), you MUST have called OSInit()
* and you MUST have created at least one task.
* 该功能用来开始多任务进程,使UC/OS-II管理你所创建的任务。在调用OSStart()之前必须先调用OSInit()并且必须创建至少一个任务
* Arguments : none
*
* Returns : none
*
* Note : OSStartHighRdy() MUST:
* a) Call OSTaskSwHook() then,调用OSStartHighRdy()之后就调用OSTaskSwHook()函数
* b) Set OSRunning to OS_TRUE.将OSRunning设置为真,指出多任务已经开始
* c) Load the context of the task pointed to by OSTCBHighRdy.加载高优先级就绪任务启动函数中指出的任务的上下文
* d_ Execute the task.执行任务
*********************************************************************************************************
*/void OSStart(void) /*启动多个任务*/
{if (OSRunning == OS_FALSE) { /*此时没有多任务*/OS_SchedNew(); /* Find highest priority's task priority number 找到最高优先级的任务优先级号 */OSPrioCur = OSPrioHighRdy; /*将最高优先级任务的优先级号作为当前要执行任务的优先级号*/OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy]; /* Point to highest priority task ready to run 指向将要运行的最高优先级任务 */OSTCBCur = OSTCBHighRdy; /*将高优先级任务的TCB作为当前TCB*/OSStartHighRdy(); /* Execute target specific code to start task执行代码开始任务 */}
}
将上述代码总结为如图所示流程:
OSStatInit()统计任务初始化函数:
/*$PAGE*/
/*
*********************************************************************************************************
* STATISTICS INITIALIZATION
* 统计任务初始化
* Description: This function is called by your application to establish CPU usage by first determining
* how high a 32-bit counter would count to in 1 second if no other tasks were to execute
* during that time. CPU usage is then determined by a low priority task which keeps track
* of this 32-bit counter every second but this time, with other tasks running. CPU usage is
* determined by:
* 统计初始化函数OSStatInit()决定在没有其它应用任务运行时,空闲计数器(OSIdleCtr)的计数有多快。这个任务每秒执行一次,以确定所有应用程序中的任务消耗了多少CPU时间。当用户的应用程序代码加入以后,运行空闲任务的CPU时间就少了,OSIdleCtr就不会像原来什么任务都不运行时有那么多计数。要知道,OSIdleCtr的最大计数值是OSStatInit()在初始化时保存在计数器最大值OSIdleCtrMax中的。
* OSIdleCtr
* CPU Usage (%) = 100 * (1 - ------------)
* OSIdleCtrMaxCPU使用率(百分比形式)=100*(1-空闲计数值/设定最大空闲计数值)
*
* Arguments : none
*
* Returns : none
*********************************************************************************************************
*/#if OS_TASK_STAT_EN > 0u
void OSStatInit(void) /*统计任务初始化*/
{
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register 中断函数被设定为模式3 */OS_CPU_SR cpu_sr = 0u;
#endifOSTimeDly(2u); /* Synchronize with clock tick调用延迟函数OSTimeDly()将自身延时2个时钟节拍以停止自身的运行,这是为了使OSStatInit()与时钟节拍同步 */OS_ENTER_CRITICAL(); /*关闭中断(进入中断)*/OSIdleCtr = 0uL; /* Clear idle counter 执行OSStartInit()时,空闲计数器OSIdleCtr被清零*/OS_EXIT_CRITICAL(); /*打开中断*/OSTimeDly(OS_TICKS_PER_SEC / 10u); /* Determine MAX. idle counter value for 1/10 second确定最大空闲计数值为1或10s */OS_ENTER_CRITICAL(); /*关闭中断*/OSIdleCtrMax = OSIdleCtr; /* Store maximum idle counter count in 1/10 second 存储最大空闲计数值 */OSStatRdy = OS_TRUE; /*将统计任务就绪标志OSStatRdy设为"真",以此来允许两个时钟节拍以后OSTaskStat()开始计算CPU的利用率*/OS_EXIT_CRITICAL(); /*打开中断*/
}
#endif
OSTimeTick()时钟节拍函数:
/*$PAGE*/
/*2018/2/3~2/7
*********************************************************************************************************
* PROCESS SYSTEM TICK
* 时钟节拍函数
* Description: This function is used to signal to uC/OS-II the occurrence of a 'system tick' (also known
* as a 'clock tick'). This function should be called by the ticker ISR but, can also be
* called by a high priority task.
*该功能是用来给uc/os发送时钟信号。该功能称为时钟中断,也叫做高优先级任务
* Arguments : none
*
* Returns : none
*********************************************************************************************************
*/void OSTimeTick(void) /*时钟节拍函数*/
{OS_TCB *ptcb; /*指向TCB列表的的指针*/
#if OS_TICK_STEP_EN > 0uBOOLEAN step; /*设置一个布尔型变量*/
#endif
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register中断函数被设定为模式3 */OS_CPU_SR cpu_sr = 0u;
#endif#if OS_TIME_TICK_HOOK_EN > 0u /*可以生成时钟钩子函数OS_TIME_TICK_HOOK()*/OSTimeTickHook(); /* Call user definable hook 调用用户自定义钩子函数 */
#endif
#if OS_TIME_GET_SET_EN > 0u /*可以生成OS_TIME_GET_SET()函数*/OS_ENTER_CRITICAL(); /* Update the 32-bit tick counter 更新32位节拍数,关中断 */OSTime++; /*/累加从开机以来的时间,用的是一个无符号32位变量*/OS_EXIT_CRITICAL(); /*开中断*/
#endifif (OSRunning == OS_TRUE) {
#if OS_TICK_STEP_EN > 0uswitch (OSTickStepState) { /* Determine whether we need to process a tick步进的状态:决定我们是否需要处理节拍 */case OS_TICK_STEP_DIS: /* Yes, stepping is disabled 步进被禁用 */step = OS_TRUE; break;case OS_TICK_STEP_WAIT: /* No, waiting for uC/OS-View to set ...步进等待状态:等待uC/OS-View将步进状态设置成进一步*/step = OS_FALSE; break;case OS_TICK_STEP_ONCE: /* Yes, process tick once and wait for next ...步进一次等待下一步命令 */step = OS_TRUE; /*... step command from uC/OS-View步进命令来自于uc/os-view*/OSTickStepState = OS_TICK_STEP_WAIT; /*将步进状态设置为步进等待状态*/break;default: /* Invalid case, correct situatio无效的情况或者正确的情况下*/step = OS_TRUE; OSTickStepState = OS_TICK_STEP_DIS; /*将步进状态设置为禁止状态*/break;}if (step == OS_FALSE) { /* Return if waiting for step command如果正在等待步进命令,返回*/return;}
#endifptcb = OSTCBList; /* Point at first TCB in TCB list 指向TCB列表的第一个*/while (ptcb->OSTCBPrio != OS_TASK_IDLE_PRIO) { /* Go through all TCBs in TCB list 浏览TCB列表的所有TCB*/OS_ENTER_CRITICAL(); /*进入中断*/if (ptcb->OSTCBDly != 0u) { /* No, Delayed or waiting for event with TO等待任务时的最多节拍数不为0*/ptcb->OSTCBDly--; /* Decrement nbr of ticks to end of delay时间延迟项减1*/if (ptcb->OSTCBDly == 0u) { /* Check for timeout减1后检查是否到时间了。时间延迟项等于0,就转为就绪态(外部条件准备就绪)*/if ((ptcb->OSTCBStat & OS_STAT_PEND_ANY) != OS_STAT_RDY) { /*(检查内部条件是否准备就绪)如果TCB状态和挂起状态进行位与运算之后不等于准备好的状态,简单来说就是任务没有准备好*/ptcb->OSTCBStat &= (INT8U)~(INT8U)OS_STAT_PEND_ANY; /* Yes, Clear status flag清除状态标志*/ptcb->OSTCBStatPend = OS_STAT_PEND_TO; /* Indicate PEND timeout将TCB挂起状态设置为超时状态*/}else { /*如果是已准备好的状态(内部条件准备就绪)*/ptcb->OSTCBStatPend = OS_STAT_PEND_OK;/*就将TCB挂起状态设置为挂起结束(正常结束)状态*/}if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) == OS_STAT_RDY) { /* Is task suspended? 查看任务是否为挂起状态*/OSRdyGrp |= ptcb->OSTCBBitY; /* No, Make ready如果不是(即已为就绪态),在就绪表中找到具体的任务控制块*/OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;}}}ptcb = ptcb->OSTCBNext; /* Point at next TCB in TCB list指向TCB列表的下一个 */OS_EXIT_CRITICAL(); /*退出中断(开中断)*/}}
}
同时介绍一下相关的时间管理方面的内容:http://blog.csdn.net/adam_embedded/article/details/46323491
1.1 时钟节拍
UCOSii通过时钟节拍OSTimeTick()来定期进行任务调度,一般来说这个频率是10-100HZ,频率越高,系统的开销也就越大。
1.2 任务延时函数
OSTimeDly()
任务可以调用OSTimeDly()来对自身延时一段时间。延时时,任务被挂起。任务被延时的时间必须是时钟节拍的倍数。与延时有关的变量在Tcb结构体中。
Tcb.OSTCBDly表示任务自己延时挂起的时间。
这样,当任务调用OSTimeDly()来进行延时时,该函数会修改修改OSTCBDly的值,把要延时的次数写入该变量,最后进行任务调度即可。
每次时钟节拍发生的时候,OSTCBDly的值都会被减去一,当该值为0的时候,内核就会把它放入就绪队列。
NOTE: 当调用OSTimeDly(1)只延时一个时钟节拍的时候,由于任务可能运行在一个时钟节拍的中后期,此时经过不到半个时钟节拍的时间,OSTCBDly的值就会被修改。因此,如果用户的应用程序至少得延时一个节拍,必须要调用 OSTimeDly(2),指定延时两个节拍。(即指定延时1,延时可能不足1,但是指定延时为2,至少可以保证延时一个节拍)。
来看一下OSTimeDly()的结构和原型:
结构:
void OSTimeDly(OS_TICK dly,//指定延时的长度,单位为时间节拍OS_OPT opt,//延时模式OS_ERR *p_err//错误信息
)
- 如果延时时间dly>0,则会发生任务调度;0表示不延时
OSTimeDly()
函数延时模式有四种:OS_OPT_TIME_DLY;OS_OPT_TIME_TIMEOUT;OS_OPT_TIME_PERIODIC;OS_OPT_TIME_MATCH;
void OSTimeDly (INT16U ticks)
{if (ticks > 0) {OS_ENTER_CRITICAL();if ((OSRdyTbl[OSTCBCur->OSTCBY] &= ~OSTCBCur->OSTCBBitX) == 0) {OSRdyGrp &= ~OSTCBCur->OSTCBBitY;} OSTCBCur->OSTCBDly = ticks;OS_EXIT_CRITICAL();OSSched();}
}
可以看到该函数将延时次数传递给了OSTCBDly。
OSTimeDly()有一些缺点:一是只能延时65535次时钟节拍,二是不能换算成时间。
1.3 结束任务延时函数
OSTimeDlyResume()函数可以被用来强制某一任务结束延时,它的主要作用是支持任务之间的通讯和同步。
OSTimeDlyResume()要做的就是将OSTCBDly清0,然后进行任务调度。
1.4 系统时间
每次发生时钟节拍时,UCOS都会将一个32位的计数器加1。
OSTimeGet()和 OSTimeSet()用来获取或者设置这个计数器的值。
OS_CORE.C(8)相关推荐
- OS_CORE.C(11)
OS_SchedNew(void)找到将要运行的最高优先级任务函数 和任务调度函数OS_Sched(void): /* **************************************** ...
- OS_CORE.C(10)
今天看os_core.c文件中的各种初始化函数. OS_EventWaitListInit(OS_EVENT *pevent)初始化事件控制块的等待列表: /*$PAGE*/ /*2018/2/8 * ...
- OS_CORE.C(总结)
在内核的功能模块中,重点函数为: static void OS_InitEventList(void);/*初始化事件列表*/ static void OS_InitMisc(void);/* ...
- OS_CORE.C(1)
第一个函数(获得信号量.互斥量.邮箱或者队列名字的函数)的流程图和分析图如下所示: /*$PAGE*/ /* ********************************************* ...
- OS_CORE.C(9)
本篇介绍以下几个函数: OSVersion()获得版本号函数. OS_Dummy()虚拟函数. OS_EventTaskRdy (OS_EVENT *pevent, void *msg, INT8U ...
- OS_CORE.C(6)
先介绍一下优先级反转的相关知识: 优先级翻转是当一个高优先级任务通过信号量机制访问共享资源时,该信号量已被一低优先级任务占有,因此造成高优先级任务被许多具有较低优先级任务阻塞,实时性难以得到保证. 例 ...
- OS_CORE.C(5)
/*$PAGE*/ /* *************************************************************************************** ...
- OS_CORE.C(3)
OSTCBCur->OSTCBStat |= events_stat | /* Resource not available, ...无法获得资源的话就将其挂起 */OS_STAT_MULTI; ...
- OS_CORE.C(7)
本篇介绍的是调度器的上锁和解锁: 调度器上锁函数OSSchedlock()的功能是用于禁止任务调度,使任务保持对CPU的控制权. 调度器开锁函数OSSchedUnlock()的功能是解除对任务调度的禁 ...
最新文章
- 关于图片上传的个人摘要
- 《当程序员的那些狗日日子》(十五)首次接单
- sqlserver 安装_安装sqlserver
- python数组合并、输入三行数据,如何在python中合并两个或三个3D数组?
- 190729知识笔记
- poj2955 Brackets (区间dp)
- Python进阶(六)文件操作
- JS学习总结(13)——DOM
- as5300g2 nas软件功能_浪潮AS5300G2 5500G2存储2U12
- c语言 队列方法的编写
- 《基于机器视觉的高压输电线路覆冰厚度检测》论文笔记
- python修改pdf元信息 metadata
- 程序员30+后的困惑焦虑,出路在哪里?
- Trie——51nod1526 分配笔名
- css3 3d特效汇总
- 弹跳机器人 桌游_「桌游推荐」我的机器人哪有这么厉害
- 写网页设计与制作的博雅互动的作业
- 小尺寸android 手机推荐,目前最值得买的4款小屏手机, 懂行的人才会买, 小屏爱好者福音!...
- CTF Web入门 命令执行 笔记
- Android 30. 广播-Broadcast(一)