UCOSiii源码分析——os_time.c

Posted Linux bsping

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UCOSiii源码分析——os_time.c相关的知识,希望对你有一定的参考价值。

        这里的内容看懂就好,源码可以不读。

一、任务延时函数 OSTimeDly()

        调用此函数可延迟当前正在运行的任务的执行,直到指定数量的系统计时结束。当然,这直接等同于将当前任务延迟一段时间以过期。如果指定的延迟为0,则不会产生延迟。如果指定的延迟大于0,则会导致上下文切换。可以使用OSTimeDlyResume()唤醒。p_tcb加入TickList中。

void  OSTimeDly (OS_TICK   dly,
                 OS_OPT    opt,
                 OS_ERR   *p_err)

    CPU_SR_ALLOC();



#ifdef OS_SAFETY_CRITICAL
    if (p_err == (OS_ERR *)0) 
        OS_SAFETY_CRITICAL_EXCEPTION();
        return;
    
#endif

#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
    if (OSIntNestingCtr > (OS_NESTING_CTR)0u)              /* Not allowed to call from an ISR                        */
       *p_err = OS_ERR_TIME_DLY_ISR;
        return;
    
#endif

    if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0u)        /* Can't delay when the scheduler is locked               */
       *p_err = OS_ERR_SCHED_LOCKED;
        return;
    

    switch (opt) 
        case OS_OPT_TIME_DLY:
        case OS_OPT_TIME_TIMEOUT:
        case OS_OPT_TIME_PERIODIC:
             if (dly == (OS_TICK)0u)                       /* 0 means no delay!                                      */
                *p_err = OS_ERR_TIME_ZERO_DLY;
                 return;
             
             break;

        case OS_OPT_TIME_MATCH:
             break;

        default:
            *p_err = OS_ERR_OPT_INVALID;
             return;
    

    OS_CRITICAL_ENTER();
    OSTCBCurPtr->TaskState = OS_TASK_STATE_DLY;
    OS_TickListInsert(OSTCBCurPtr,
                      dly,
                      opt,
                      p_err);
    if (*p_err != OS_ERR_NONE) 
         OS_CRITICAL_EXIT_NO_SCHED();
         return;
    
    OS_RdyListRemove(OSTCBCurPtr);                          /* Remove current task from ready list                    */
    OS_CRITICAL_EXIT_NO_SCHED();
    OSSched();                                              /* Find next task to run!                                 */
   *p_err = OS_ERR_NONE;

二、按时分秒延时函数 OSTimeDlyHMSM()

        调用此函数可将当前正在运行的任务的执行延迟到某个时间到期。此调用允许您以小时、分钟、秒和毫秒(而不是滴答声)为单位指定延迟时间。p_tcb加入TickList中。

void  OSTimeDlyHMSM (CPU_INT16U   hours,
                     CPU_INT16U   minutes,
                     CPU_INT16U   seconds,
                     CPU_INT32U   milli,
                     OS_OPT       opt,
                     OS_ERR      *p_err)

#if OS_CFG_ARG_CHK_EN > 0u
    CPU_BOOLEAN  opt_invalid;
    CPU_BOOLEAN  opt_non_strict;
#endif
    OS_OPT       opt_time;
    OS_RATE_HZ   tick_rate;
    OS_TICK      ticks;
    CPU_SR_ALLOC();



#ifdef OS_SAFETY_CRITICAL
    if (p_err == (OS_ERR *)0) 
        OS_SAFETY_CRITICAL_EXCEPTION();
        return;
    
#endif

#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
    if (OSIntNestingCtr > (OS_NESTING_CTR)0u)              /* Not allowed to call from an ISR                        */
       *p_err = OS_ERR_TIME_DLY_ISR;
        return;
    
#endif

    if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0u)        /* Can't delay when the scheduler is locked               */
       *p_err = OS_ERR_SCHED_LOCKED;
        return;
    

    opt_time = opt & OS_OPT_TIME_MASK;                      /* Retrieve time options only.                            */
    switch (opt_time) 
        case OS_OPT_TIME_DLY:
        case OS_OPT_TIME_TIMEOUT:
        case OS_OPT_TIME_PERIODIC:
             if (milli == (CPU_INT32U)0u)                  /* Make sure we didn't specify a 0 delay                  */
                 if (seconds == (CPU_INT16U)0u) 
                     if (minutes == (CPU_INT16U)0u) 
                         if (hours == (CPU_INT16U)0u) 
                            *p_err = OS_ERR_TIME_ZERO_DLY;
                             return;
                         
                     
                 
             
             break;

        case OS_OPT_TIME_MATCH:
             break;

        default:
            *p_err = OS_ERR_OPT_INVALID;
             return;
    

