μC/OS-II的任务之间的通讯与同步
OSEventTbl[5]中的任何一位为1时,.OSEventGrp中的第5位为1。
当.OSEventTbl[6]中的任何一位为1时,.OSEventGrp中的第6位为1。
当.OSEventTbl[7]中的任何一位为1时,.OSEventGrp中的第7位为1。

图F6.2事件的等待任务列表
下面的代码将一个任务放到事件的等待任务列表中。
程序清单L6.2——将一个任务插入到事件的等待任务列表中
pevent->OSEventGrp|=OSMapTbl[prio>>3];
pevent->OSEventTbl[prio>>3]|=OSMapTbl[prio0x07];
其中,prio是任务的优先级,pevent是指向事件控制块的指针。
从程序清单L6.2可以看出,插入一个任务到等待任务列表中所花的时间是相同的,和表中现有多少个任务无关。从图F6.2中可以看出该算法的原理:任务优先级的最低3位决定了该任务在相应的.OSEventTbl[]中的位置,紧接着的3位则决定了该任务优先级在.OSEventTbl[]中的字节索引。该算法中用到的查找表OSMapTbl[](定义在OS_CORE.C中)一般在ROM中实现。
表T6.1OSMapTbl[]

从等待任务列表中删除一个任务的算法则正好相反,如程序清单L6.3所示。
程序清单L6.3从等待任务列表中删除一个任务
if((pevent->OSEventTbl[prio>>3]=~OSMapTbl[prio0x07])==0){
pevent->OSEventGrp=~OSMapTbl[prio>>3];
}
该代码清除了任务在.OSEventTbl[]中的相应位,并且,如果其所在的组中不再有处于等待该事件的任务时(即.OSEventTbl[prio>>3]为0),将.OSEventGrp中的相应位也清除了。和上面的由任务优先级确定该任务在等待表中的位置的算法类似,从等待任务列表中查找处于等待状态的最高优先级任务的算法,也不是从.OSEventTbl[0]开始逐个查询,而是采用了查找另一个表OSUnMapTbl[256](见文件OS_CORE.C)。这里,用于索引的8位分别代表对应的8组中有任务处于等待状态,其中的最低位具有最高的优先级。用这个值索引,首先得到最高优先级任务所在的组的位置(0~7之间的一个数)。然后利用.OSEventTbl[]中对应字节再在OSUnMapTbl[]中查找,就可以得到最高优先级任务在组中的位置(也是0~7之间的一个数)。
这样,最终就可以得到处于等待该事件状态的最高优先级任务了。程序清单L6.4是该算法的具体实现代码。
程序清单L6.4在等待任务列表中查找最高优先级的任务
y=OSUnMapTbl[pevent->OSEventGrp];
x=OSUnMapTbl[pevent->OSEventTbl[y]];
prio=(y3)+x;
举例来说,如果.OSEventGrp的值是01101000(二进制),而对应的OSUnMapTbl[.OSEventGrp]值为3,说明最高优先级任务所在的组是3。类似地,如果.OSEventTbl[3]的值是11100100(二进制),OSUnMapTbl[.OSEventTbl[3]]的值为2,则处于等待状态的任务的最高优先级是3×8+2=26。
在μC/OS-II中,事件控制块的总数由用户所需要的信号量、邮箱和消息队列的总数决定。
该值由OS_CFG.H中的#defineOS_MAX_EVENTS定义。 在调用OSInit()时 (见3.11节, μC/OS-II
的初始化),所有事件控制块被链接成一个单向链表——空闲事件控制块链表(图F6.3)。每
当建立一个信号量、邮箱或者消息队列时,就从该链表中取出一个空闲事件控制块,并对它进
行初始化。因为信号量、邮箱和消息队列一旦建立就不能删除,所以事件控制块也不能放回到
空闲事件控制块链表中。

图F6.3空闲事件控制块链表——Figure6.3
对于事件控制块进行的一些通用操作包括:
y 初始化一个事件控制块
y 使一个任务进入就绪态
y 使一个任务进入等待该事件的状态
y 因为等待超时而使一个任务进入就绪态
为了避免代码重复和减短程代码长度,μC/OS-II将上面的操作用4个系统函数实现,它们是:OSEventWaitListInit(),OSEventTaskRdy(),OSEventWait()和OSEventTO()。
6.2 初始化一个事件控制块,OSEventWaitListInit()
程序清单L6.5是函数OSEventWaitListInit()的源代码。当建立一个信号量、邮箱或者消息队列时,相应的建立函数OSSemInit(),OSMboxCreate(),或者OSQCreate()通过调用
OSEventWaitListInit()对事件控制块中的等待任务列表进行初始化。该函数初始化一个空的等
待任务列表,其中没有任何任务。该函数的调用参数只有一个,就是指向需要初始化的事件控
制块的指针pevent。
程序清单L6.5初始化ECB块的等待任务列表
voidOSEventWaitListInit(OS_EVENT*pevent)
{
INT8Ui;
pevent->OSEventGrp=0x00;
for(i=0;i
pevent->OSEventTbl[i]=0x00;
}
}
6.3 使一个任务进入就绪态,OSEventTaskRdy()
程序清单L6.6是函数OSEventTaskRdy()的源代码。当发生了某个事
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)
