OS_FLAG.C(1)

175 阅读5分钟

本篇介绍OS_FLAG.C中的检测事件标志组的标志状态函数

OS_FLAGS  OSFlagAccept (OS_FLAG_GRP  *pgrp,OS_FLAGS flags,INT8U wait_type,INT8U *perr)检测事件标志组的标志状态函数:

  • 介绍一下wait_type:

在最后的代码中也有相关介绍,为了更好理解,下面具体解释一下:

 wait_type     specifies whether you want ALL bits to be set/cleared or ANY of the bitsto be set/cleared.
*                            You can specify the following argument:
*                            OS_FLAG_WAIT_CLR_ALL   You will check ALL bits in 'flags' to be clear (0)
*                            OS_FLAG_WAIT_CLR_ANY   You will check ANY bit  in 'flags' to be clear (0)
*                            OS_FLAG_WAIT_SET_ALL   You will check ALL bits in 'flags' to be set   (1)
*                            OS_FLAG_WAIT_SET_ANY   You will check ANY bit  in 'flags' to be set   (1)
*--wait_type:定义等待事件标志位的方式.有以下四种参数选择:
OS_FLAG_WAIT_CLR_ALL:所有指定事件标志位清 (0);
OS_FLAG_WAIT_CLR_ANY:任意指定事件标志位清 (0);
OS_FLAG_WAIT_SET_ALL:所有指定事件标志位置 (1);
OS_FLAG_WAIT_SET_ANY:任意指定事件标志位置 (1)。\

*NOTE: Add OS_FLAG_CONSUME if you want the event flag to be 'consumed' by the call.  Example, to wait for any flag in a group AND then clear the flags that are present, set 'wait_type' to:OS_FLAG_WAIT_SET_ANY + OS_FLAG_CONSUME

*注释:如果需要在得到期望的事件标志后,清除该事件标志,则可以在调用函数时,
将该参数加上一个常量OS_FLAG_CONSUME。例如,如果等待事件标志组中任意指定事件标志位置位,
并且在任意事件标志位置位后清除该位,则把参数wait_type设置为:OS_FLAG_WAIT_SET_ANY + OS_FLAG_CONSUME。\

 所谓的消耗与否,就是事件组满足条件后(获得事件标志组后),事件标志组控制块的对应事件标志是否清除,如果清除,就称为消耗掉,如果不清除,就成为不消耗。

代码中具体体现为:

result = (INT8U)(wait_type & OS_FLAG_CONSUME); /*将wiat_type与OS_FLAG_COUNSUME进行与,结果存放在result中*/
    if (result != (INT8U)0)						/*判断我们是否需要清除标志。*/
	{                 
        wait_type &= ~OS_FLAG_CONSUME;			/*不为0,消耗型,需要清除,wait_type保存其取反之后的值*/
        consume    = OS_TRUE;					/*"清除"事件标志位置1,需要对这个标志清0*/
    } 
	else						/*result为0,非消耗型。不需要清除*/
	{
        consume    = OS_FALSE;					/*"清除"事件标志位为0*/
    }

将wiat_type与OS_FLAG_COUNSUME进行逻辑与运算,结果存放在result中。若是rusult为0,则说明wait_type是没有加上OS_FLAG_CONSUME的,也就是非消耗类型的,否则就是消耗类型的。

  • 该函数中第二个需要解释的点:
case OS_FLAG_WAIT_SET_ALL:             /*等待选择的所有位都置1,即所有指定事件标志位清 (0)*/
             flags_rdy = (OS_FLAGS)(pgrp->OSFlagFlags & flags);     /*提取我们需要的位*/
             if (flags_rdy == flags)		 /*必须匹配到我们需要的所有的位*/
			 {                   
                 if (consume == OS_TRUE)	/*如果是消耗型的*/
				 {                
                     pgrp->OSFlagFlags &= (OS_FLAGS)~flags_rdy;    /*将请求事件组中对应请求标志位的位清零,消耗了事件*/
                 }
             }

以这个小片段为例,里面有一个与运算:

flags_rdy = (OS_FLAGS)(pgrp->OSFlagFlags & flags);     /*提取我们需要的位*/

