时间管理
延时函数,其实已经是 uC/OS 操作系统时间管理的范畴了。这一章介绍的基本都是一些服务函数
OSTimeDly()
OSTimeDly() 函数用于停止当前任务进行的运行,延时一段时间后再运行。OSTimeDly()函数的信息如下表所示。
OSTimeDly() 函数的定义位于“os_time.c”。
void OSTimeDly (OS_TICK dly, //延时的时钟节拍数
OS_OPT opt, //选项
OS_ERR *p_err) //返回错误类型
{
CPU_SR_ALLOC(); //使用到临界段(在关/开中断时)时必需该宏,该宏声明和定义一个局部变
//量,用于保存关中断前的 CPU 状态寄存器 SR(临界段关中断只需保存SR)
//,开中断时将该值还原。
#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) { //如果该延时函数是在中断中被调用
*p_err = OS_ERR_TIME_DLY_ISR; //错误类型为“在中断函数中延时”
return; //返回,不执行延时操作
}
#endif
/* 当调度器被锁时任务不能延时 */
if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0u) { //如果调度器被锁
*p_err = OS_ERR_SCHED_LOCKED; //错误类型为“调度器被锁”
return; //返回,不执行延时操作
}
switch (opt) { //根据延时选项参数 opt 分类操作
case OS_OPT_TIME_DLY: //如果选择相对时间(从现在起延时多长时间)
case OS_OPT_TIME_TIMEOUT: //如果选择超时(实际同上)
case OS_OPT_TIME_PERIODIC: //如果选择周期性延时
if (dly == (OS_TICK)0u) { //如果参数 dly 为0(0意味不延时)
*p_err = OS_ERR_TIME_ZERO_DLY; //错误类型为“0延时”
return; //返回,不执行延时操作
}
break;
case OS_OPT_TIME_MATCH: //如果选择绝对时间(匹配系统开始运行(OSStart())后的时钟节拍数)
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); //从就绪列表移除当前任务
OS_CRITICAL_EXIT_NO_SCHED(); //退出临界段(无调度)
OSSched(); //任务切换
*p_err = OS_ERR_NONE; //错误类型为“无错误”
}
View Code
OSTimeDly() 函数中,如果函数的实参和调用场合均合法,就会调用 OS_TickListInsert()函数将当前任务插入到节拍列表进行管理,这与上一章所讲的更新节拍列表是对应的。OS_TickListInsert() 函数的定义位于“os_tick.c”。要插入节拍列表的任务的等待时间有个门限 OS_TICK_TH_RDY,该宏为 0Xffff0000。如果以时钟节拍最高频率 1000 Hz 来算,该宏所代表时间都有 49 天(至少数),任务等待这么长的时间在实际应用中是不可能存在的,所以 uC/OS 设置了该门限,凡是超过该门限的等待时间均视为 0 延时,防止恶性等待,浪费资源。
void OS_TickListInsert (OS_TCB *p_tcb, //任务控制块
OS_TICK time, //时间
OS_OPT opt, //选项
OS_ERR *p_err) //返回错误类型
{
OS_TICK tick_delta;
OS_TICK tick_next;
OS_TICK_SPOKE *p_spoke;
OS_TCB *p_tcb0;
OS_TCB *p_tcb1;
OS_TICK_SPOKE_IX spoke;
if (opt == OS_OPT_TIME_MATCH) { //如果 time 是个绝对时间
tick_delta = time - OSTickCtr - 1u; //计算离到期还有多长时间
if (tick_delta > OS_TICK_TH_RDY) { //如果延时时间超过了门限
p_tcb->TickCtrMatch = (OS_TICK )0u; //将任务的时钟节拍的匹配变量置0
p_tcb->TickRemain = (OS_TICK )0u; //将任务的延时还需时钟节拍数置0
p_tcb->TickSpokePtr = (OS_TICK_SPOKE *)0; //该任务不插入节拍列表
*p_err = OS_ERR_TIME_ZERO_DLY; //错误类型相当于“0延时”
return; //返回,不将任务插入节拍列表
}
p_tcb->TickCtrMatch = time; //任务等待的匹配点为 OSTickCtr = time
p_tcb->TickRemain = tick_delta + 1u; //计算任务离到期还有多长时间
} else if (time > (OS_TICK)0u) { //如果 time > 0
if (opt == OS_OPT_TIME_PERIODIC) { //如果 time 是周期性时间
tick_next = p_tcb->TickCtrPrev + time; //计算任务接下来要匹配的时钟节拍总计数
tick_delta = tick_next - OSTickCtr - 1u; //计算任务离匹配还有个多长时间
if (tick_delta < time) { //如果 p_tcb->TickCtrPrev < OSTickCtr + 1
p_tcb->TickCtrMatch = tick_next; //将 p_tcb->TickCtrPrev + time 设为时钟节拍匹配点
} else { //如果 p_tcb->TickCtrPrev >= OSTickCtr + 1
p_tcb->TickCtrMatch = OSTickCtr + time; //将 OSTickCtr + time 设为时钟节拍匹配点
}
p_tcb->TickRemain = p_tcb->TickCtrMatch - OSTickCtr; //计算任务离到期还有多长时间
p_tcb->TickCtrPrev = p_tcb->TickCtrMatch; //保存当前匹配值为下一周期延时用
} else { //如果 time 是相对时间
p_tcb->TickCtrMatch = OSTickCtr + time; //任务等待的匹配点为 OSTickCtr + time
p_tcb->TickRemain = time; //计算任务离到期的时间就是 time
}
} else { //如果 time = 0
p_tcb->TickCtrMatch = (OS_TICK )0u; //将任务的时钟节拍的匹配变量置0
p_tcb->TickRemain = (OS_TICK )0u; //将任务的延时还需时钟节拍数置0
p_tcb->TickSpokePtr = (OS_TICK_SPOKE *)0; //该任务不插入节拍列表
*p_err = OS_ERR_TIME_ZERO_DLY; //错误类型为“0延时”
return; //返回,不将任务插入节拍列表
}
spoke = (OS_TICK_SPOKE_IX)(p_tcb->TickCtrMatch % OSCfg_TickWheelSize); //使用哈希算法(取余)来决定任务存于数组
p_spoke = &OSCfg_TickWheel[spoke]; //OSCfg_TickWheel的哪个元素(组织一个节拍列表),
//与更新节拍列表相对应,可方便查找到期任务。
if (p_spoke->NbrEntries == (OS_OBJ_QTY)0u) { //如果当前节拍列表为空
p_tcb->TickNextPtr = (OS_TCB *)0; //任务中指向节拍列表中下一个任务的指针置空
p_tcb->TickPrevPtr = (OS_TCB *)0; //任务中指向节拍列表中前一个任务的指针置空
p_spoke->FirstPtr = p_tcb; //当前任务被列为该节拍列表的第一个任务
p_spoke->NbrEntries = (OS_OBJ_QTY)1u; //节拍列表中的元素数目为1
} else { //如果当前节拍列表非空
p_tcb1 = p_spoke->FirstPtr; //获取列表中的第一个任务
while (p_tcb1 != (OS_TCB *)0) { //如果该任务存在
p_tcb1->TickRemain = p_tcb1->TickCtrMatch //计算该任务的剩余等待时间
- OSTickCtr;
if (p_tcb->TickRemain > p_tcb1->TickRemain) { //如果当前任务的剩余等待时间大于该任务的
if (p_tcb1->TickNextPtr != (OS_TCB *)0) { //如果该任务不是列表的最后一个元素
p_tcb1 = p_tcb1->TickNextPtr; //让当前任务继续与该任务的下一个任务作比较
} else { //如果该任务是列表的最后一个元素
p_tcb->TickNextPtr = (OS_TCB *)0; //当前任务为列表的最后一个元素
p_tcb->TickPrevPtr = p_tcb1; //该任务是当前任务的前一个元素
p_tcb1->TickNextPtr = p_tcb; //当前任务是该任务的后一个元素
p_tcb1 = (OS_TCB *)0; //插入完成,退出 while 循环
}
} else { //如果当前任务的剩余等待时间不大于该任务的
if (p_tcb1->TickPrevPtr == (OS_TCB *)0) { //如果该任务是列表的第一个元素
p_tcb->TickPrevPtr = (OS_TCB *)0; //当前任务就作为列表的第一个元素
p_tcb->TickNextPtr = p_tcb1; //该任务是当前任务的后一个元素
p_tcb1->TickPrevPtr = p_tcb; //当前任务是该任务的前一个元素
p_spoke->FirstPtr = p_tcb; //当前任务是列表的第一个元素
} else { //如果该任务也不是是列表的第一个元素
p_tcb0 = p_tcb1->TickPrevPtr; // p_tcb0 暂存该任务的前一个任务
p_tcb->TickPrevPtr = p_tcb0; //该任务的前一个任务作为当前任务的前一个任务
p_tcb->TickNextPtr = p_tcb1; //该任务作为当前任务的后一个任务
p_tcb0->TickNextPtr = p_tcb; // p_tcb0 暂存的任务的下一个任务改为当前任务
p_tcb1->TickPrevPtr = p_tcb; // 该任务的前一个任务也改为当前任务
}
p_tcb1 = (OS_TCB *)0; //插入完成,退出 while 循环
}
}
p_spoke->NbrEntries++; //节拍列表中的元素数目加1
}
if (p_spoke->NbrEntriesMax < p_spoke->NbrEntries) { //更新节拍列表的元素数目的最大记录
p_spoke->NbrEntriesMax = p_spoke->NbrEntries;
}
p_tcb->TickSpokePtr = p_spoke; //记录当前任务存放于哪个节拍列表
*p_err = OS_ERR_NONE; //错误类型为“无错误”
}
View Code
如果 OSTimeDly() 函数调用 OS_TickListInsert() 函数将当前任务插入节拍列表成功的话,就会调用 OS_RdyListRemove() 函数将当前任务从任务就绪列表中移除,并将系统切换至其他任务。OS_RdyListRemove() 函数属于任务管理范畴,该函数的原理可参考“任务管理”章节。
OSTimeDlyHMSM()
OSTimeDlyHMSM() 函数与 OSTimeDly() 函数的功能类似,也是用于停止当前任务进行的运行,延时一段时间后再运行。但是,用户若要使用 OSTimeDlyHMSM() 函数,得事先将宏 OS_CFG_TIME_DLY_HMSM_EN(位于“os_cfg.h”)设为 1。
/* -------------------------- TIME MANAGEMENT -------------------------- */
#define OS_CFG_TIME_DLY_HMSM_EN 1u //使能/禁用 OSTimeDlyHMSM() 函数
#define OS_CFG_TIME_DLY_RESUME_EN 1u //使能/禁用 OSTimeDlyResume() 函数
View Code
OSTimeDlyHMSM () 函数的信息如下表所示。
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) { //如果该延时函数是在中断中被调用
*p_err = OS_ERR_TIME_DLY_ISR; //错误类型为“在中断函数中延时”
return; //返回,不执行延时操作
}
#endif
/* 当调度器被锁时任务不能延时 */
if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0u) { //如果调度器被锁
*p_err = OS_ERR_SCHED_LOCKED; //错误类型为“调度器被锁”
return; //返回,不执行延时操作
}
opt_time = opt & OS_OPT_TIME_MASK; //检测除选项中与延时时间性质有关的位
switch (opt_time) { //根据延时选项参数 opt 分类操作
case OS_OPT_TIME_DLY: //如果选择相对时间(从现在起延时多长时间)
case OS_OPT_TIME_TIMEOUT: //如果选择超时(实际同上)
case OS_OPT_TIME_PERIODIC: //如果选择周期性延时
if (milli == (CPU_INT32U)0u) { //如果毫秒数为0
if (seconds == (CPU_INT16U)0u) { //如果秒数为0
if (minutes == (CPU_INT16U)0u) { //如果分钟数为0
if (hours == (CPU_INT16U)0u) { //如果小时数为0
*p_err = OS_ERR_TIME_ZERO_DLY; //错误类型为“0延时”
return; //返回,不执行延时操作
}
}
}
}
break;
case OS_OPT_TIME_MATCH: //如果选择绝对时间(把系统开始运行(OSStart()时做为起点)
break;
default: //如果选项超出范围
*p_err = OS_ERR_OPT_INVALID; //错误类型为“选项非法”
return; //返回,不执行延时操作
}
#if OS_CFG_ARG_CHK_EN > 0u //如果使能(默认使能)了参数检测功能
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) { //如果选项选择了 OS_OPT_TIME_HMSM_STRICT
if (milli > (CPU_INT32U)999u) { //如果毫秒数>999
*p_err = OS_ERR_TIME_INVALID_MILLISECONDS; //错误类型为“毫秒数不可用”
return; //返回,不执行延时操作
}
if (seconds > (CPU_INT16U)59u) { //如果秒数>59
*p_err = OS_ERR_TIME_INVALID_SECONDS; //错误类型为“秒数不可用”
return; //返回,不执行延时操作
}
if (minutes > (CPU_INT16U)59u) { //如果分钟数>59
*p_err = OS_ERR_TIME_INVALID_MINUTES; //错误类型为“分钟数不可用”
return; //返回,不执行延时操作
}
if (hours > (CPU_INT16U)99u) { //如果小时数>99
*p_err = OS_ERR_TIME_INVALID_HOURS; //错误类型为“小时数不可用”
return; //返回,不执行延时操作
}
} else { //如果选项选择了 OS_OPT_TIME_HMSM_ NON_STRICT
if (minutes > (CPU_INT16U)9999u) { //如果分钟数>9999
*p_err = OS_ERR_TIME_INVALID_MINUTES; //错误类型为“分钟数不可用”
return; //返回,不执行延时操作
}
if (hours > (CPU_INT16U)999u) { //如果小时数>999
*p_err = OS_ERR_TIME_INVALID_HOURS; //错误类型为“小时数不可用”
return; //返回,不执行延时操作
}
}
#endif
/*将延时时间转换成时钟节拍数*/
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) { //如果延时节拍数>0
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); //从就绪列表移除当前任务
OS_CRITICAL_EXIT_NO_SCHED(); //退出临界段(无调度)
OSSched(); //任务切换
*p_err = OS_ERR_NONE; //错误类型为“无错误”
} else { //如果延时节拍数=0
*p_err = OS_ERR_TIME_ZERO_DLY; //错误类型为“0延时”
}
}
View Code
OSTimeDlyHMSM() 函 数 中 , 如 果 函 数 的 实 参 和 调 用 场 合 均 合 法 , 就 会 调 用OS_TickListInsert() 函数将当前任务插入到节拍列表进行管理。OS_TickListInsert() 函数的原理参考“OSTimeDly()”章节。如果 OSTimeDlyHMSM() 函数调用 OS_TickListInsert() 函数将当前任务插入节拍列表成功的话,就会调用 OS_RdyListRemove() 函数将当前任务从任务就绪列表中移除,并将系统切换至其他任务。
OSTimeDlyResume()
OSTimeDlyResume () 函数用于直接结束其他任务(非当前任务)的延时。用户若要使用OSTimeDlyResume () 函数,得事先将宏 OS_CFG_TIME_DLY_RESUME_EN(位于“os_cfg.h”)设为 1。
/* -------------------------- TIME MANAGEMENT -------------------------- */
#define OS_CFG_TIME_DLY_HMSM_EN 1u //使能/禁用 OSTimeDlyHMSM() 函数
#define OS_CFG_TIME_DLY_RESUME_EN 1u //使能/禁用 OSTimeDlyResume() 函数
View Code
OSTimeDlyResume () 函数的信息如下表所示。
OSTimeDlyResume () 函数的定义位于“os_time.c”。
#if OS_CFG_TIME_DLY_RESUME_EN > 0u //如果使能(默认使能)了 OSTimeDlyResume() 函数
void OSTimeDlyResume (OS_TCB *p_tcb, //任务控制块
OS_ERR *p_err) //错误类型
{
CPU_SR_ALLOC(); //使用到临界段(在关/开中断时)时必需该宏,该宏声明和定义一个局部变
//量,用于保存关中断前的 CPU 状态寄存器 SR(临界段关中断只需保存SR)
//,开中断时将该值还原。
#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) { //如果函数是在中断中被调用
*p_err = OS_ERR_TIME_DLY_RESUME_ISR; //错误类型为“在中断中结束延时”
return; //返回,函数执行不成功
}
#endif
#if OS_CFG_ARG_CHK_EN > 0u //如果使能(默认使能)了参数检测功能
if (p_tcb == (OS_TCB *)0) { //如果任务为空
*p_err = OS_ERR_TASK_NOT_DLY; //错误类型为“任务不在延时”
return; //返回,函数执行不成功
}
#endif
CPU_CRITICAL_ENTER(); //关中断
if (p_tcb == OSTCBCurPtr) { //如果任务为当前任务
*p_err = OS_ERR_TASK_NOT_DLY; //错误类型为“任务不在延时”
CPU_CRITICAL_EXIT(); //开中断
return; //返回,函数执行不成功
}
switch (p_tcb->TaskState) { //根据任务的任务状态分类处理
case OS_TASK_STATE_RDY: //如果任务处于就绪状态
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); //将该任务从节拍列表移除
OS_RdyListInsert(p_tcb); //将该任务插入到就绪列表
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); //将该任务从节拍列表移除
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(); //任务切换
}
#endif
View Code
如果任务的任务状态中包括延时,就调用 OS_TickListRemove() 函数将任务从节拍列表中移除。OS_TickListRemove() 函数的定义位于“os_tick.c”。
void OS_TickListRemove (OS_TCB *p_tcb) //把任务从节拍列表移除
{
OS_TICK_SPOKE *p_spoke;
OS_TCB *p_tcb1;
OS_TCB *p_tcb2;
p_spoke = p_tcb->TickSpokePtr; //获取任务位于哪个节拍列表
if (p_spoke != (OS_TICK_SPOKE *)0) { //如果任务的确在节拍列表中
p_tcb->TickRemain = (OS_TICK)0u; //将任务的延时还需时钟节拍数置0
if (p_spoke->FirstPtr == p_tcb) { //如果任务为节拍列表的第一个任务
p_tcb1 = (OS_TCB *)p_tcb->TickNextPtr; //获取任务的后一个任务为 p_tcb1
p_spoke->FirstPtr = p_tcb1; //把 p_tcb1 作为节拍列表的第一个任务
if (p_tcb1 != (OS_TCB *)0) { //如果 p_tcb1 非空
p_tcb1->TickPrevPtr = (OS_TCB *)0; //p_tcb1 前面已不存在任务
}
} else { //如果任务不为节拍列表的第一个任务
p_tcb1 = p_tcb->TickPrevPtr; //获取任务的前一个任务为 p_tcb1
p_tcb2 = p_tcb->TickNextPtr; //获取任务的后一个任务为 p_tcb2
p_tcb1->TickNextPtr = p_tcb2; //将 p_tcb2 作为 p_tcb1 的后一个任务
if (p_tcb2 != (OS_TCB *)0) { //如果 p_tcb2 非空
p_tcb2->TickPrevPtr = p_tcb1; //把 p_tcb1 作为 p_tcb2 的前一个任务
}
}
p_tcb->TickNextPtr = (OS_TCB *)0; //清空任务的后一个任务
p_tcb->TickPrevPtr = (OS_TCB *)0; //清空任务的前一个任务
p_tcb->TickSpokePtr = (OS_TICK_SPOKE *)0; //任务不再属于任何节拍列表
p_tcb->TickCtrMatch = (OS_TICK )0u; //将任务的时钟节拍的匹配变量置0
p_spoke->NbrEntries--; //节拍列表中的元素数目减1
}
}
View Code
OSTimeGet ()
OSTimeGet () 函数用于获取当前的时钟节拍计数值。OSTimeGet () 函数的信息如下表所示。
OSTimeGet () 函数的定义位于“os_time.c”。
OS_TICK OSTimeGet (OS_ERR *p_err) //获取当前的时钟节拍计数值
{
OS_TICK ticks;
CPU_SR_ALLOC(); //使用到临界段(在关/开中断时)时必需该宏,该宏声明和定义一个局部变
//量,用于保存关中断前的 CPU 状态寄存器 SR(临界段关中断只需保存SR)
//,开中断时将该值还原。
#ifdef OS_SAFETY_CRITICAL //如果使能(默认禁用)了安全检测
if (p_err == (OS_ERR *)0) { //如果错误类型实参为空
OS_SAFETY_CRITICAL_EXCEPTION(); //执行安全检测异常函数
return ((OS_TICK)0); //返回0,函数执行不成功
}
#endif
CPU_CRITICAL_ENTER(); //关中断
ticks = OSTickCtr; //获取当前的时钟节拍计数值
CPU_CRITICAL_EXIT(); //开中断
*p_err = OS_ERR_NONE; //错误类型为“无错误”
return (ticks); //返回当前的时钟节拍计数值
}
View Code
OSTimeSet ()
OSTimeSet () 函数用于设置当前的时钟节拍计数值。OSTimeSet () 函数的信息如下表所示。
OSTimeSet () 函数的定义位于“os_time.c”。
void OSTimeSet (OS_TICK ticks, //设置当前的时钟节拍计数值
OS_ERR *p_err) //返回错误类型
{
CPU_SR_ALLOC(); //使用到临界段(在关/开中断时)时必需该宏,该宏声明和定义一个局部变
//量,用于保存关中断前的 CPU 状态寄存器 SR(临界段关中断只需保存SR)
//,开中断时将该值还原。
#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; //错误类型为“无错误”
}
View Code