新闻中心

EEPW首页 > 嵌入式系统 > 设计应用 > μC/OS-II的任务之间的通讯与同步

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

作者: 时间:2016-10-08 来源:网络 收藏

在μC/OS-II中,有多种方法可以保护任务之间的共享数据和提供任务之间的通讯。在前面的章节中,已经讲到了其中的两种:

本文引用地址:https://www.eepw.com.cn/article/201610/305741.htm

一是利用宏OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()来关闭中断和打开中断。当两个任务或者一个任务和一个中断服务子程序共享某些数据时,可以采用这种方法,详见3.00节临界段、8.03.02节 OS_ENTER_CRITICAL() 和OS_EXIT_CRITICAL()及9.03.02节临界段,OS_CPU.H;

二是利用函数OSSchedLock()和OSSchekUnlock()对μC/OS-II中的任务调度函数上锁和开锁。用这种方法也可以实现数据的共享,详见3.06节 给调度器上锁和开锁。

本章将介绍另外三种用于数据共享和任务通讯的方法:信号量、邮箱和消息队列。

图F6.1介绍了任务和中断服务子程序之间是如何进行通讯的。

一个任务或者中断服务子程序可以通过事件控制块ECB(EventCONtrolBlocks)来向另外的任务发信号[F6.1A(1)]。这里,所有的信号都被看成是事件(Event)。这也说明为什么上面把用于通讯的数据结构叫做事件控制块。一个任务还可以等待另一个任务或中断服务子程序给它发送信号[F6.1A(2)]。这里要注意的是,只有任务可以等待事件发生,中断服务子程序是不能这样做的。对于处于等待状态的任务,还可以给它指定一个最长等待时间,以此来防止因为等待的事件没有发生而无限期地等下去。

多个任务可以同时等待同一个事件的发生[F6.1B]。在这种情况下,当该事件发生后,所有等待该事件的任务中,优先级最高的任务得到了该事件并进入就绪状态,准备执行。上面讲到的事件,可以是信号量、邮箱或者消息队列等。当事件控制块是一个信号量时,任务可以等待它,也可以给它发送消息。

图6.1事件控制块的使用

6.1 事件控制块ECB

μC/OS-II通过uCOS_II.H中定义的OS_EVENT数据结构来维护一个事件控制块的所有信息[程序清单L6.1],也就是本章开篇讲到的事件控制块ECB。该结构中除了包含了事件本身的定义,如用于信号量的计数器,用于指向邮箱的指针,以及指向消息队列的指针数组等,还定义了等待该事件的所有任务的列表。程序清单L6.1是该数据结构的定义。

程序清单L6.1ECB数据结构

typedefSTruct{

void*OSEventPtr;/*指向消息或者消息队列的指针*/

INT8UOSEventTbl[OS_EVENT_TBL_SIZE];/*等待任务列表*/

INT16UOSEventCnt;/*计数器(当事件是信号量时)*/

INT8UOSEventType;/*时间类型*/

INT8UOSEventGrp;/*等待任务所在的组*/

}OS_EVENT;

.OSEventPtr指针,只有在所定义的事件是邮箱或者消息队列时才使用。 当所定义的事件是邮箱时,它指向一个消息,而当所定义的事件是消息队列时,它指向一个数据结构,详见6.06节消息邮箱和6.07节消息队列。

.OSEventTbl[] 和 .OSEventGrp 很像前面讲到的OSRdyTbl[]和OSRdyGrp,只不过前两者包含的是等待某事件的任务,而后两者包含的是系统中处于就绪状态的任务。(见3.04节就绪表)

.OSEventCnt 当事件是一个信号量时,.OSEventCnt是用于信号量的计数器,(见6.05节信号量)。

.OSEventType 定义了事件的具体类型。它可以是信号量(OS_EVENT_SEM)、邮箱

(OS_EVENT_TYPE_MBOX)或消息队列(OS_EVENT_TYPE_Q)中的一种。用户要根据该域的具体值

来调用相应的系统函数,以保证对其进行的操作的正确性。

每个等待事件发生的任务都被加入到该事件事件控制块中的等待任务列表中,该列表包括.OSEventGrp和.OSEventTbl[]两个域。变量前面的[.]说明该变量是数据结构的一个域。在这

里,所有的任务的优先级被分成8组(每组8个优先级),分别对应.OSEventGrp中的8位。当

某组中有任务处于等待该事件的状态时,.OSEventGrp中对应的位就被置位。相应地,该任务

在.OSEventTbl[]中的对应位也被置位。.OSEventTbl[]数组的大小由系统中任务的最低优先级

决定,这个值由uCOS_II.H中的OS_LOWEST_PRIO常数定义。这样,在任务优先级比较少的情况

下,减少μC/OS-II对系统RAM的占用量。

当一个事件发生后,该事件的等待事件列表中优先级最高的任务,也即在.OSEventTbl[]中,所有被置1的位中,优先级代码最小的任务得到该事件。图F6.2给出

了.OSEventGrp和.OSEventTbl[]之间的对应关系。该关系可以描述为:

当.OSEventTbl[0]中的任何一位为1时,.OSEventGrp中的第0位为1。

当.OSEventTbl[1]中的任何一位为1时,.OSEventGrp中的第1位为1。

当.OSEventTbl[2]中的任何一位为1时,.OSEventGrp中的第2位为1。

当.OSEventTbl[3]中的任何一位为1时,.OSEventGrp中的第3位为1。

当.OSEventTbl[4]中的任何一位为1时,.OSEventGrp中的第4位为1。

当.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中实现。


上一页 1 2 3 4 5 6 7 8 9 10 11 下一页

关键词:

评论


相关推荐

技术专区

关闭