uC/OS-II的任务一般格式为:
void TASKn(void *pdata)
{
pdata = pdata;
while (1)
{
OSTimeDly(OS_TICKS_PER_SEC);
}
}
ucos-II是基于任务优先级抢占式任务调度法的,就是内核在管理调度时,调用任务切换函数(一般为SSched()),在该函数中将此时 已处于就绪状态(条件一)并且为最高优先级(条件二)的任务的保存于其栈中的相应信息压入cpu寄存器中(软中断完成),然后cpu开始运行该任务的代 码。
内核是何时进行任务调度的呢?虽然uC/OS-II是可被剥夺资源的内核(高优先级可强行占有低优先级正在使用的资源),但此事发生的前提是内核实时"检测"到了更高就绪的优先级了,那么内核是怎样来实时检测的呢?
带着这个问题让我们再来看看任务的结构——里边有函数OSTimeDly(OS_TICKS_PER_SEC),一看就知道这是个延时函数, 除了延时外它还会有其他用途呢?经查看其源码了解到里边有一条代码:OSSched(),对,函数OSTimeDly()的作用就是将此时正在运行的函数 挂起(保存任务控制块OS_TCB中的相应信息)(任务控制块OS_TCB是系统分配给每个任务的信息存储单元),然后调用函数OSSched()进行任 务切换,进而执行就绪的最高优先级任务。此刻,我们了解到uCOS-II的任务切换是在执行的任务中调用延时函数OSTimeDly()进行的。
现在,还有一个问题还没解决,就是当延时到了,内核如何将资源返还给被延时挂起的任务?
我们先来了解一下任务可控制块(OS_TCB),任务控制块是一个数据结构,当任务的cpu使用权被剥夺时,uC/OS-II用它来保存该任 务的状态。当任务重新得到cpu使用权时,任务控制块确保任务从当时被中断的那一点丝毫不差地继续执行。OS_TCB全部驻留在RAM中。在OS_TCB 中有一项时间延时项OSTCBDly,调用函数OSTimeDly()过程中有一步骤就是给OSTCBDly赋延时值。uC/OS—II中有函数 OSTimTick(),叫时钟节拍函数,它的一项工作就是给每个用户任务控制块OS_TCB中的时间延迟项OSTCBDly减1(如果该项不为零),当 某项任务的任务控制块中的时间延时项OSTCBDly减为0时,这个任务就进入了就绪态,等待任务切换。而时钟节拍函数OSTimTick()的调用函数 由时钟节拍中断服务函数OSTickISR()调用(或与相应函数配合调用)。
现在,我们来理一下思路:任务调用函数OSTimeDly(),挂起任务和调用切换函数并设置延时时间——>周期性调用时钟节拍中断服务函数OSTickISR()进行任务延时计数(OSTimTick()完成),延时到时调用任务切换函数OSSched(),进行任务切换。
综上,任务切换有两种途径——时钟节拍中断服务函数OSTickISR()进行切换,任务中调用时间延迟函数OSTimeDly()进行切 换。从先后顺序来说,应该是OSTimeDly()先发生(设置OSTCBDly),才会有时钟节拍中断函数OSTickISR()进行切换的动作发生。