本篇介绍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);     /*提取我们需要的位*/

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

OSFlagFlags
0 1 0 1 1 1 0 0
flags
1 1 0 1 1 0 0 0

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

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*/}#endifif (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;
#endifdefault:          /*默认情况下*/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

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

OS_FLAG.C(1)相关推荐

  1. OS_FLAG.C(3)

    上篇我们介绍了创建和删除事件标志组函数,后来在接着看源代码的时候,发现倒着来更有助于理解.所以后面几篇我会选择较为合适的方式来不定期更博,方便大家理解. 1.介绍删除节点函数OS_FlagUnlink ...

  2. OS_FLAG.C(2)

    本篇介绍OS_FLAG.C文件中的创建事件标志组函数*OSFlagCreate (OS_FLAGS  flags,INT8U *perr)和删除事件标志组函数 *OSFlagDel (OS_FLAG_ ...

  3. OpenAPI使用(swagger3),Kotlin使用swagger3,Java使用swagger3,gradle、Maven使用swagger3

    OpenAPI使用(swagger3) demo见Gitte 一.背景及名词解释 OpenAPI是规范的正式名称.规范的开发工作于2015年启动,当时SmartBear(负责Swagger工具开发的公 ...

  4. 2022-2028年中国第五代移动通信技术(5G)市场研究及前瞻分析报告

    [报告类型]产业研究 [报告价格]4500起 [出版时间]即时更新(交付时间约3个工作日) [发布机构]智研瞻产业研究院 [报告格式]PDF版 本报告介绍了中国第五代移动通信技术(5G)行业市场行业相 ...

  5. 2021-2027全球与中国经颅磁刺激仪(TMS)市场现状及未来发展趋势

    [报告类型]产业研究 [报告价格]¥4500起 [出版时间]即时更新(交付时间约3个工作日) [发布机构]智研瞻产业研究院 [报告格式]PDF版 本报告介绍了全球与中国经颅磁刺激仪(TMS)行业市场行 ...

  6. Go 学习笔记(84)— Go 项目目录结构

    1. 目录规范 一个好的目录结构至少要满足以下几个要求. 命名清晰:目录命名要清晰.简洁,不要太长,也不要太短,目录名要能清晰地表达出该目录实现的功能,并且目录名最好用单数.一方面是因为单数足以说明这 ...

  7. Redis 笔记(16)— info 指令和命令行工具(查看内存、状态、客户端连接数、监控服务器、扫描大key、采样服务器、执行批量命令等)

    Info 命令返回关于 Redis 服务器的各种信息和统计数值.通过给定可选的参数 section ,可以让命令只返回某一部分的信息. 1. 显示模块 server : 一般 Redis 服务器信息, ...

  8. Redis 笔记(12)— 单线程架构(非阻塞 IO、多路复用)和多个异步线程

    Redis 使用了单线程架构.非阻塞 I/O .多路复用模型来实现高性能的内存数据库服务.Redis 是单线程的.那么为什么说是单线程呢? Redis 在 Reactor 模型内开发了事件处理器,这个 ...

  9. Redis 笔记(10)— 发布订阅模式(发布订阅单个信道、订阅信道后的返回值分类、发布订阅多个信道)

    1. 发布-订阅概念 发布-订阅 模式包含两种角色,分别为发布者和订阅者. 订阅者可以订阅一个或者若干个频道(channel): 而发布者可以向指定的频道发送消息,所有订阅此频道的订阅者都可以收到此消 ...

最新文章

  1. 【 全干货 】5 分钟带你看懂 Docker !
  2. 毕业就拿阿里offer,你和他比差在哪?
  3. Nginx源码分析(3)
  4. Big Sur:加州一号公路和比克斯比大桥
  5. Boost:bind绑定boost::apply的测试程序
  6. Qtum量子链帅初受邀火星特训营面对面授课
  7. CPU是如何处理指令的
  8. intellij idea 12 搭建maven web项目 freemarker + spring mvc
  9. ubuntu16.04 安装python3.6
  10. .NET后台如何获取前台HMTL控件的值
  11. 简单web服务器的实现(C++)
  12. 著名的十大经济学效应
  13. Pytorch——报错解决:匈牙利匹配
  14. excel表格公式出现#REF是什么意思
  15. 中国移动通信互联网短信网关接口协议及相关下载
  16. 百度之星Valley Numer
  17. Multisim14安装报错fatal error!Required NIPathsDir property NISHAREDDIR is undefined.
  18. 卷土重来的FCoin日本站,你被割了吗?
  19. facebooks项目aria是您一生的Google地图
  20. 在ORCAD原理图中怎么去指定器件的封装呢?

热门文章

  1. jQuery对象的序列化详解
  2. 《ArcGIS Engine 地理信息系统开发从入门到精通(第二版)》——6.7 本章小结
  3. JVM 史上最最最完整知识总结!
  4. 新一代垃圾回收器ZGC的探索与实践
  5. 如何让 Mybatis 自动生成代码
  6. 一次服务器CPU占用率高的定位分析
  7. 欠阿里云一分钱,会是什么样的后果。。。
  8. 工作没有挑战性,怎么办?
  9. 专心做业务,别想不开搞研发
  10. 这大概是一篇最简单最清晰的Java JVM执行流程