浅析μC/OS-II v2.85内核OSTimeDly()函数工作原理
浅析μC/OS-II v2.85内核OSTimeDly()函数工作原理<br /><br />**来源:http://gliethttp.cublog.cn[转载请声明出处]<br /><br />//----------------------------------------------------------------------<br />//1.OSTimeDly()函数<br />void OSTimeDly (INT16U ticks)<br />{<br /> INT8U y;<br />#if OS_CRITICAL_METHOD == 3<br /> OS_CPU_SR cpu_sr = 0;<br />#endif<br /> if (OSIntNesting > 0) {<br /> return;//在中断处理函数中调用了OSTimeDly(),那么直接退出<br /> }<br /> if (ticks > 0) {<br /> OS_ENTER_CRITICAL();<br />//调用OSTimeDly()的进程自己把自己从就绪控制矩阵中拿下来,<br />//即:去掉调度器(x,y)矩形阵列(OSRdyTbl,OSRdyGrp)中该task对应的bit位,使得调度器不考虑<br />//该task的调度<br /> y = OSTCBCur->OSTCBY;<br /> OSRdyTbl &= ~OSTCBCur->OSTCBBitX;<br /> if (OSRdyTbl == 0) {<br /> OSRdyGrp &= ~OSTCBCur->OSTCBBitY;<br /> }<br />//延时ticks值,放入OSTCBDly单元,在os时钟滴答处理函数OSTimeTick()中,会处理该单元<br /> OSTCBCur->OSTCBDly = ticks;<br /> OS_EXIT_CRITICAL();<br />//因为本task正在运行,所以本task现在的优先级最高,现在本task已经将自己从就绪控制矩阵中--调度器(x,y)矩形阵列<br />//把自己摘掉,所以调度函数OS_Sched()一定会切换到另一个task中执行新task的代码<br /> OS_Sched();//具体参见《浅析μC/OS-II v2.85内核调度函数》<br /> }//ticks==0,那么什么也不做<br />}<br />//----------------------------------------------------------------------<br />//2.OSTimeTick()--在定时中断里引用的系统滴答函数<br />void OSTimeTick (void)<br />{<br /> OS_TCB *ptcb;<br />#if OS_TICK_STEP_EN > 0<br /> BOOLEAN step;<br />#endif<br />#if OS_CRITICAL_METHOD == 3<br /> OS_CPU_SR cpu_sr = 0;//该3方式将使中断状态寄存器放入堆栈中<br /><br />#endif<br /><br />#if OS_TIME_TICK_HOOK_EN > 0<br /> OSTimeTickHook();<br />#endif<br />#if OS_TIME_GET_SET_EN > 0<br /> OS_ENTER_CRITICAL();<br /> OSTime++;<br /> OS_EXIT_CRITICAL();<br />#endif<br /> if (OSRunning == OS_TRUE) {<br />#if OS_TICK_STEP_EN > 0<br />//控制内核的tick<br /> switch (OSTickStepState) {<br /> case OS_TICK_STEP_DIS:<br /> step = OS_TRUE;<br /> break;<br /> case OS_TICK_STEP_WAIT:<br /> step = OS_FALSE;<br /> break;<br /> case OS_TICK_STEP_ONCE:<br />//本次tick将将影响到task的OSTCBDly域<br />//但以后的tick将一直被屏蔽,不会影响到OSTCBDly域<br />//直到外部将OSTickStepState改变为止<br /> step = OS_TRUE;<br /> OSTickStepState = OS_TICK_STEP_WAIT;<br /> break;<br /> default:<br /> step = OS_TRUE;//本次tick将影响到task的OSTCBDly域<br /> OSTickStepState = OS_TICK_STEP_DIS;<br /> break;<br /> }<br /> if (step == OS_FALSE) {<br /> return;<br /> }<br />#endif<br /> ptcb = OSTCBList;<br />//2007-09-08 gliethttp<br />//OSTCBList是一个按进程创建的先后顺序链接成的task单向链表,最后创建的task在最前面,最先创建的<br />//task在单向链表的尾端,<br />//所以OS_TaskIdle空闲进程在链表的最后,因为它最先创建<br /> while (ptcb->OSTCBPrio != OS_TASK_IDLE_PRIO) {<br /> OS_ENTER_CRITICAL();<br /> if (ptcb->OSTCBDly != 0) {<br /> if (--ptcb->OSTCBDly == 0) {<br />//该task的延时时间已到,解析此次延时是OSTimeDly()引起的,还是OSQPend()之类超时引起的<br /> if ((ptcb->OSTCBStat & OS_STAT_PEND_ANY) != OS_STAT_RDY) {<br /> //2007-09-08 gliethttp<br /> //如:由OSSemPend (pevent,timeout,perr);定义的timeout已经到了,对应task需要运行了<br /> //超时时间到,所以不论当前进程是在做什么,只要时间一到<br /> //该task就可以运行了,所以清除所有事件标志,之后状态标示为OS_STAT_PEND_TO(超时)<br /> ptcb->OSTCBStat &= ~(INT8U)OS_STAT_PEND_ANY;<br /> ptcb->OSTCBStatPend = OS_STAT_PEND_TO;//超时异常<br /> } else {<br /> //2007-09-08 gliethttp<br /> //说明该task调用的是OSTimeDly()<br /> ptcb->OSTCBStatPend = OS_STAT_PEND_OK;//正常结束<br /> }<br /> if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) == OS_STAT_RDY) {<br /> //2007-09-08 gliethttp<br /> //如果该task没有suspend,那么把当前就绪的task加入到运行调度器的就绪控制矩阵中<br /> //等待被调度<br /> OSRdyGrp |= ptcb->OSTCBBitY;<br /> OSRdyTbl |= ptcb->OSTCBBitX;<br /> }<br /> }<br /> }<br /> ptcb = ptcb->OSTCBNext;//继续运算下一个task的OSTCBDly时间域<br /> OS_EXIT_CRITICAL();<br /> }<br /> }<br />}<br />做产品用这个的多不多??
页:
[1]