嵌入式实时操作系统uC/os-II(十)-任务时钟

  1. uC/OS-II 用硬件定时器产生一个周期为毫秒(ms)级的周期性中断来实现系统时钟。最小的时钟单位就是两次中断之间相间隔的时间,这个最小时钟单位叫做时钟节拍

硬件定时器以时钟节拍为周期定时地产生中断,该中断的中断服务程序叫做OSTickISR()。其示意代码如下:

         Void OSTickISR(void)

         {

                                     OSIntEnter();

                                     OSTimeTick();

                                     OSIntExit();

           }

在时钟中断服务程序中调用OSTimeTick()叫做时钟节拍服务函数。该函数源代码如下:

void  OSTimeTick (void)

{

    OS_TCB    *ptcb;

#if OS_TICK_STEP_EN > 0

    BOOLEAN    step;

#endif

#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register     */

    OS_CPU_SR  cpu_sr = 0;

#endif

#if OS_TIME_TICK_HOOK_EN > 0

    OSTimeTickHook();        /* Call user definable hook   */

#endif

#if OS_TIME_GET_SET_EN > 0

    OS_ENTER_CRITICAL();      /* Update the 32-bit tick counter   */

    OSTime++;                                   //记录节拍数

    OS_EXIT_CRITICAL();

#endif

    if (OSRunning == TRUE) {

#if OS_TICK_STEP_EN > 0

  switch (OSTickStepState) { /* Determine whether we need to process a tick  */

     case OS_TICK_STEP_DIS:  /* Yes, stepping is disabled    */

                 step = TRUE;

                 break;

      case OS_TICK_STEP_WAIT: /* No, waiting for uC/OS-View to set ...*/

                 step = FALSE; /* .. OSTickStepState to OS_TICK_STEP_ONCE */

                 break;

      case OS_TICK_STEP_ONCE: /* Yes, process tick once and wait for next ... */

                 step = TRUE;   /*... step command from uC/OS-View   */

                 OSTickStepState = OS_TICK_STEP_WAIT;

                 break;

        default:   /* Invalid case, correct situation              */

                 step = TRUE;

                 OSTickStepState = OS_TICK_STEP_DIS;

                 break;

        }

        if (step == FALSE) {  /* Return if waiting for step command    */

            return;

        }

#endif

  ptcb = OSTCBList;   /* Point at first TCB in TCB list               */

while (ptcb->OSTCBPrio != OS_IDLE_PRIO) {  /* Go through all TCBs in TCB list  */

OS_ENTER_CRITICAL();

if (ptcb->OSTCBDly != 0) {  /* No, Delayed or waiting for event with TO     */

  if (--ptcb->OSTCBDly == 0) { /* Decrement nbr of ticks to end of delay     */

     if ((ptcb->OSTCBStat & OS_STAT_PEND_ANY) != OS_STAT_RDY) {

      ptcb->OSTCBStat   &= ~OS_STAT_PEND_ANY; /* Yes, Clear status flag   */

              ptcb->OSTCBPendTO  = TRUE; /* Indicate PEND timeout    */

               } else {

                        ptcb->OSTCBPendTO  = FALSE;

                    }

 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 */

            OS_EXIT_CRITICAL();

        }

    }

}

从加粗的代码片段中可知,uC/OS-II在每次响应定时中断时调用OSTimeTick()做了两件事:一是计数器OSTime1;二是遍历任务控制链表中的所有任务控制块,把各个任务控制块中用来存放任务延时时限OSTCBDly变量减1,并使该项为0,同时又不使被挂任务的任务进入就绪状态函数OSTimeTick的任务就是在每个时钟节拍了解每个任务的延时状态,使其中已经到了延时时限的非挂起任务进入就绪状态。

  1. 任务的延时

           怎么解除高优先级任务独占CPU,可以给其他任务优先级别低的任务获得CPU使用权的机会?

         系统规定:除了空闲任务之外的所有任务必须在任务中合适的位置调用系统提供的函数OSTimeDly(),使当前任务的运行延时一段时间并进行一次任务调度,以让出CPU的使用权。

函数OSTimeDly()的代码如下:

void  OSTimeDly (INT16U ticks)

{

    INT8U      y;

#if OS_CRITICAL_METHOD == 3  /* Allocate storage for CPU status register    */

    OS_CPU_SR  cpu_sr = 0;

#endif

    if (ticks > 0) {     /* 0 means no delay!   */

        OS_ENTER_CRITICAL();

        y  =  OSTCBCur->OSTCBY;        /* Delay current task         */

        OSRdyTbl[y] &= ~OSTCBCur->OSTCBBitX;

        if (OSRdyTbl[y] == 0) {

            OSRdyGrp &= ~OSTCBCur->OSTCBBitY; //取消当前任务的就绪状态

        }

        OSTCBCur->OSTCBDly = ticks;  /*延时节拍数存入任务控制块  */

        OS_EXIT_CRITICAL();

        OS_Sched();                                           /* 调用调度函数 */

    }

}

为了方便使用,系统还提供了OSTimeDlyHMSM()。该函数的原型如下:

         INT8U  OSTimeDlyHMSM(

INT8U hours,                      //小时

INT8U minutes,                 //

INT8U seconds,                 //

INT16U milli                        //毫秒

);

 

  1. 取消任务的延时

延时的任务可通过在其他任务中调用函数OSTimeDlyResume()取消延时而进入就绪状态。如果新任务比正在运行的任务优先级别高,则立即引发一次任务调度。

函数OSTimeDlyResune()的原型如下:

INT8U  OSTimeDlyResume (INT8U prio)

{

 OS_TCB    *ptcb;

#if OS_CRITICAL_METHOD == 3     /* Storage for CPU status register      */

    OS_CPU_SR  cpu_sr = 0;

#endif

    if (prio >= OS_LOWEST_PRIO) {

        return (OS_PRIO_INVALID);

    }

    OS_ENTER_CRITICAL();

    ptcb = OSTCBPrioTbl[prio];   /* Make sure that task exist    */

    if (ptcb == (OS_TCB *)0) {

        OS_EXIT_CRITICAL();

        return (OS_TASK_NOT_EXIST);  /* The task does not exist  */

    }

    if (ptcb == (OS_TCB *)1) {

        OS_EXIT_CRITICAL();

        return (OS_TASK_NOT_EXIST);  /* The task does not exist   */

    }

    if (ptcb->OSTCBDly == 0) {       /* See if task is delayed    */

        OS_EXIT_CRITICAL();

        return (OS_TIME_NOT_DLY);  /* Indicate that task was not delayed   */

    }

    ptcb->OSTCBDly = 0;           /* Clear the time delay          */

    if ((ptcb->OSTCBStat & OS_STAT_PEND_ANY) != OS_STAT_RDY) {

     ptcb->OSTCBStat   &= ~OS_STAT_PEND_ANY;  /* Yes, Clear status flag */

     ptcb->OSTCBPendTO  = TRUE;   /* Indicate PEND timeout  */

    } else {

        ptcb->OSTCBPendTO  = FALSE;

    }

    if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) == OS_STAT_RDY) {  /* Is task suspended?                   */

        OSRdyGrp    |= ptcb->OSTCBBitY;   /* No,  Make ready    */

        OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;

        OS_EXIT_CRITICAL();

        OS_Sched();         /* See if this is new highest priority  */

    } else {

        OS_EXIT_CRITICAL();   /* Task may be suspended   */

    }

    return (OS_NO_ERR);

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值