#if OS_CFG_ARG_CHK_EN > 0u                                  /* Validate arguments to be within range                  */
    opt_invalid = DEF_BIT_IS_SET_ANY(opt, ~OS_OPT_TIME_OPTS_MASK);
    if (opt_invalid == DEF_YES) 
       *p_err = OS_ERR_OPT_INVALID;
        return;
    

    opt_non_strict = DEF_BIT_IS_SET(opt, OS_OPT_TIME_HMSM_NON_STRICT);
    if (opt_non_strict != DEF_YES) 
         if (milli   > (CPU_INT32U)999u) 
            *p_err = OS_ERR_TIME_INVALID_MILLISECONDS;
             return;
         
         if (seconds > (CPU_INT16U)59u) 
            *p_err = OS_ERR_TIME_INVALID_SECONDS;
             return;
         
         if (minutes > (CPU_INT16U)59u) 
            *p_err = OS_ERR_TIME_INVALID_MINUTES;
             return;
         
         if (hours   > (CPU_INT16U)99u) 
            *p_err = OS_ERR_TIME_INVALID_HOURS;
             return;
         
     else 
         if (minutes > (CPU_INT16U)9999u) 
            *p_err = OS_ERR_TIME_INVALID_MINUTES;
             return;
         
         if (hours   > (CPU_INT16U)999u) 
            *p_err = OS_ERR_TIME_INVALID_HOURS;
             return;
         
    
#endif

                                                            /* Compute the total number of clock ticks required..     */
                                                            /* .. (rounded to the nearest tick)                       */
    tick_rate = OSCfg_TickRate_Hz;
    ticks     = ((OS_TICK)hours * (OS_TICK)3600u + (OS_TICK)minutes * (OS_TICK)60u + (OS_TICK)seconds) * tick_rate
              + (tick_rate * ((OS_TICK)milli + (OS_TICK)500u / tick_rate)) / (OS_TICK)1000u;

    if (ticks > (OS_TICK)0u) 
        OS_CRITICAL_ENTER();
        OSTCBCurPtr->TaskState = OS_TASK_STATE_DLY;
        OS_TickListInsert(OSTCBCurPtr,
                          ticks,
                          opt_time,
                          p_err);
        if (*p_err != OS_ERR_NONE) 
             OS_CRITICAL_EXIT_NO_SCHED();
             return;
        
        OS_RdyListRemove(OSTCBCurPtr);                      /* Remove current task from ready list                    */
        OS_CRITICAL_EXIT_NO_SCHED();
        OSSched();                                          /* Find next task to run!                                 */
       *p_err = OS_ERR_NONE;
     else 
       *p_err = OS_ERR_TIME_ZERO_DLY;
    

三、OSTimeDlyResume()

        此函数用于恢复通过调用OSTimeDly()或OSTIMEDLYHMM()延迟的任务。请注意,无法调用此函数来恢复正在等待超时事件的任务。从p_tcb从TickList中删除

void  OSTimeDlyResume (OS_TCB  *p_tcb,
                       OS_ERR  *p_err)

    CPU_SR_ALLOC();



#ifdef OS_SAFETY_CRITICAL
    if (p_err == (OS_ERR *)0) 
        OS_SAFETY_CRITICAL_EXCEPTION();
        return;
    
#endif

#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
    if (OSIntNestingCtr > (OS_NESTING_CTR)0u)              /* Not allowed to call from an ISR                        */
       *p_err = OS_ERR_TIME_DLY_RESUME_ISR;
        return;
    
#endif

#if OS_CFG_ARG_CHK_EN > 0u
    if (p_tcb == (OS_TCB *)0)                              /* Not possible for the running task to be delayed!       */
       *p_err = OS_ERR_TASK_NOT_DLY;
        return;
    
#endif

    CPU_CRITICAL_ENTER();
    if (p_tcb == OSTCBCurPtr)                              /* Not possible for the running task to be delayed!       */
       *p_err = OS_ERR_TASK_NOT_DLY;
        CPU_CRITICAL_EXIT();
        return;
    

    switch (p_tcb->TaskState) 
        case OS_TASK_STATE_RDY:                             /* Cannot Abort delay if task is ready                    */
             CPU_CRITICAL_EXIT();
            *p_err = OS_ERR_TASK_NOT_DLY;
             break;

        case OS_TASK_STATE_DLY:
             OS_CRITICAL_ENTER_CPU_EXIT();
             p_tcb->TaskState = OS_TASK_STATE_RDY;
             OS_TickListRemove(p_tcb);                      /* Remove task from tick list                             */
             OS_RdyListInsert(p_tcb);                       /* Add to ready list                                      */
             OS_CRITICAL_EXIT_NO_SCHED();
            *p_err = OS_ERR_NONE;
             break;

        case OS_TASK_STATE_PEND:
             CPU_CRITICAL_EXIT();
            *p_err = OS_ERR_TASK_NOT_DLY;
             break;

        case OS_TASK_STATE_PEND_TIMEOUT:
             CPU_CRITICAL_EXIT();
            *p_err = OS_ERR_TASK_NOT_DLY;
             break;

        case OS_TASK_STATE_SUSPENDED:
             CPU_CRITICAL_EXIT();
            *p_err = OS_ERR_TASK_NOT_DLY;
             break;

        case OS_TASK_STATE_DLY_SUSPENDED:
             OS_CRITICAL_ENTER_CPU_EXIT();
             p_tcb->TaskState = OS_TASK_STATE_SUSPENDED;
             OS_TickListRemove(p_tcb);                      /* Remove task from tick list                             */
             OS_CRITICAL_EXIT_NO_SCHED();
            *p_err            = OS_ERR_TASK_SUSPENDED;
             break;

        case OS_TASK_STATE_PEND_SUSPENDED:
             CPU_CRITICAL_EXIT();
            *p_err = OS_ERR_TASK_NOT_DLY;
             break;

        case OS_TASK_STATE_PEND_TIMEOUT_SUSPENDED:
             CPU_CRITICAL_EXIT();
            *p_err = OS_ERR_TASK_NOT_DLY;
             break;

        default:
             CPU_CRITICAL_EXIT();
            *p_err = OS_ERR_STATE_INVALID;
             break;
    

    OSSched();

