任务之间的通讯与同步
在µC/OS-II中,有多种方法可以保护任务之间的共享数据和提供任务之间的通讯。在前面的章节中,已经讲到了其中的两种:
一是利用宏OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()来关闭中断和打开中断。当两个任务或者一个任务和一个中断服务子程序共享某些数据时。
二是利用函数OSSchedLock()和OSSchekUnlock()对µC/OS-II中的任务调度函数上锁和开锁。用这种方法也可以实现数据的共享,给调度器上锁和开锁。
将介绍另外三种用于数据共享和任务通讯的方法:信号量、邮箱和消息队列。
图F6.1介绍了任务和中断服务子程序之间是如何进行通讯的。
一个任务或者中断服务子程序可以通过事件控制块ECB(Event Control Blocks)来向另外的任务发信号(1)]。这里,所有的信号都被看成是事件(Event)。这也说明为什么上面把用于通讯的数据结构叫做事件控制块。一个任务还可以等待另一个任务或中断服务子程序给它发送信号[(2)]。这里要注意的是,只有任务可以等待事件发生,中断服务子程序是不能这样做的。对于处于等待状态的任务,还可以给它指定一个最长等待时间,以此来防止因为等待的事件没有发生而无限期地等下去。
多个任务可以同时等待同一个事件的发生[B]。在这种情况下,当该事件发生后,所有等待该事件的任务中,优先级最高的任务得到了该事件并进入就绪状态,准备执行。上面讲到的事件,可以是信号量、邮箱或者消息队列等。当事件控制块是一个信号量时,任务可以等待它,也可以给它发送消息。
事件控制块ECB
µC/OS-II通过uCOS_II.H 中定义的OS_EVENT数据结构来维护一个事件控制块的所有信息,该数据结构的定义。
ECB数据结构 |
typedef struct { |
void *OSEventPtr; /* 指向消息或者消息队列的指针 */ |
INT8U OSEventTbl[OS_EVENT_TBL_SIZE]; /* 等待任务列表 */ |
INT16U OSEventCnt; /* 计数器(当事件是信号量时) */ |
INT8U OSEventType; /* 时间类型 */ |
INT8U OSEventGrp; /* 等待任务所在的组 */ |
} OS_EVENT; |
.OSEventPtr指针,只有在所定义的事件是邮箱或者消息队列时才使用。当所定义的事件是邮箱时,它指向一个消息,而当所定义的事件是消息队列时,它指向一个数据结构。
.OSEventTbl[] 和 .OSEventGrp 很像前面讲到的OSRdyTbl[]和OSRdyGrp,只不过前两者包含的是等待某事件的任务,而后两者包含的是系统中处于就绪状态的任务。
.OSEventCnt当事件是一个信号量时,.OSEventCnt是用于信号量的计数器。
.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的占用量。
下面的代码将一个任务放到事件的等待任务列表中。
将一个任务插入到事件的等待任务列表中 |
pevent->OSEventGrp |= OSMapTbl[prio >> 3]; |
pevent->OSEventTbl[prio >> 3] |= OSMapTbl[prio & 0x07]; |
其中,prio是任务的优先级,pevent是指向事件控制块的指针。
在µC/OS-II中,事件控制块的总数由用户所需要的信号量、邮箱和消息队列的总数决定。该值由OS_CFG.H 中的#define OS_MAX_EVENTS定义。在调用OSInit()时,所有事件控制块被链接成一个单向链表——空闲事件控制块链表。每当建立一个信号量、邮箱或者消息队列时,就从该链表中取出一个空闲事件控制块,并对它进行初始化。因为信号量、邮箱和消息队列一旦建立就不能删除,所以事件控制块也不能放回到空闲事件控制块链表中。
UCOS_II基础入门:
扫一扫关注微信公众号,获取更多实时的嵌入式资讯,嵌入式学习指导方法,汽车电子最新资讯等。