uCOS任务中的OSTCBDly

例:应用程序的 2 个任务使用了延时函数 OSTimeDly () 进行延时,在任务 MyTask 中还调用了函数 OSTimeDlyResume () 取消了任务 YourTask 的延时(为了观察任务YourTask 的延时时间的变化,在钩子函数 OSTimeTickHook () 输出了任务 YourTask在延时时间到时的时钟节拍数)。

  OSTimeTickHook钩子函数程序如下

#if OS_CPU_HOOKS_EN > 0 

INT8U d=0;
INT8U l=0;

INT8U n=0;
INT8U m=0;

INT16U tt=1; //时钟计数器
char s[5];

void OSTimeTickHook (void)
{

if(OSTCBPrioTbl[2]->OSTCBDly == 1)
{
sprintf(s,"%5d",tt);
PC_DispStr(d,l+4,s,DISP_BGND_BLACK+DISP_FGND_WHITE );
d+=6;
}
/*
if(OSTCBPrioTbl[2]->OSTCBDly == 0)
{
sprintf(s,"%5d",tt);
PC_DispStr(d,l+6,s,DISP_BGND_BLACK+DISP_FGND_WHITE );
d+=6;
}
*/
tt+=1;

}

#endif

经过我调试发现当(OSTCBPrioTbl[2]->OSTCBDly == 1)  时,正常显示节拍数,当(OSTCBPrioTbl[2]->OSTCBDly == 0)  时,则不显示节拍数。

所以显然,在OSTimeTickHook函数中OSTCBPrioTbl[2]->OSTCBDly不为0。

但是仔细一想在OSTimeDlyResume () 中

INT8U OSTimeDlyResume  (INT8U  prio )
{
if ( prio >= OS_LOWEST_PRIO)
{
return (OS_PRIO_INVALID);
}
OS_ENTER_CRITICAL();
ptcb = (OS_TCB * ) OSTCBPrioTbl[prio ];
if ( ptcb != (OS_TCB * )0)
      {
if ( ptcb -> OSTCBDly != 0)
        {                         
ptcb -> OSTCBDly = 0;
if (( ptcb -> OSTCBStat & OS_STAT_SUSPEND) == OS_STAT_RDY)
            {  
OSRdyGrp |= ptcb -> OSTCBBitY ;
OSRdyTbl[ptcb ->OSTCBY] |= ptcb -> OSTCBBitX ;
OS_EXIT_CRITICAL();
OS_Sched ();
}
            else 
           {
OS_EXIT_CRITICAL();
}
return (OS_NO_ERR);
}
        else 
       {
OS_EXIT_CRITICAL();
return (OS_TIME_NOT_DLY);
}
}
OS_EXIT_CRITICAL();
return (OS_TASK_NOT_EXIST);
}


可以看出在OSTCBPrioTbl[prio]->OSTCBDly 被赋值为0,且进行了一次任务调度,那为什么上面的结果又不对了。那就得看void   OSTimeTick  (void)   

void OSTimeTick ( void )
{
OS_TCB *ptcb;

OSTimeTickHook(); //
ptcb = OSTCBList; //时钟节拍到来时,将控制块双向链表的第一个控制块取出(并不是节拍之前运行的任务)
while (ptcb->OSTCBPrio != OS_IDLE_PRIO)
   {                                                      //空闲任务处于控制块双向链表的最后一个,如果取出的控制块为空闲任务的控制块,那么已经取到最后一个了,就结束

//OS_ENTER_CRITICAL();
if (ptcb->OSTCBDly != 0)
        {                         //
if (--ptcb->OSTCBDly == 0)
           {                   //

if (!(ptcb->OSTCBStat & OS_STAT_SUSPEND))
               {                                         //检查任务是否处于强制挂起状态,如果是,那再挂起一个时钟节拍,否则就将它就绪

OSRdyGrp |= ptcb->OSTCBBitY;

OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
}
               else
{                                       
                    ptcb->OSTCBDly = 1;                       
               }                                              
           }
}
ptcb = ptcb->OSTCBNext; //下一个任务控制块
//OS_EXIT_CRITICAL();
}
//OS_ENTER_CRITICAL();                                   
OSTime++; //节拍计数器+1
//OS_EXIT_CRITICAL();
}

 

可见当OSTCBPrioTbl[prio]->OSTCBDly=1时 在OSTimeTick函数中就已经赋值为0了,且将任务放入就绪表。

分析 当使用OSTimeDlyResume ()将任务中OSTCBPrioTbl[prio]->OSTCBDly强制变为0,在进行任务调度,进入优先级高的任务后,任务中肯要使用延时函数,延时一段节拍,进行任务调度,这时候OSTCBPrioTbl[prio]->OSTCBDly就不为0了,所以再进入OSTimeTick函数时,使用(OSTCBPrioTbl[2]->OSTCBDly == 0) 的判断就不对了。所以就为出现上面调试的结果。 
 

posted @ 2012-02-10 11:30  Mr.阿拉丁  阅读(2650)  评论(0编辑  收藏  举报