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