浅谈μCOS-III关于系统延时函数

嵌入式操作系统μCOS-III中涉及很多的系统延时函数,本文列举几个常用延时函数展开讨论,如有错误,望路过的各位大神不吝指点
一、系统延时函数–OSTimeDly()
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)
{
*p_err = OS_ERR_TIME_DLY_ISR; //中断中禁止使用OSTimeDly()延时
return;
}
井endif
if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0u)
{ //任务上锁不能使用OSTimeDly()
*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
{
*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); //将当前任务从就绪表中移除
OS_CRITICAL_EXIT_NO_SCHED(); //退出临界区
OSSched(); //启动任务调度
*p_err = OS_ERR_NONE; //返回错误码
}
OSTimeDly()函数是位于μCOS-III os_time.c 中的一个基本函数,进入函数首先判断中断嵌套层数是否为0,即在中断中不能调用该函数;然后判断调度器是否上锁,因为调用该函数后,系统会发生任务调度,即切换到下一优先级的任务,而不是像裸机一样在此空转,直到延时完成。设置好控制块延时节拍之前,调用OS_CRITICAL_ENTER()函数,对临界资源进行保护,每次系统时钟中断会将每个任务的非0 TaskState成员进行减一操作,直至该成员值为0。完成上述步骤后,启动任务调度,正在执行的任务让出CPU现在的使用权。本函数使用会发生系统调度。
二、系统延时函数–OSTimeDlyHMSM ()
井if OS_CFG_TIME_DLY_HMSM_EN > 0u
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
{
/* 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;
}
…………………………..
此处省略各延时值的正误判断
……………………………..
/* 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;
}
}
井endif
与上一函数的流程相似,OSTimeDlyHMSM ()函数也是是位于μCOS-III os_time.c 中的一个基本函数,进入函数首先判断中断嵌套层数是否为0,即在中断中不能调用该函数;然后判断调度器是否上锁,因为调用该函数后,设置好控制块延时节拍后,完成上述步骤后,启动任务调度。与上述函数的最大区别是,该函数传参为小时、分钟、秒、毫秒延时种类更加丰富。
二、用户延时函数–delay_us(u32 nus)
void delay_us(u32 nus)
{
u32 ticks;
u32 told,tnow,tcnt=0;
u32 reload=SysTick->LOAD; //设置LOAD值
ticks=nus*fac_us; //需要的节拍数
tcnt=0;
delay_osschedlock(); //阻止OS调度,防止打断us延时
told=SysTick->VAL; //¸装入计数值
while(1)
{
tnow=SysTick->VAL;
if(tnow!=told)
{
if(tnow<=told)tcnt+=told-tnow; //SYSTICK是一个递减的计数器
else tcnt+=reload-tnow+told;
told=tnow;
if(tcnt>=ticks)break; //时间超出/等于要延时的时间则退出
}
};
delay_osschedunlock(); //恢复OS调度
}
与上述的两个函数最大的区别是,本函数延时过程中不会发生任务调度,而且延时都是尽量是us级延时,即远小于系统时钟节拍的延时。否则此函数会占用太多CPU资源。

你可能感兴趣的:(嵌入式操作系统)