四、OSTimeGet()

        获取 OSTickCtr的值,计数器记录了时钟滴答数。

OS_TICK  OSTimeGet (OS_ERR  *p_err)

    OS_TICK  ticks;
    CPU_SR_ALLOC();



#ifdef OS_SAFETY_CRITICAL
    if (p_err == (OS_ERR *)0) 
        OS_SAFETY_CRITICAL_EXCEPTION();
        return ((OS_TICK)0);
    
#endif

    CPU_CRITICAL_ENTER();
    ticks = OSTickCtr;
    CPU_CRITICAL_EXIT();
   *p_err = OS_ERR_NONE;
    return (ticks);

五、OSTimeSet()

        此功能设置计数器,用于跟踪时钟滴答声的数量。

void  OSTimeSet (OS_TICK   ticks,
                 OS_ERR   *p_err)

    CPU_SR_ALLOC();



#ifdef OS_SAFETY_CRITICAL
    if (p_err == (OS_ERR *)0) 
        OS_SAFETY_CRITICAL_EXCEPTION();
        return;
    
#endif

    CPU_CRITICAL_ENTER();
    OSTickCtr = ticks;
    CPU_CRITICAL_EXIT();
   *p_err     = OS_ERR_NONE;

六、OSTimeTick (void)

 处理System Tick,在System Tick中断函数中调用。调用钩子函数,根据 OS_CFG_ISR_POST_DEFERRED_EN给OSTickTask发出Sem,根据OS_CFG_SCHED_ROUND_ROBIN_EN调用时间片轮询,根据 OS_CFG_TMR_EN当OSTmrUpdateCtr==0时给OSTmrTask发出Sem。

void  OSTimeTick (void)

    OS_ERR  err;
#if OS_CFG_ISR_POST_DEFERRED_EN > 0u
    CPU_TS  ts;
#endif


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

#if OS_CFG_ISR_POST_DEFERRED_EN > 0u

    ts = OS_TS_GET();                                       /* Get timestamp                                          */
    OS_IntQPost((OS_OBJ_TYPE) OS_OBJ_TYPE_TICK,             /* Post to ISR queue                                      */
                (void      *)&OSRdyList[OSPrioCur],
                (void      *) 0,
                (OS_MSG_SIZE) 0u,
                (OS_FLAGS   ) 0u,
                (OS_OPT     ) 0u,
                (CPU_TS     ) ts,
                (OS_ERR    *)&err);

#else

   (void)OSTaskSemPost((OS_TCB *)&OSTickTaskTCB,            /* Signal tick task                                       */
                       (OS_OPT  ) OS_OPT_POST_NONE,
                       (OS_ERR *)&err);


#if OS_CFG_SCHED_ROUND_ROBIN_EN > 0u
    OS_SchedRoundRobin(&OSRdyList[OSPrioCur]);
#endif

#if OS_CFG_TMR_EN > 0u
    OSTmrUpdateCtr--;
    if (OSTmrUpdateCtr == (OS_CTR)0u) 
        OSTmrUpdateCtr = OSTmrUpdateCnt;
        OSTaskSemPost((OS_TCB *)&OSTmrTaskTCB,              /* Signal timer task                                      */
                      (OS_OPT  ) OS_OPT_POST_NONE,
                      (OS_ERR *)&err);
    
#endif

#endif

以上是关于UCOSiii源码分析——os_time.c的主要内容,如果未能解决你的问题,请参考以下文章

ucosiii浅析内核对象-软件定时器

UCOSIII空闲任务的作用及源码分析

UCOSiii源码分析——os_task.c任务管理函数分析

ucosiii内核源码解析---os_core.c

测绘程序设计C#将度分秒(° ‘ “)转换度(°)程序实现(附源码)

测绘程序设计C#将度分秒(° ‘ “)转换度(°)程序实现(附源码)