程序清单 L6.6是函数OSEventTaskRdy()的源代码。当发生了某个事件,该事件等待任务列表中的最高优先级任务(Highest Priority Task – HPT)要置于就绪态时,该事件对应的OSSemPost(),OSMboxPost(),OSQPost(),和OSQPostFront()函数调用OSEventTaskRdy()实现该操作。换句话说,该函数从等待任务队列中删除HPT任务(Highest Priority Task),并把该任务置于就绪态。图 F6.4给出了OSEventTaskRdy()函数最开始的4个动作。
该函数首先计算HPT任务在.OSEventTbl[]中的字节索引[L6.6/F6.4(1)],其结果是一个从0到OS_LOWEST_PRIO/8+1之间的数,并利用该索引得到该优先级任务在.OSEventGrp中的位屏蔽码[L6.6/F6.4(2)](从表T6.1可以得到该值)。然后,OSEventTaskRdy()函数判断HPT任务在.OSEventTbl[]中相应位的位置[L6.6/F6.4(3)],其结果是一个从0到OS_LOWEST_PRIO/8+1之间的数,以及相应的位屏蔽码[L6.6/F6.4(4)]。根据以上结果,OSEventTaskRdy()函数计算出HPT任务的优先级[L6.6(5)],然后就可以从等待任务列表中删除该任务了[L6.6(6)]。
任务的任务控制块中包含有需要改变的信息。知道了HPT任务的优先级,就可以得到指向该任务的任务控制块的指针[L6.6(7)]。因为最高优先级任务运行条件已经得到满足,必须停止OSTimeTick()函数对.OSTCBDly域的递减操作,所以OSEventTaskRdy()直接将该域清澈0[L6.6(8)]。因为该任务不再等待该事件的发生,所以OSEventTaskRdy()函数将其任务控制块中指向事件控制块的指针指向NULL[L6.6(9)]。如果OSEventTaskRdy()是由OSMboxPost()或者OSQPost()调用的,该函数还要将相应的消息传递给HPT,放在它的任务控制块中[L6.6(10)]。另外,当OSEventTaskRdy()被调用时,位屏蔽码msk作为参数传递给它。该参数是用于对任务控制块中的位清零的位屏蔽码,和所发生事件的类型相对应[L6.6(11)]。最后,根据.OSTCBStat判断该任务是否已处于就绪状态[L6.6(12)]。如果是,则将HPT插入到µC/OS-II的就绪任务列表中[L6.6(13)]。注意,HPT任务得到该事件后不一定进入就绪状态,也许该任务已经由于其它原因挂起了。[见4.07节,挂起一个任务,OSTaskSuspend(),和4.08节,恢复一个任务,OSTaskResume()]。
另外,.OSEventTaskRdy()函数要在中断禁止的情况下调用。
程序清单 L6.6 使一个任务进入就绪状态 |
void OSEventTaskRdy (OS_EVENT *pevent, void *msg, INT8U msk) |
{ |
OS_TCB *ptcb; |
INT8U x; |
INT8U y; |
INT8U bitx; |
INT8U bity; |
INT8U prio; |
|
|
y = OSUnMapTbl[pevent->OSEventGrp]; (1) |
bity = OSMapTbl[y]; (2) |
x = OSUnMapTbl[pevent->OSEventTbl[y]]; (3) |
bitx = OSMapTbl[x]; (4) |
prio = (INT8U)((y << 3) + x); (5) |
if ((pevent->OSEventTbl[y] &= ~bitx) == 0) { (6) |
pevent->OSEventGrp &= ~bity; |
} |
ptcb = OSTCBPrioTbl[prio]; (7) |
ptcb->OSTCBDly = 0; (8) |
ptcb->OSTCBEventPtr = (OS_EVENT *)0; (9) |
#if (OS_Q_EN && (OS_MAX_QS >= 2)) || OS_MBOX_EN |
ptcb->OSTCBMsg = msg; (10) |
#else |
msg = msg; |
#endif |
ptcb->OSTCBStat &= ~msk; (11) |
if (ptcb->OSTCBStat == OS_STAT_RDY) { (12) |
OSRdyGrp |= bity; (13) |
OSRdyTbl[y] |= bitx; |
} |
} |