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源码分析——os_task.c任务管理函数分析