μC/OS-II的任务之间的通讯与同步
件,该事件等待任务列表中的最高优先级任务(HighestPriorityTask–HPT)要置于就绪态时,该事件对应的OSSemPost(),OSMboxPost(),OSQPost(),和OSQPostFront()函数调用OSEventTaskRdy()实现该操作。换句话说,该函数从等待任务队列中删除HPT任务(HighestPriorityTask),并把该任务置于就绪态。图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使一个任务进入就绪状态
voidOSEventTaskRdy(OS_EVENT*pevent,void*msg,INT8Umsk)
{
OS_TCB*ptcb;
INT8Ux;
INT8Uy;
INT8Ubitx;
INT8Ubity;
INT8Uprio;
y=OSUnMapTbl[pevent->OSEventGrp];(1)
bity=OSMapTbl[y];(2)
x=OSUnMapTbl[pevent->OSEventTbl[y]];(3)
bitx=OSMapTbl[x];(4)
prio=(INT8U)((y3)+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;
}
}

图F6.4使一个任务进入就绪状态——Figure6.4
6.4 使一个任务进入等待某事件发生状态,OSEventTaskWait()
程序清单L6.7是OSEventTaskWait()函数的源代码。当某个任务要等待一个事件的发生时,相应事件的OSSemPend(),OSMboxPend()或者OSQPend()函数会调用该函数将当前任务从就绪任务表中删除,并放到相应事件的事件控制块的等待任务表中。
程序清单L6.7使一个任务进入等待状态
voidOSEventTaskWait(OS_EVENT*pevent)
{
OSTCBCur->OSTCBEventPtr=pevent;(1)
if((OSRdyTbl[OSTCBCur->OSTCBY]=~OSTCBCur->OSTCBBitX)==0){(2)
OSRdyGrp=~OSTCBCur->OSTCBBitY;
}
pevent->OSEventTbl[OSTCBCur->OSTCBY]|=OSTCBCur->OSTCBBitX;(3)
pevent->OSEventGrp|=OSTCBCur->OSTCBBitY;
}
在该函数中,首先将指向事件控制块的指针放到任务的任务控制块中[L6.7(1)],接着将任务从就绪任务表中删除[L6.7(2)],并把该任务放到事件控制块的等待任务表中[L6.7(3)]。
6.5 由于等待超时而将任务置为就绪态,OSEventTO()
程序清单L6.8是OSEventTO()函数的源代码。当在预先指定的时间内任务等待的事件没有发生时,OSTimeTick()函数会因为等待超时而将任务的状态置为就绪。在这种情况下,事件的OSSemPend(),OSMboxPend()或者OSQPend()函数会调用OSEventTO()来完成这项工作。该函数负责从事件控制块中的等待任务列表里将任务删除[L6.8(1)],并把它置成就绪状态[L6
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)
