微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > μC/OS-II的任务之间的通讯与同步

μC/OS-II的任务之间的通讯与同步

时间:10-08 来源:互联网 点击:

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()的源代码。当发生了某个事

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top