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。