本篇介绍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); /*提取我们需要的位*/
解释一下我们是如何提取我们需要的位呢?这行语句为什么进行与运算?
0 | 1 | 0 | 1 | 1 | 1 | 0 | 0 |
---|
1 | 1 | 0 | 1 | 1 | 0 | 0 | 0 |
---|
OSFlagFlags和flags都是8位。假定各自8位分别如上图设置。当我们提取位的时候,就一一对应,进行逻辑与操作,并赋给flags_rdy:
0 | 1 | 0 | 1 | 1 | 0 | 0 | 0 |
---|
然后再将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
不足之处还望提醒,谢过~