在μC/OS-II中,有多种办法能够保护使命之间的同享数据和供给使命之间的通讯。在前面的章节中,现已讲到了其间的两种:
一是运用宏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中完成。