解释一下我们是如何提取我们需要的位呢?这行语句为什么进行与运算?

01011100
11011000

OSFlagFlags和flags都是8位。假定各自8位分别如上图设置。当我们提取位的时候,就一一对应,进行逻辑与操作,并赋给flags_rdy:

01011000

然后再将flags_rdy与flags的每位进行比较(针对OS_FLAG_WAIT_SET_ALL情况):

if (flags_rdy == flags)		 /*必须匹配到我们需要的所有的位*/

上述例子可以看到二者是不一样的。所以这个等式不成立,就没有匹配到我们需要的所有的位,就执行相应的操作。

如果是OS_FLAG_WAIT_SET_ANY等待类型,进行完与操作之后,

 if (flags_rdy != (OS_FLAGS)0) /*看是否有任何设置为1的标志*/

是将flags_rdy与0进行比较。然后执行相关操作。

  • 第三个需要提醒的点:
if (consume == OS_TRUE)	/*如果是消耗型的*/
				 {                
                     pgrp->OSFlagFlags &= (OS_FLAGS)~flags_rdy;    /*将请求事件组中对应请求标志位的位清零,消耗了事件*/
                 }

如果是消耗型的,在清除的时候,我们只清除了之前用到的位,并不是所有位都清除了。这点需要注意一下。

\

下面是该函数的源代码:

/*$PAGE*/
/*
*********************************************************************************************************
*                              CHECK THE STATUS OF FLAGS IN AN EVENT FLAG GROUP
*									检测事件标志组的标志状态
* Description: This function is called to check the status of a combination of bits to be set or cleared
*              in an event flag group.  Your application can check for ANY bit to be set/cleared or ALL
*              bits to be set/cleared.
			   This call does not block if the desired flags are not present.
*描述:这个功能用来检查位的组合状态,来确定事件标志组中的事件标志位是置位还是清0。
		你的应用程序可以检查任意一位是置位还是清0,也可以检查所有位是置位还是清0。
*		这个调用不会被阻塞如果需要的事件标志没有产生。这点与于OSFlagPend()不同。
* Arguments  : pgrp          is a pointer to the desired event flag group.
*参数:						--pgrp:指向事件标志组的指针
*              flags         Is a bit pattern indicating which bit(s) (i.e. flags) you wish to check.
*                            The bits you want are specified by setting the corresponding bits in
*                            'flags'.  e.g. if your application wants to wait for bits 0 and 1 then
*                            'flags' would contain 0x03.
*							--flags:指定需要检查的事件标志位。为1则检查对应位;为0则忽若对应位。
									flags是事件组合的标志,是位掩码,表示事件要等待哪些位。
									如果应用程序等待任务组中事件标志中的0和2,掩码为0x05。
*              wait_type     specifies whether you want ALL bits to be set/cleared or ANY of the bits
*                            to be set/cleared.
*                            You can specify the following argument:
*                            OS_FLAG_WAIT_CLR_ALL   You will check ALL bits in 'flags' to be clear (0)
*                            OS_FLAG_WAIT_CLR_ANY   You will check ANY bit  in 'flags' to be clear (0)
*                            OS_FLAG_WAIT_SET_ALL   You will check ALL bits in 'flags' to be set   (1)
*                            OS_FLAG_WAIT_SET_ANY   You will check ANY bit  in 'flags' to be set   (1)
*							--wait_type:定义等待事件标志位的方式.有以下四种参数选择:
										OS_FLAG_WAIT_CLR_ALL:所有指定事件标志位清 (0);
										OS_FLAG_WAIT_CLR_ANY:任意指定事件标志位清 (0);
										OS_FLAG_WAIT_SET_ALL:所有指定事件标志位置 (1);
										OS_FLAG_WAIT_SET_ANY:任意指定事件标志位置 (1)。
*                            NOTE: Add OS_FLAG_CONSUME if you want the event flag to be 'consumed' by
*                                  the call.  Example, to wait for any flag in a group AND then clear
*                                  the flags that are present, set 'wait_type' to:
*                                  OS_FLAG_WAIT_SET_ANY + OS_FLAG_CONSUME
*							注释:如果需要在得到期望的事件标志后,清除该事件标志,则可以在调用函数时,
								 将该参数加上一个常量OS_FLAG_CONSUME。例如,如果等待事件标志组中任意指定事件标志位置位,
								 并且在任意事件标志位置位后清除该位,则把参数wait_type设置为:OS_FLAG_WAIT_SET_ANY + OS_FLAG_CONSUME
								 所谓的消耗与否,就是事件组满足条件后,获得事件标志组后。事件标志组控制块的对应事件标志清除,即消耗掉。
*              perr          is a pointer to an error code and can be:
*                            OS_ERR_NONE               No error
*                            OS_ERR_EVENT_TYPE         You are not pointing to an event flag group
*                            OS_ERR_FLAG_WAIT_TYPE     You didn't specify a proper 'wait_type' argument.
*                            OS_ERR_FLAG_INVALID_PGRP  You passed a NULL pointer instead of the event flag
*                                                      group handle.
*                            OS_ERR_FLAG_NOT_RDY       The desired flags you are waiting for are not
*                                                      available.
*							--perr:是一个指向错误码的指针,可以是一下几种:
								  OS_ERR_NONE:无错误
								  OS_ERR_EVENT_TYPE:指针未指向事件标志组错
								  OS_ERR_FLAG_WAIT_TYPE:参数wait_type不是指定的四个方式之一。
								  OS_ERR_FLAG_INVALID_PGRP:pgrp为空指针
								  OS_ERR_FLAG_NOT_RDY:指定的事件标志没有发生。
* Returns    : The flags in the event flag group that made the task ready or, 0 if a timeout or an error
*              occurred.
*返回值:返回事件标志组的事件标志。如果是超时或者有错误发生,返回0
* Called from: Task or ISR
*调用:从任务或者中断调用
* Note(s)    : 1) IMPORTANT, the behavior of this function has changed from PREVIOUS versions.  The
*                 function NOW returns the flags that were ready INSTEAD of the current state of the
*                 event flags.
	注释:1)重点:该功能和之前版本的不同,现在版本的该功能返回的是就绪的标志,而不是当前事件的状态
*********************************************************************************************************
*/

