1.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) { /* 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();
OS_TickListInsertDly(OSTCBCurPtr,
dly,
opt,
p_err);
if (*p_err != OS_ERR_NONE) {
OS_CRITICAL_EXIT_NO_SCHED();
return;
}
#if (defined(TRACE_CFG_EN) && (TRACE_CFG_EN > 0u))
TRACE_OS_TASK_DLY(dly); /* Record the event. */
#endif
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;
}
2.OSTimeDlyHMSM
是以小时(H)、分(M)、秒(S)和毫秒(m)四个参数来定义延时时间的,函数在内部把这些参数转换为时钟节拍,再通过单次或多次调用OSTimeDly()进行延时和任务调度,所以延时原理和调用延时函数OSTimeDly()是一样的
3.OSTimeDlyResume
可以使用户结束正处于延时期的任务,延时的任务可以不等待延时期满,而是通过取消其它任务的延时来使自己处于就绪态可以通过调用OSTimeDlyResume()和指定要恢复的任务的优先级来完成
void Task1(void *pdata)
{
…… //初始化代码
while (1) //循坏控制LED以固定频率闪烁
{
IO0CLR = LED1; //点亮LED
OSTimeDly(OS_TICKS_PER_SEC); //1s延时
IO0SET = LED1; //熄灭LED
OSTimeDly (OS_TICKS_PER_SEC); //1s延时
}
}
void Task2 (void *pdata)
{
…… //初始化代码
while (1)
{
while ((IO0PIN & KEY1) != 0) //等待按健按下
{
OSTimeDly(1); //延时1个节拍用于任务切换
}
OSTimeDlyResume((OS_TCB *)&task1); //Task1优先级为2,恢复TaskLED
while ((IO0PIN & KEY1) == 0)
{
OSTimeDly(1); //延时1个节拍,用于任务切换
}
}
}
Tips:
在这里可能很多文章并没有讲清楚是怎么处理的,这里详解一下个人的见解:
Task1是在等待Task2的延时才能切换到自己执行。
然而Task2需要按键有变化了就执行Task1,不需要继续延时,所以调用OSTimeDlyResume()可以直接去切换就绪的Task1。