UCOSiii源码分析——os_time.c
2023-09-11 14:16:29 时间
这里的内容看懂就好,源码可以不读。
一、任务延时函数 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
}
相关文章
- python中os库用法详解(总结)
- python文件操作(open()、write()、writelines()、read()、readline()、readlines()、seek()、os)
- Hybrid OS环境搭建初探
- iTerm2 + Oh My Zsh 打造舒适终端体验[mac os系统]
- python做中学(六)os.getcwd() 的用法
- 鸿蒙OS 2.0开发工具macOS版安装教程(HarmonyOS DevEco Studio)
- Mac OS忘记password怎么办?无光盘破解Mac OS的管理员password
- 【历史上的今天】12 月 16 日:晶体管问世;IBM 停售 OS/2;科幻小说巨匠诞生
- Mac OS使用技巧十九:Safari碉堡功能之二查看网页源代码
- HarmonyOS(鸿蒙OS)发布,聊聊操作系统的调度
- elementary os 5配置
- elementary os 0.4.1下编译GCC-7.1源码并安装成功