#if OS_FLAG_ACCEPT_EN > 0u
OS_FLAGS  OSFlagAccept (OS_FLAG_GRP  *pgrp,
                        OS_FLAGS      flags,
                        INT8U         wait_type,
                        INT8U        *perr)
{
    OS_FLAGS      flags_rdy;					/*定义一个"准备完毕"含量值*/
    INT8U         result;						/*结果*/
    BOOLEAN       consume;						/*定义一个"清除"事件标志位(保存值)*/
	#if OS_CRITICAL_METHOD == 3u                /*中断被设置为类型3*/
		OS_CPU_SR     cpu_sr = 0u;
	#endif

	#ifdef OS_SAFETY_CRITICAL					/*如果定义了安全性中断*/
		if (perr == (INT8U *)0)					/*如果错误码指针为空,调用安全中断异常函数*/
		{
			OS_SAFETY_CRITICAL_EXCEPTION();
		}
	#endif

	#if OS_ARG_CHK_EN > 0u						/*进行参数检查*//*有效化pgrp指针*/
		if (pgrp == (OS_FLAG_GRP *)0)			/*如果pgrp指针为空*/
		{                       
			*perr = OS_ERR_FLAG_INVALID_PGRP;	/*将错误码指针设置为OS_ERR_FLAG_INVALID_PGRP*/
			return ((OS_FLAGS)0);				/*返回0*/
		}
	#endif

    if (pgrp->OSFlagType != OS_EVENT_TYPE_FLAG)  /*有效化事件控制块类型 如果不是事件类型标志*/
	{         
        *perr = OS_ERR_EVENT_TYPE;				/*将错误码指针设置为OS_ERR_EVENT_TYPE*/
        return ((OS_FLAGS)0);					/*返回0*/
    }

    result = (INT8U)(wait_type & OS_FLAG_CONSUME); /*将wiat_type与OS_FLAG_COUNSUME进行与,结果存放在result中*/
    if (result != (INT8U)0)						/*判断我们是否需要清除标志。*/
	{                 
        wait_type &= ~OS_FLAG_CONSUME;			/*不为0,需要清除,wait_type保存其取反之后的值*/
        consume    = OS_TRUE;					/*"清除"事件标志位置1,需要对这个标志清0*/
    } 
	else										/*result为0,不需要清除*/
	{
        consume    = OS_FALSE;					/*"清除"事件标志位为0*/
    }
	/*$PAGE*/
    *perr = OS_ERR_NONE;                       /*先将错误码指针设置为无错误形式*/
    OS_ENTER_CRITICAL();					   /*关中断(进入中断)*/
    switch (wait_type)						   /*判断等待类型,根据类型不同,处理相应的代码*/
	{
        case OS_FLAG_WAIT_SET_ALL:             /*等待选择的所有位都置1,即所有指定事件标志位清 (1)*/
             flags_rdy = (OS_FLAGS)(pgrp->OSFlagFlags & flags);     /*提取我们需要的位*/
             if (flags_rdy == flags)		 /*必须匹配到我们需要的所有的位*/
			 {                   
                 if (consume == OS_TRUE)	/*如果是消耗型的*/
				 {                
                     pgrp->OSFlagFlags &= (OS_FLAGS)~flags_rdy;    /*将请求事件组中对应请求标志位的位清零,消耗了事件*/
                 }
             }
			 else				/*没有匹配到我们需要的所有的位,阻塞,等待事件标志组完成或者是超时*/
			 {
                 *perr = OS_ERR_FLAG_NOT_RDY;/*将错误码设置为标志位位准备好类型*/
             }
             OS_EXIT_CRITICAL();	/*开中断*/
             break;

        case OS_FLAG_WAIT_SET_ANY:	/*如果等待类型为任意指定事件标志位清(1)*/
             flags_rdy = (OS_FLAGS)(pgrp->OSFlagFlags & flags); 
             if (flags_rdy != (OS_FLAGS)0) /*看是否有任何设置为1的标志*/
			 {           
                 if (consume == OS_TRUE) /*如果是消耗类型*/
				 {             
                     pgrp->OSFlagFlags &= (OS_FLAGS)~flags_rdy;     /*只清除我们需要的位*/
                 }
             }
			 else
			 {
                 *perr = OS_ERR_FLAG_NOT_RDY;	/*将错误类型设置为OS_ERR_FLAG_NOT_RDY*/
             }
             OS_EXIT_CRITICAL();				/*开中断*/
             break;

#if OS_FLAG_WAIT_CLR_EN > 0u		/*允许生成 Wait on Clear 事件标志代码*/
        case OS_FLAG_WAIT_CLR_ALL:   /* 等待类型为所有指定事件标志位清 (0);  */
             flags_rdy = (OS_FLAGS)~pgrp->OSFlagFlags & flags;    /*只提取我们需要的位 */
             if (flags_rdy == flags) {                     
                 if (consume == OS_TRUE) 
				 {                
                     pgrp->OSFlagFlags |= flags_rdy;      
                 }
             } 
			 else 
			 {
                 *perr = OS_ERR_FLAG_NOT_RDY;
             }
             OS_EXIT_CRITICAL();
             break;

        case OS_FLAG_WAIT_CLR_ANY:
             flags_rdy = (OS_FLAGS)~pgrp->OSFlagFlags & flags;   /* Extract only the bits we want      */
             if (flags_rdy != (OS_FLAGS)0) {               /* See if any flag cleared                  */
                 if (consume == OS_TRUE) {                 /* See if we need to consume the flags      */
                     pgrp->OSFlagFlags |= flags_rdy;       /* Set ONLY the flags that we got           */
                 }
             } else {
                 *perr = OS_ERR_FLAG_NOT_RDY;
             }
             OS_EXIT_CRITICAL();
             break;
#endif

        default:			/*默认情况下*/
             OS_EXIT_CRITICAL();/*开中断(退出中断)*/
             flags_rdy = (OS_FLAGS)0;/*将flags_rdy设置为0*/
             *perr     = OS_ERR_FLAG_WAIT_TYPE;/*错误码设置为OS_ERR_FLAG_WAIT_TYPE*/
             break;
    }
    return (flags_rdy);/*返回flags_rdy*/
}
#endif

大概流程图为:

\

END

不足之处还望提醒,谢过~