zoukankan      html  css  js  c++  java
  • 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) 的判断就不对了。所以就为出现上面调试的结果。 
     

  • 相关阅读:
    【云计算奇妙学习之旅】第一期:初识云计算
    手撸平衡二叉树!保证讲懂平衡过程!
    复习一下各种排序算法
    CSAPP实验——DataLab
    信息的表示和处理(整数部分)
    实现一个简单的解释器(6)
    实现一个简单的解释器(5)
    实现一个简单的解释器(4)
    实现一个简单的解释器(3)
    实现一个简单的解释器(2)
  • 原文地址:https://www.cnblogs.com/MrDing/p/2344847.html
Copyright © 2011-2022 走看看