时间管理

分类: 注册送365元可提款 时间: 2025-09-30 15:08:33 作者: admin 阅读: 1856 点赞: 779
时间管理

延时函数,其实已经是 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

相关推荐

Absolute Value Calculator
注册送365元可提款

Absolute Value Calculator

📅 08-26 👁️ 6848
整数包括什么
365彩票是不是诈骗呢

整数包括什么

📅 09-06 👁️ 9550
蛇年端午節是「凶日」 三生肖要小心
365彩票是不是诈骗呢

蛇年端午節是「凶日」 三生肖要小心

📅 09-14 👁️ 7964