1、第8章 事件标志组第8章 事件标志组8.1 概述概述 8.2 建立事件标志组建立事件标志组OSFlagCreate()8.3 等待事件标志组中的事件标志位等待事件标志组中的事件标志位OSFlagPend()8.4 置位或者清零事件标志组中的事件标志置位或者清零事件标志组中的事件标志OSFlagPost()8.5 删除事件标志组删除事件标志组OSFlagDel()8.6 无等待地获得事件标志组中的事件标志无等待地获得事件标志组中的事件标志OSFlagAccept()8.7 查询事件标志组的状态查询事件标志组的状态OSFlagQuery()习题习题 第8章 事件标志组8.1 概概 述述8.1.1
2、事件标志组的组成及管理函数事件标志组的组成及管理函数C/OS-的事件标志组由两部分组成:一是用于保存当前事件组中各种状态的各种标志位;二是等待标志位或者清零的任务列表。如表8.1所示,C/OS-提供了六种对事件标志组进行管理的函数,函数所属文件是OS_FLAG.C。第8章 事件标志组表表8.1 事件标志组管理函数一览表事件标志组管理函数一览表第8章 事件标志组8.1.2 事件标志组管理函数的配置常量事件标志组管理函数的配置常量在使用事件标志组管理函数之前,必须设置OS_CFG.H文件中相应的配置常量,以确定是编译还是裁剪该函数,其配置常量如表8.2所示。第8章 事件标志组表表8.2 事件标志组
3、管理函数的配置常量一览表事件标志组管理函数的配置常量一览表第8章 事件标志组8.1.3 实现事件标志组所需要的数据结构实现事件标志组所需要的数据结构实现一个事件标志组除了需要任务控制块OS_TCB以外,还需要两个新的数据结构,即事件标志组数据结构OS_FLAG_GRP和事件标志节点OS_FLAG_NODE。如程序清单8.1所示,OS_FLAG_GRP包括如下三个成员:(1).OSFlagType:用来检验指针的类型是否为指向事件标志组的指针。(2).OSFlagWaitList:事件标志组的等待任务列表。(3).OSFlagFlags:一系列表明当前事件标志状态的位,它可以是8、16或32位的
4、,具体大小由OS_CFG.H文件中的OS_FLAGS常量决定。第8章 事件标志组程序清单程序清单8.1 OS_FLAG_GRP数据结构数据结构typedef struct INT8U OSFlagType;void *OSFlagWaitList;OS_FLAGS OSFlagFlags;OS_FLAG_GRP第8章 事件标志组OS_FLAG_NODE数据结构用来记录任务在等待哪些事件标志位以及等待的方式(“与”或者“或”)。当任务需要等待事件标志位时,就会建立一个OS_FLAG_NODE数据结构;当这些等待事件的标志位发生后,这个数据结构就会被删除。OS_FLAG_NODE数据结构如程序清单
5、8.2所示,具体说明如下:(1).OSFlagNodeNext和.OSFlagNodePrev:用于链接OS_FLAG_NODE的双向链表指针。(2).OSFlagNodeTCB:指向一个等待事件标志组中事件标志的任务控制块。通过这个指针可以确定哪一个任务在等待事件标志组中的事件。第8章 事件标志组(3).OSFlagNodeFlagGrp:反向指向事件标志组的指针。(4).OSFlagNodeFlags:指明任务在等待事件标志组中的哪几位事件标志。例如,如果任务调用OSFlagPend(),并等待事件标志组中的0、2、4、6位事件标志,那么OSFlag NodeFlags的值为0 x55。O
6、SFlagNodeFlags的位数可能是8、16或32位,其大小由OS_FLAGS指定。(5).OSFlagNodeWaitType:指明等待事件标志组中的事件标志的类型是AND(“与”)还是OR(“或”),AND表示所有事件标志都发生,OR表示任何一个事件标志发生。其可能值如下:第8章 事件标志组OS_FLAG_WAIT_CLR_ALL 所有指定的事件标志位清零OS_FLAG_WAIT_CLR_ANDOS_FLAG_WAIT_CLR_ANY 任意指定的事件标志位清零OS_FLAG_WAIT_CLR_OROS_FLAG_WAIT_SET_ALL 所有指定的事件标志位置位OS_FLAG_WAIT
7、_SET_AND第8章 事件标志组OS_FLAG_WAIT_SET_ANY 任意指定的事件标志位置位OS_FLAG_WAIT_SET_OR其中,AND和ALL意义相同,OR和ANY意义也是相同的,意义相同的可以互换使用。第8章 事件标志组程序清单程序清单8.2 OS_FLAG_NODE数据结构数据结构type structvoid *OSFlagNodeNext;void *OSFlagNodePrev;void *OSFlagNodeTCB;void *OSFlagNodeFlagGrp;OS_FLAGS OSFlagNodeFlags;INT8U OSFlagNodeWaitType;OS
8、_FLAG_NODE;事件标志组、事件标志节点和任务控制块之间的关系如图8.1所示。第8章 事件标志组图8.1 事件标志组、事件标志节点和任务控制块之间的关系第8章 事件标志组8.2 建立事件标志组建立事件标志组OSFlagCreate()8.2.1 函数原型函数原型函数原型如下:OS_FALG_GRP*OSFlagCreate(OS_FLAGS flags,INT8U*err)OSFlagCreate()函数用于建立事件标志组。其开关量是OS_FLAG_EN,调用者可以是任务或者启动代码。它有如下两个参数:(1)flags:事件标志组的事件标志初值。第8章 事件标志组(2)err:指向错误代
9、码的指针。其值为如下内容之一:OS_NO_ERR:事件标志组建立成功。OS_ERR_CREATE_ISR:在中断中调用。OS_FLAG_GRP_DEPLETED:系统中空闲事件标志组已用完,OS_CFG.H文件中事件标志组的数量需要更改。第8章 事件标志组8.2.2 返回值返回值如果建立成功,则返回事件标志组的指针;如果系统没有多余的空闲事件标志组,则返回空指针。8.2.3 源代码源代码OSFlagCreate()函数的源代码如程序清单8.3所示。第8章 事件标志组程序清单程序清单8.3 OSFlagCreate()函数的源代码函数的源代码OS_FLAG_GRP *OSFlagCreate(O
10、S_FLAGS flags,INT8U*err)#if OS_CRITICAL_METHOD=3 OS_CPU_SR cpu_sr;#endif OS_FLAG_GRP*pgrp;if(OSIntNesting 0)/*确保中断不能调用*/*err=OS_ERR_CREATE_ISR;/*若在中断中调用,则返回错误代码和空指针*/第8章 事件标志组 return(OS_FLAG_GRP*)0);OS_ENTER_CRITICAL();pgrp=OSFlagFreeList;/*在空闲事件标志组链表中取一个空闲事件标志组*/if(pgrp!=(OS_FLAG_GRP*)0)/*检查所取的空闲事件
11、标志组是否有效*/*若有效,则调整空闲事件标志组链表指针*/OSFlagFreeList =(OS_FLAG_GRP*)OSFlagFreeList-OSFlagWaitList;第8章 事件标志组 pgrp-OSFlagType =OS_EVENT_TYPE_FLAG;/*设置事件标志组类型*/pgrp-OSFlagFlags =flags;/*设置初始值 */pgrp-OSFlagWaitList=(void*)0;/*事件标志组的等待任务列表清零*/OS_EXIT_CRITICAL();*err =OS_NO_ERR;/*返回调用成功代码*/else /*若没有多余的空闲事件标志组,则返
12、回相应的错误代码*/第8章 事件标志组 OS_EXIT_CRITICAL();*err =OS_FLAG_GRP_DEPLETED;return(pgrp);/*返回事件标志组指针 */第8章 事件标志组8.3 等待事件标志组中的事件标志位等待事件标志组中的事件标志位OSFlagPend()8.3.1 函数原型函数原型函数原型如下:OS_FLAGS OSFlagPend(OS_FLAG_GRP*pgrp,OS_FLAGS flags,INT8U wait_type,INT16U timeout,INT8U*err)第8章 事件标志组OSFlagPend()函数用于等待事件标志组中的事件标志,可
13、以是多个事件标志的不同组合,可以等待任一指定事件标志位置位或者清零,也可以等待全部指定事件标志位置位或者清零。如果所等待的事件标志位条件不能满足,则会挂起调用者,直到指定的事件标志组合发生或者等待超时期满。该函数的调用者只能是任务,开关量是OS_FLAG_EN。该函数有如下五个参数:(1)pgrp:指向事件标志组的指针。其值可以在事件标志组建立时得到。(2)flags:指定需要检查的事件标志位。若置1,则检查对应位;若置0,则忽略对应位。第8章 事件标志组(3)wait_type:定义等待事件标志位的方式。其方式为如下四种之一:OS_FLAG_WAIT_CLR_ALL:所有指定的事件标志位都清
14、零。OS_FLAG_WAIT_CLR_ANY:任意指定的事件标志位清零。OS_FLAG_WAIT_SET_ALL:所有指定的事件标志位都置位。OS_FLAG_WAIT_SET_ANY:任意指定的事件标志位置位。(4)timeout:超时定义。第8章 事件标志组(5)err:指向错误代码的指针。其内容为如下几种之一:OS_NO_ERR:调用成功。OS_ERR_PEND_ISR:在中断中调用。OS_FLAG_INVALID_PGRP:pgrp为空指针。OS_ERR_EVENT_TYPE:pgrp不是指向事件标志组的指针。OS_TIMEOUT:等待超时。OS_FLAG_ERR_WAIT_TYPE:w
15、ait_type不是指定的参数之一。第8章 事件标志组如果一个任务在得到所需要的事件标志后想恢复这个事件标志,则可以在wait_type参数上加一个常量OS_FLAG_ CONSUME,即OS_FLAG_WAIT_?_?+OS_FLAG_ CONSUME。8.3.2 返回值返回值如果调用该函数时使用了OS_FLAG_CONSUME选项,则返回恢复后的事件标志组事件标志状态;否则,返回OSFlagPend()调用后的事件标志组事件标志状态;如果超时,则返回0。8.3.3 源代码源代码OSFlagPend()函数的源代码如程序清单8.4所示。第8章 事件标志组程序清单程序清单8.4 OSFlagP
16、end()函数的源代码函数的源代码OS_FLAGS OSFlagPend(OS_FLAG_GRP*pgrp,OS_FLAGS flags,INT8U wait_type,INT16U timeout,INT8U*err)#if OS_CRITICAL_METHOD=3 OS_CPU_SR cpu_sr;#endif OS_FLAG_NODE node;OS_FLAGS flags_cur;OS_FLAGS flags_rdy;BOOLEAN consume;第8章 事件标志组 if(OSIntNesting 0)/*确保中断不能调用*/*err=OS_ERR_PEND_ISR;/*若在中断中调
17、用,则返回错误代码*/return(OS_FLAGS)0);/*返回空指针 */#if OS_ARG_CHK_EN 0 if(pgrp=(OS_FLAG_GRP*)0)/*确保pgrp指针有效 */第8章 事件标志组*err=OS_FLAG_INVALID_PGRP;return(OS_FLAGS)0);#endif if(pgrp-OSFlagType!=OS_EVENT_TYPE_FLAG)/*确保事件类型正确 */*err=OS_ERR_EVENT_TYPE;return(OS_FLAGS)0);第8章 事件标志组 if(wait_type&OS_FLAG_CONSUME)/*检查是否使
18、用了consume选项*/wait_type&=OS_FLAG_CONSUME;consume =TRUE;/*设置consume选用状态标志*/else/*若未使用*/consume =FALSE;/*将consume选用状态标志设置为“FALSE”*/第8章 事件标志组 OS_ENTER_CRITICAL();switch(wait_type)/*以四种方式处理等待事件标志组*/case OS_FLAG_WAIT_SET_ALL:/*所有指定的事件标志位都置位*/flags_rdy=pgrp-OSFlagFlags&flags;/*提取flags指定的事件标志位*/if(flags_rdy
19、=flags)/*检查是否有可用的事件标志组*/if(consume=TRUE)/*若可用,则检查是否设置了consume 选项*/第8章 事件标志组 pgrp-OSFlagFlags&=flags_rdy;/*对指定的事件标志位清零*/flags_cur=pgrp-OSFlagFlags;/*保存需要返回的事件标志位状态*/OS_EXIT_CRITICAL();*err =OS_NO_ERR;return(flags_cur);/*返回调用者*/else /*若没有可用的事件标志组,则需等到事件发生或超时期满*/第8章 事件标志组 OS_FlagBlock(pgrp,&node,flags,
20、wait_type,timeout);/*将调用者加到事件标志组的等待任务列表中去,挂起任务*/OS_EXIT_CRITICAL();break;case OS_FLAG_WAIT_SET_ANY:/*任意指定的事件标志位置位*/flags_rdy=pgrp-OSFlagFlags&flags;/*提取flags指定的事件标志位*/if(flags_rdy!=(OS_FLAGS)0)/*检查是否有可用的事件标志组*/第8章 事件标志组 if(consume=TRUE)/*若可用,则检查是否设置了consume 选项*/pgrp-OSFlagFlags&=flags_rdy;/*对指定的事件标志
21、位清零*/flags_cur=pgrp-OSFlagFlags;/*保存需要返回的事件标志位状态*/OS_EXIT_CRITICAL();*err =OS_NO_ERR;return(flags_cur);/*返回调用者*/第8章 事件标志组 else /*若没有可用的事件标志组,则需等到事件发生或超时期满*/OS_FlagBlock(pgrp,&node,flags,wait_type,timeout);OS_EXIT_CRITICAL();break;#if OS_FLAG_WAIT_CLR_EN 0 case OS_FLAG_WAIT_CLR_ALL:/*所有指定的事件标志位都清零 */
22、第8章 事件标志组 flags_rdy=pgrp-OSFlagFlags&flags;/*提取flags指定的事件标志位*/if(flags_rdy=flags)/*检查是否有可用的事件标志组*/if(consume=TRUE)/*若有,则检查是否设置了consume 选项*/pgrp-OSFlagFlags|=flags_rdy;/*对指定的事件标志位置位*/flags_cur=pgrp-OSFlagFlags;/*保存需要返回的事件标志位状态*/第8章 事件标志组 OS_EXIT_CRITICAL();*err =OS_NO_ERR;return(flags_cur);/*返回调用者*/e
23、lse /*若没有可用的事件标志组,则需等到事件发生或超时期满*/OS_FlagBlock(pgrp,&node,flags,wait_type,timeout);OS_EXIT_CRITICAL();break;第8章 事件标志组 case OS_FLAG_WAIT_CLR_ANY:/*任意指定的事件标志位清零*/flags_rdy=pgrp-OSFlagFlags&flags;/*提取flags指定的事件标志位*/if(flags_rdy!=(OS_FLAGS)0)/*检查是否有可用的事件标志组*/if(consume=TRUE)/*若有,则检查是否设置了consume 选项*/pgrp-
24、OSFlagFlags|=flags_rdy;/*对指定的事件标志位置位*/第8章 事件标志组 flags_cur=pgrp-OSFlagFlags;/*保存需要返回的事件标志位状态*/OS_EXIT_CRITICAL();*err =OS_NO_ERR;return(flags_cur);else /*若没有可用的事件标志组,则需等到事件发生或超时期满*/OS_FlagBlock(pgrp,&node,flags,wait_type,timeout);OS_EXIT_CRITICAL();第8章 事件标志组 break;#endif default:/*如果wait_type参数不是指定的四
25、种之一*/OS_EXIT_CRITICAL();flags_cur=(OS_FLAGS)0;*err =OS_FLAG_ERR_WAIT_TYPE;return(flags_cur);第8章 事件标志组 OS_Sched();/*调用者被挂起,需要运行准备就绪的最高优先级任务*/OS_ENTER_CRITICAL();/*当再次返回时,需要检查本函数是因超时期满还是因事件发生而恢复运行的*/if(OSTCBCur-OSTCBStat&OS_STAT_FLAG)/*是因超时期满而恢复运行的吗*/OS_FlagUnlink(&node);/*若是,则将OS_FLAG_NODE从等待任务列表链表中删
26、除 */OSTCBCur-OSTCBStat=OS_STAT_RDY;/*设置状态标志使任务恢复运行*/第8章 事件标志组 OS_EXIT_CRITICAL();flags_cur =(OS_FLAGS)0;*err =OS_TIMEOUT;else /*若因事件发生而恢复运行的*/if(consume=TRUE)/*检查是否设置了consume 选项*/switch(wait_type)case OS_FLAG_WAIT_SET_ALL:/*所有指定的事件标志位都置位*/第8章 事件标志组 case OS_FLAG_WAIT_SET_ANY:/*任意指定的事件标志位清零*/pgrp-OSFl
27、agFlags&=OSTCBCur-OSTCBFlagsRdy;break;#if OS_FLAG_WAIT_CLR_EN 0 case OS_FLAG_WAIT_CLR_ALL:/*所有指定的事件标志位都清零*/case OS_FLAG_WAIT_CLR_ANY:/*任意指定的事件标志位清零*/第8章 事件标志组 pgrp-OSFlagFlags|=OSTCBCur-OSTCBFlagsRdy;break;#endif default:/*若不是指定的四种方式之一*/OS_EXIT_CRITICAL();*err=OS_FLAG_ERR_WAIT_TYPE;return(OS_FLAGS)0
28、);/*返回空指针和错误代码*/第8章 事件标志组 flags_cur=pgrp-OSFlagFlags;/*保存需要返回的事件标志位状态*/OS_EXIT_CRITICAL();*err =OS_NO_ERR;return(flags_cur);第8章 事件标志组8.4 置位或者清零事件标志组中的事件置位或者清零事件标志组中的事件标志标志OSFlagPost()8.4.1 函数原型函数原型函数原型如下:OS_FLAGS OSFlagPost(OS_FLAG_GRP*pgrp,OS_FLAGS flags,INT8U opt,INT8U*err)OSFlagPost()函数用于设置指定的事件标
29、志组中的事件标志位,它可以对指定的标志位置位或者清零。如果函数设定的事件标志位正好满足某个等待这个事件标志组的任务,那么这个任务将转入就绪。该函数的调用者可以是任务或者中断,开关量是OS_FLAG_EN。该函数有如下四个参数:第8章 事件标志组(1)pgrp:指向事件标志组的指针,其值可以在建立事件标志组时得到。(2)flags:指定需要检验的事件标志位。(3)opt:设定事件标志位方式的选项。它有如下两个值:OS_FLAG_SET:置位指定的事件标志位。OS_FLAG_CLR:清零指定的事件标志位。如果flags=0 x 31,当opt=OS_FLAG_SET时,0、4、5位被置位;当opt
30、=OS_FLAG_CLR时,0、4、5位被清零。第8章 事件标志组(4)err:指向错误代码的指针。其值为如下内容之一:OS_NO_ERR:调用成功。OS_FLAG_INVALID_PGRP:pgrp指针为空。OS_ERR_EVENT_TYPE:pgrp指针指向的不是事件标志组。OS_FLAG_INVALID_OPT:opt参数不是指定的参数之一。第8章 事件标志组8.4.2 返回值返回值OSFlagPost()函数返回事件标志组的新事件标志状态。8.4.3 源代码源代码OSFlagPost()函数的源代码如程序清单8.5所示。第8章 事件标志组程序清单程序清单8.5 OSFlagPost()
31、函数的源代码函数的源代码OS_FLAGS OSFlagPost(OS_FLAG_GRP*pgrp,OS_FLAGS flags,INT8U opt,INT8U*err)#if OS_CRITICAL_METHOD=3 OS_CPU_SR cpu_sr;#endif OS_FLAG_NODE *pnode;BOOLEAN sched;OS_FLAGS flags_cur;OS_FLAGS flags_rdy;第8章 事件标志组BOOLEAN rdy;#if OS_ARG_CHK_EN 0 if(pgrp=(OS_FLAG_GRP*)0)/*确保有可用的事件标志组结构*/*err=OS_FLAG_
32、INVALID_PGRP;return(OS_FLAGS)0);/*若没有,则返回空指针*/#endif if(pgrp-OSFlagType!=OS_EVENT_TYPE_FLAG)/*确保指针指向的数据类型正确*/第8章 事件标志组*err=OS_ERR_EVENT_TYPE;return(OS_FLAGS)0);/*若pgrp指向的不是事件标志组,则返回空*/OS_ENTER_CRITICAL();switch(opt)/*检验选项*/case OS_FLAG_CLR:/*如果对指定的标志位清零*/pgrp-OSFlagFlags&=flags;/*则清零指定的事件标志位*/第8章 事件
33、标志组 break;case OS_FLAG_SET:/*如果置位指定的事件标志位*/pgrp-OSFlagFlags|=flags;/*则置位指定的事件标志位*/break;default:/*如果opt选项不是指定的参数之一*/OS_EXIT_CRITICAL();*err=OS_FLAG_INVALID_OPT;第8章 事件标志组 return(OS_FLAGS)0);/*则返回空指针*/sched=FALSE;/*假定对事件标志的操作不会导致更高优先级任务转入就绪*/pnode=(OS_FLAG_NODE*)pgrp-OSFlagWaitList;/*检验是否有任务在等待事件标志组*/
34、while(pnode!=(OS_FLAG_NODE*)0)/*如果有任务在等待该事件标志组,则遍历事件标志组的等待任务列表*/第8章 事件标志组 switch(pnode-OSFlagNodeWaitType)/*检验等待事件标志的类型*/case OS_FLAG_WAIT_SET_ALL:/*指定的事件标志位都置位*/flags_rdy=pgrp-OSFlagFlags&pnode-OSFlagNodeFlags;if(flags_rdy=pnode-OSFlagNodeFlags)if(OS_FlagTaskRdy(pnode,flags_rdy)=TRUE)/*将等待事件标志组的任务转
35、入就绪*/第8章 事件标志组 sched=TRUE;/*如果确有任务转入就绪,则设置一个标志*/break;case OS_FLAG_WAIT_SET_ANY:/*任意指定的标志位置位*/flags_rdy=pgrp-OSFlagFlags&pnode-OSFlagNodeFlags;if(flags_rdy!=(OS_FLAGS)0)第8章 事件标志组 if(OS_FlagTaskRdy(pnode,flags_rdy)=TRUE)/*将任务就绪*/sched=TRUE;/*如果确有任务转入就绪,则设置一个标志*/break;#if OS_FLAG_WAIT_CLR_EN 0 case OS
36、_FLAG_WAIT_CLR_ALL:/*所有指定的事件标志位都清零*/第8章 事件标志组 flags_rdy=pgrp-OSFlagFlags&pnode-OSFlagNodeFlags;if(flags_rdy=pnode-OSFlagNodeFlags)if(OS_FlagTaskRdy(pnode,flags_rdy)=TRUE)/*将任务就绪*/sched=TRUE;/*如果确有任务转入就绪,则设置一个标志*/break;case OS_FLAG_WAIT_CLR_ANY:/*任意指定的标志位清零*/第8章 事件标志组 flags_rdy=pgrp-OSFlagFlags&pnode
37、-OSFlagNodeFlags;if(flags_rdy!=(OS_FLAGS)0)if(OS_FlagTaskRdy(pnode,flags_rdy)=TRUE)/*将任务就绪*/sched=TRUE;/*如果确有任务转入就绪,则设置一个标志*/break;#endif 第8章 事件标志组 pnode=pnode-OSFlagNodeNext;/*通过双向链表取得下一个OS_FLAG_NODE指针*/OS_EXIT_CRITICAL();if(sched=TRUE)OS_Sched();/*如果有任务就绪,则使最高优先级任务恢复运行*/OS_ENTER_CRITICAL();第8章 事件标
38、志组 flags_cur=pgrp-OSFlagFlags;OS_EXIT_CRITICAL();*err =OS_NO_ERR;return(flags_cur);/*返回当前事件标志组的事件状态*/第8章 事件标志组8.4.4 范例范例Task1等待Task2和Task3两个任务发来置位事件标志组,具体代码如下:OS_FLAG_GRP *EventStatus;/*定义一个指向事件标志组的指针*/#define Event1_OK 0 x01#define Event2_OK 0 x02OS_STK*Task1Stk100;/*定义任务栈 */OS_STK*Task2Stk100;OS_S
39、TK*Task3Stk100;第8章 事件标志组void main(void)INT8U err;OSInit();EventStatus=OSMutexCreat(0 x00,&err);/*建立一个事件标志组*/OSTaskCretae(Task1,(void*)0,&Task1Stk0,15);OSTaskCretae(Task2,(void*)0,&Task2Stk0,20);OSTaskCretae(Task3,(void*)0,&Task3Stk0,25);OSStart();第8章 事件标志组void Task1(void*pdata)INT8U err;OS_FLAGS val
40、ue;pdata=pdata;for(;)value=OSFlagPend(EventStatus,Event1_OK+Event2_OK,OS_FLAG_WAIT_SET_ALL+OS_FLAG_CONSUME,100,&err);/*等待Task2和Task3置位事件标志组*/第8章 事件标志组 switch(err)case OS_NO_ERR:处理成功返回事件;break;case OS_TIMEOUT:处理超时;break;第8章 事件标志组void Task2(void*pdata)INT8U err;pdata=pdata;for(;).第8章 事件标志组void Task3(v
41、oid*pdata)INT8U err;pdata=pdata;for(;).err=OSFlagPost(EventStatus,Event2_OK,OS_FLAG_SET,&err);.第8章 事件标志组8.5 删除事件标志组删除事件标志组OSFlagDel()8.5.1 函数原型函数原型函数原型如下:OS_FLAG_GRP *OSFlagDel(OS_FLAG_GRP*pgrp,INT8U opt,INT8U*err)OSFlagDel()函数用于删除事件标志组。删除事件标志组之前,应该首先删除与该事件标志组有关的任务,以避免相关任务继续使用已经删除了的事件标志组。该函数的调用者只能是任
42、务,开关量是OS_FLAG_EN和OS_FLAG_DEL_ EN。该函数有如下三个参数:第8章 事件标志组(1)pgrp:指向事件标志组的指针。其值可以在建立事件标志组时得到。(2)opt:指明删除条件。它有如下两个选择:OS_DEL_NO_PEND:在没有任何任务等待事件标志组时删除。OS_DEL_ALWAYS:无论有无任务在等待事件标志组都删除。(3)err:指向错误代码的指针。其值为下述内容之一:OS_NO_ERR:删除成功。OS_ERR_DEL_ISR:从中断中调用。第8章 事件标志组 OS_FLAG_INVALID_PGRP:pgrp是空指针。OS_ERR_EVENT_TYPE:pg
43、rp不是指向事件标志组的指针。OS_ERR_INVALID_OPT:opt参数不是指定的值。OS_ERR_TASK_WAITING:删除时有任务在等待事件标志组。第8章 事件标志组8.5.2 返回值返回值如果事件标志组成功删除,则返回空指针;如果删除不成功,则返回指向该事件标志组的指针,此时需要检查错误代码,以确定删除不成功的原因。8.5.3 源代码源代码OSFlagDel()函数的源代码如程序清单8.6所示。第8章 事件标志组程序清单程序清单8.6 OSFlagDel()函数的源代码函数的源代码#if OS_FLAG_DEL_EN 0OS_FLAG_GRP *OSFlagDel(OS_FLA
44、G_GRP*pgrp,INT8U opt,INT8U*err)#if OS_CRITICAL_METHOD=3 OS_CPU_SR cpu_sr;#endif BOOLEAN tasks_waiting;OS_FLAG_NODE *pnode;第8章 事件标志组 if(OSIntNesting 0)/*确保中断不能调用*/*err=OS_ERR_DEL_ISR;/*返回错误代码*/return(pgrp);/*返回指针*/#if OS_ARG_CHK_EN 0 if(pgrp=(OS_FLAG_GRP*)0)/*确保指向事件标志组的指针非空*/第8章 事件标志组*err=OS_FLAG_INV
45、ALID_PGRP;return(pgrp);#endif if(pgrp-OSFlagType!=OS_EVENT_TYPE_FLAG)/*确保指针类型正确*/*err=OS_ERR_EVENT_TYPE;return(pgrp);OS_ENTER_CRITICAL();第8章 事件标志组 if(pgrp-OSFlagWaitList!=(void*)0)/*检查是否有任务在等待事件标志组*/tasks_waiting=TRUE;/*若有,则将状态标志设置为“真”*/else tasks_waiting=FALSE;/*若没有,则将状态标志设置为“假”*/switch(opt)/*检查删除条
46、件*/第8章 事件标志组 case OS_DEL_NO_PEND:/*无任务等待事件标志组时删除*/if(tasks_waiting=FALSE)/*确实无任务等待事件标志组*/pgrp-OSFlagType =OS_EVENT_TYPE_UNUSED;pgrp-OSFlagWaitList=(void*)OSFlagFreeList;/*交还指针*/pgrp-OSFlagFlags =(OS_FLAGS)0;OSFlagFreeList =pgrp;/*将被删除的指针链接到空闲链表中去*/第8章 事件标志组 OS_EXIT_CRITICAL();*err =OS_NO_ERR;return(
47、OS_FLAG_GRP*)0);/*返回空指针给调用者*/else /*确实有任务在等待事件标志组*/OS_EXIT_CRITICAL();*err =OS_ERR_TASK_WAITING;return(pgrp);/*返回事件标志组指针给调用者*/第8章 事件标志组 case OS_DEL_ALWAYS:/*无论有无任务在等待事件标志组都删除*/pnode=(OS_FLAG_NODE*)pgrp-OSFlagWaitList;while(pnode!=(OS_FLAG_NODE*)0)/*遍历所有等待标志组的任务*/OS_FlagTaskRdy(pnode,(OS_FLAGS)0);/*使
48、任务就绪*/pnode=(OS_FLAG_NODE*)pnode-OSFlagNodeNext;第8章 事件标志组 pgrp-OSFlagType =OS_EVENT_TYPE_UNUSED;/*设置成未使用状态*/pgrp-OSFlagWaitList=(void*)OSFlagFreeList;/*将指针还给事件标志组空闲链表*/pgrp-OSFlagFlags =(OS_FLAGS)0;OSFlagFreeList =pgrp;OS_EXIT_CRITICAL();if(tasks_waiting=TRUE)/*检查是否有任务在等待事件标志组 */OS_Sched();第8章 事件标志组
49、 *err=OS_NO_ERR;return(OS_FLAG_GRP*)0);/*成功删除,返回空指针*/default:/*如果opt 参数不是指定的类型*/OS_EXIT_CRITICAL();*err=OS_ERR_INVALID_OPT;/*返回错误代码*/return(pgrp);/*返回指针*/#endif第8章 事件标志组8.5.4 范例范例OSFLagDel()函数的使用范例如下:OS_FLAG_GRP *EventStatus;void Task(void*pdata)INT8U err;OS_FLAG_GRP *prgp;pdata=pdata;for(;)第8章 事件标志
50、组.pgrp=OSFlagDel(EventStatus,OS_DEL_NO_PEND,&err);.第8章 事件标志组8.6 无等待地获得事件标志组中的事件无等待地获得事件标志组中的事件标志标志OSFlagAccept()8.6.1 函数原型函数原型函数原型如下:OS_FLAGS OSFlagAccept(OS_FLAG_GRP*pgrp,OS_FLAGS flags,INT8U wait_type,INT8U*err)OSFlagAccept()函数用于检查事件标志组中的事件标志位是置位还是清零,它可以检查事件标志组中的某一位,也可以检查所有的位。如果没有需要的事件标志产生,该函数不挂起调