FreeRTOS 24:事件组EventGroup等待、清零、获取操作

等待事件标志位xEventGroupWaitBits()

既然标记了事件的发生,那么我怎么知道他到底有没有发生,这也是需要一个函数来获 取 事 件 是 否 已 经 发 生 , FreeRTOS 提 供 了 一 个 等 待 指 定 事 件 的 函 数 — —
xEventGroupWaitBits(),通过这个函数, 任务可以知道事件标志组中的哪些位,有什么事件发生了, 然后通过 “逻辑与”、“逻辑或”等操作对感兴趣的事件进行获取,并且这个函数实现了等待超时机制, 当且仅当任务等待的事件发生时,任务才能获取到事件信息。在这段时间中,如果事件一直没发生,该任务将保持阻塞状态以等待事件发生。当其它任务或中断服务程序往其等待的事件设置对应的标志位,该任务将自动由阻塞态转为就绪态。当任务等待的时间超过了指定的阻塞时间,即使事件还未发生,任务也会自动从阻塞态转移为就绪态。这样子很有效的体现了操作系统的实时性,如果事件正确获取(等待到) 则返回对应的事件标志位,由用户判断再做处理, 因为在事件超时的时候也会返回一个不能确定的事件值,所以需要判断任务所等待的事件是否真的发生。

EventGroupWaitBits()用于获取事件组中的一个或多个事件发生标志, 当要读取的事件标 志 位 没 有 被 置 位 时 任 务 将 进 入 阻 塞 等 待 状 态 。

EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup,const EventBits_t uxBitsToWaitFor,const BaseType_t xClearOnExit,const BaseType_t xWaitForAllBits,TickType_t xTicksToWait )
{EventGroup_t * pxEventBits = xEventGroup;EventBits_t uxReturn, uxControlBits = 0;BaseType_t xWaitConditionMet, xAlreadyYielded;BaseType_t xTimeoutOccurred = pdFALSE;// 检查用户是否尝试等待内核自身使用的位,并且至少请求了一个位configASSERT( xEventGroup );configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );configASSERT( uxBitsToWaitFor != 0 );#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ){configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );}#endifvTaskSuspendAll();{const EventBits_t uxCurrentEventBits = pxEventBits->uxEventBits;// 检查等待条件是否已经满足xWaitConditionMet = prvTestWaitCondition( uxCurrentEventBits, uxBitsToWaitFor, xWaitForAllBits );if( xWaitConditionMet != pdFALSE ){// 等待条件已经满足,无需阻塞uxReturn = uxCurrentEventBits;xTicksToWait = ( TickType_t ) 0;// 如果需要,清除等待的位if( xClearOnExit != pdFALSE ){pxEventBits->uxEventBits &= ~uxBitsToWaitFor;}else{mtCOVERAGE_TEST_MARKER();}}else if( xTicksToWait == ( TickType_t ) 0 ){// 等待条件未满足,但未指定阻塞时间,直接返回当前值uxReturn = uxCurrentEventBits;xTimeoutOccurred = pdTRUE;}else{// 任务将阻塞等待所需位被设置// 使用控制位记录此调用的行为if( xClearOnExit != pdFALSE ){uxControlBits |= eventCLEAR_EVENTS_ON_EXIT_BIT;}else{mtCOVERAGE_TEST_MARKER();}if( xWaitForAllBits != pdFALSE ){uxControlBits |= eventWAIT_FOR_ALL_BITS;}else{mtCOVERAGE_TEST_MARKER();}// 将调用任务等待的位存储在任务的事件列表项中,以便内核知道何时找到匹配项vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | uxControlBits ), xTicksToWait );// 这是过时的,但在某些编译器中如果不这样做会生成警告uxReturn = 0;traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor );}}xAlreadyYielded = xTaskResumeAll();if( xTicksToWait != ( TickType_t ) 0 ){if( xAlreadyYielded == pdFALSE ){portYIELD_WITHIN_API();}else{mtCOVERAGE_TEST_MARKER();}// 任务阻塞等待所需位被设置,此时要么所需位已被设置,要么阻塞时间已到期// 如果所需位已被设置,它们将存储在任务的事件列表项中,现在应检索并清除uxReturn = uxTaskResetEventItemValue();if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 ){taskENTER_CRITICAL();{// 任务超时,返回当前事件位值uxReturn = pxEventBits->uxEventBits;// 可能在任务离开阻塞状态和再次运行之间更新了事件位if( prvTestWaitCondition( uxReturn, uxBitsToWaitFor, xWaitForAllBits ) != pdFALSE ){if( xClearOnExit != pdFALSE ){pxEventBits->uxEventBits &= ~uxBitsToWaitFor;}else{mtCOVERAGE_TEST_MARKER();}}else{mtCOVERAGE_TEST_MARKER();}xTimeoutOccurred = pdTRUE;}taskEXIT_CRITICAL();}else{// 任务因位被设置而解除阻塞}// 任务阻塞,因此可能设置了控制位uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;}traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred );// 防止编译器警告( void ) xTimeoutOccurred;return uxReturn;
}

xEventGroupWaitBits 函数用于等待事件组中的特定事件位被设置。具体功能和步骤如下:

  1. 参数检查

    • 检查传入的事件组是否有效。

    • 检查等待的位是否包含内核自身使用的位。

    • 检查至少请求了一个位。

    • 如果配置了 INCLUDE_xTaskGetSchedulerState 或 configUSE_TIMERS,则检查调度器是否暂停并且等待时间不为零。

  2. 任务调度暂停

    • 暂停任务调度,防止其他任务干扰。

  3. 检查当前事件位

    • 获取当前事件位。

    • 检查等待条件是否已经满足。

      • 如果满足,直接返回当前事件位,并根据需要清除这些位。

      • 如果不满足且未指定阻塞时间,直接返回当前事件位并设置超时标志。

      • 如果不满足且指定了阻塞时间,将任务加入等待队列。

  4. 任务阻塞

    • 根据需要设置控制位,记录任务的行为。

    • 将任务加入等待队列,等待所需事件位被设置。

    • 恢复任务调度。

  5. 任务唤醒

    • 如果任务因事件位被设置而唤醒,返回当前事件位。

    • 如果任务因超时而唤醒,返回当前事件位并设置超时标志。

  6. 清除控制位

    • 返回前清除控制位,防止影响后续操作。

清零事件标志位

xEventGroupClearBits()与 xEventGroupClearBitsFromISR()都是用于清除事件组指定的位, 如果在获取事件的时候没有将对应的标志位清除, 那么就需要用这个函数来进行显式清除, xEventGroupClearBits()函数不能在中断中使用,而是由具有中断保护功能 的xEventGroupClearBitsFromISR() 来代替,中断清除事件标志位的操作在守护任务(也叫定时 器 服 务 任 务 ) 里 面 完 成 。 守 护 进 程 的 优 先 级 由 FreeRTOSConfig.h 中 的 宏configTIMER_TASK_PRIORITY 来 定 义 。

xEventGroupClearBits()清零事件标志位

EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup,const EventBits_t uxBitsToClear )
{EventGroup_t * pxEventBits = xEventGroup;EventBits_t uxReturn;/* 检查用户是否尝试清除内核自身使用的位 */configASSERT( xEventGroup );configASSERT( ( uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES ) == 0 );taskENTER_CRITICAL();{traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear );/* 返回值是清除位之前的事件组值 */uxReturn = pxEventBits->uxEventBits;/* 清除指定的位 */pxEventBits->uxEventBits &= ~uxBitsToClear;}taskEXIT_CRITICAL();return uxReturn;
}

函数 xEventGroupClearBits,用于清除事件组中的指定位。

  1. 参数检查

    • configASSERT( xEventGroup );:检查事件组句柄是否有效。
    • configASSERT( ( uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES ) == 0 );:确保要清除的位不包含内核保留的位。
  2. 进入临界区

    • taskENTER_CRITICAL();:进入临界区,防止多任务环境下的并发问题。
  3. 记录当前事件组值

    • uxReturn = pxEventBits->uxEventBits;:在清除位之前,记录当前事件组的值。
  4. 清除指定位

    • pxEventBits->uxEventBits &= ~uxBitsToClear;:通过按位与操作清除指定的位。
  5. 退出临界区

    • taskEXIT_CRITICAL();:退出临界区。
  6. 返回结果

    • return uxReturn;:返回清除位之前的事件组值。

xEventGroupClearBitsFromISR()在中断中清零事件标志位

#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup,const EventBits_t uxBitsToClear )
{BaseType_t xReturn;// 记录从中断服务例程清除事件组位的操作traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear );// 将清除位的操作挂起到调度器,以便在合适的时机执行xReturn = xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL ); /*lint !e9087 无法避免将指针强制转换为 void*,因为这是一个通用的回调函数,不是特定于此用例的。回调会将指针重新转换为原始类型,因此是安全的。 */// 返回挂起结果return xReturn;
}#endif /* if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */

函数 xEventGroupClearBitsFromISR,用于在中断服务例程(ISR)中清除事件组中的指定位。具体功能如下:

  1. 参数检查:无显式的参数检查,但通过调用 xTimerPendFunctionCallFromISR 来确保安全。

  2. 记录事件:记录从中断服务例程清除事件组位的操作。

  3. 挂起函数调用:使用 xTimerPendFunctionCallFromISR 将清除位的操作挂起到调度器,以便在合适的时机执行。

  4. 返回结果:返回 xTimerPendFunctionCallFromISR 的结果,指示是否成功挂起函数调用。

获取事件组中各事件标志位的值xEventGroupGetBits()

EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup )
{UBaseType_t uxSavedInterruptStatus;EventGroup_t const * const pxEventBits = xEventGroup;EventBits_t uxReturn;// 保存当前的中断状态,防止中断嵌套uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();{// 从事件组中读取当前的位值uxReturn = pxEventBits->uxEventBits;}// 恢复中断状态portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );// 返回事件组的当前位值return uxReturn;
} /*lint !e818 EventGroupHandle_t 是一个在其他函数中使用的 typedef,因此不能是指向常量的指针。*//*lint !e818 EventGroupHandle_t is a typedef used in other functions to so can't be pointer to const. */

函数 xEventGroupGetBitsFromISR,用于在中断服务例程(ISR)中获取事件组的当前位。具体功能如下:

  1. 保存中断状态:使用 portSET_INTERRUPT_MASK_FROM_ISR 保存当前的中断状态,防止中断嵌套。

  2. 获取事件组位:从事件组中读取当前的位值。

  3. 恢复中断状态:使用 portCLEAR_INTERRUPT_MASK_FROM_ISR 恢复中断状态。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/12157.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

信息安全数学基础(47)域的结构

一、域的定义 设F为一个非空集合,在其上定义两种运算:加法和乘法。如果这两种运算在集合上封闭,且满足以下条件,则称F对于规定的乘法和加法构成一个域: F中所有元素对于加法形成加法交换群,即加法满足交换律…

#渗透测试#SRC漏洞挖掘#CSRF漏洞的防御

免责声明 本教程仅为合法的教学目的而准备,严禁用于任何形式的违法犯罪活动及其他商业行为,在使用本教程前,您应确保该行为符合当地的法律法规,继续阅读即表示您需自行承担所有操作的后果,如有异议,请立即停…

HarmonyOS 沉浸式状态实现的多种方式

1. HarmonyOS 沉浸式状态实现的多种方式 HarmonyOS 沉浸式状态实现的多种方式 1.1. 方法一 1.1.1. 实现讲解 (1)首先设置setWindowLayoutFullScreen(true)(设置全屏布局)。   布局将从屏幕最顶部开始到最底部结束&#xff0c…

在API接口数据获取过程中,如何确保数据的安全性和隐私性?

在API接口数据获取过程中,确保数据的安全性和隐私性至关重要。以下是一些关键措施,可以帮助开发者和管理者保护API接口的数据安全和隐私性: 身份认证和授权 身份认证:确认用户身份的过程,常用的身份认证方式包括用户…

C++常用的特性-->day05

友元的拓展语法 声明一个类为另外一个类的友元时&#xff0c;不再需要使用class关键字&#xff0c;并且还可以使用类的别名&#xff08;使用 typedef 或者 using 定义&#xff09;。 #include <iostream> using namespace std;// 类声明 class Tom; // 定义别名 using …

python-27-Python ORM系列之彻底搞明白ORM概念,对ORM进行封装结合FastAPI实现数据库的增删改查,联表查询等接口

python-27-Python ORM系列之彻底搞明白ORM概念&#xff0c;对ORM进行封装结合FastAPI实现数据库的增删改查&#xff0c;联表查询等接口 一.简介 在Python基础系列ORM部分为大家介绍了如何搭建MySQL数据和MySQL一些访问配置&#xff0c;同时也介绍了pymysql库的封装来实现对数…

从哈佛哲学系到蛋白质设计大师,David Baker:AlphaFold令我深刻认识到深度学习的力量

要说谁是引领蛋白质设计的世界级大师&#xff0c;美国华盛顿大学的 David Baker 教授可谓是当之无愧&#xff0c;作为该领域的顶级专家&#xff0c;Baker 在蛋白质方向发表研究论文 700 余篇&#xff0c;引用量累计超 17.7 万。今年 10 月&#xff0c;因其在蛋白质设计方面的卓…

【测试框架篇】单元测试框架pytest(2):用例编写

一、 前言 前面一章我们介绍了pytest环境安装和配置&#xff0c;并在pycharm里面实现了我们第一个pytest脚本。但是有些童鞋可能在编写脚本的时候遇到了问题&#xff0c;本文会讲一下我们编写pytest用例时需要遵守哪些既定的规则&#xff0c;同时这个规则也是可以修改的。 二…

实现LiDAR和多视角摄像头数据的对齐、可控X-DRIVE:用于驾驶场景的跨模态一致多传感器数据合成

Abstract 近年来&#xff0c;扩散模型在合成驾驶场景中的LiDAR点云或摄像头图像数据方面取得了进展。尽管这些模型在单一模态数据的边际分布建模方面取得成功&#xff0c;但对不同模态之间互相依赖关系的探索仍然不足&#xff0c;而这种依赖关系能够更好地描述复杂的驾驶场景。…

稳恒磁场(1)

物理概念 磁场是物质性的。 地磁场&#xff08;与地磁场正负极相反&#xff09;与磁偏角&#xff08;一般为0到11度&#xff09; 磁感应强度&#xff1a; 单位为特斯拉&#xff08;T&#xff09;&#xff0c;另一个常用单位是高斯&#xff08;G&#xff09;且1T 10^4 G 物…

自动驾驶系列—自动驾驶中的短距离感知:超声波雷达的核心技术与场景应用

&#x1f31f;&#x1f31f; 欢迎来到我的技术小筑&#xff0c;一个专为技术探索者打造的交流空间。在这里&#xff0c;我们不仅分享代码的智慧&#xff0c;还探讨技术的深度与广度。无论您是资深开发者还是技术新手&#xff0c;这里都有一片属于您的天空。让我们在知识的海洋中…

多语言爬取淘宝价格信息 python 比价api接入指南

以下是爬取淘宝价格信息及接入淘宝比价 API 的一般步骤&#xff1a; 传统爬虫方式获取价格信息&#xff08;不建议大量使用&#xff0c;可能违反淘宝规定&#xff09;&#xff1a; 分析目标页面 URL&#xff1a;在淘宝搜索框输入关键词后&#xff0c;观察页面的 URL 结构。例如…

Java List——针对实习面试

目录 Java ListJava List的三种主要实现是什么&#xff1f;它们各自的特点是什么&#xff1f;Java List和Array&#xff08;数组&#xff09;的区别&#xff1f;Java List和Set有什么区别&#xff1f;ArrayList和Vector有什么区别&#xff1f;什么是LinkedList&#xff1f;它与…

如何在Linux系统中安装微信

官方版微信的安装 好消息是&#xff0c;现在微信已经发布了官方的Linux版本&#xff0c;大家可以直接通过官方网站下载并安装&#xff0c;避免了以前繁琐的第三方工具安装步骤。 1.1 下载官方版微信 微信&#xff0c;是一个生活方式 选择Linux-> X86 1.2 安装微信 提前…

java双向链表解析实现双向链表的创建含代码

双向链表 一.双向链表二.创建MyListCode类实现双向链表创建一.AddFirst创建&#xff08;头插法&#xff09;二.AddLast创建&#xff08;尾叉法&#xff09;三.size四.remove(指定任意节点的首位删除)五.removeAll(包含任意属性值的所有删除)六.AddIndex(给任意位置添加一个节点…

hhdb数据库介绍(2-2)

数据高可用服务 HHDB Server在计算节点、数据节点、配置库等层次提供全面的高可用保障。提供完善的心跳检测、故障切换对存储节点同步追平判断、全局自增序列在故障时自动跳号、客户端连接Hold等机制&#xff0c;保障数据服务的可用性与数据的一致性。 计算节点服务高可用 H…

精挑细选的100道软测高频面试题,面试前你肯定用得上

测试技术面试题 1、什么是兼容性测试&#xff1f;兼容性测试侧重哪些方面&#xff1f; 2、我现在有个程序&#xff0c;发现在 Windows 上运行得很慢&#xff0c;怎么判别是程序存在问题还是软硬件系统存在问题&#xff1f; 3、测试的策略有哪些&#xff1f; 4、正交表测试用…

STM32获取SHT3X温湿度芯片数据

目录 一、概述 二、单次数据采集模式的测量 1、配置说明 2、代码实现方式 三、周期性数据采集模式的测量 1、配置说明 2、代码实现方式 四、完整代码下载链接 一、概述 SHT3X是Sensirion公司推出的一款高精度、完全校准的温湿度传感器&#xff0c;基于CMOSens技术。它提…

[原创]手把手教学之前端0基础到就业——day11( Javascript )

文章目录 day11(Javascript)01Javascript①Javascript是什么②JavaScript组成③ Javascript的书写位置1. 行内式 (不推荐)2 . 内部位置使用 ( 内嵌式 )3. 外部位置使用 ( 外链式 ) 02变量1. 什么是变量2. 定义变量及赋值3. 注意事项4. 命名规范 03输入和输出1) 输出形式12) 输出…

[JAVAEE] 面试题(五) - HashMap, Hashtable, ConcurrentHashMap

目录 一. Hashtable1.1 Hashtable效率低下的原因: 二. ConcurrentHashMap2.1 ConcurrentHashMap更高效的原因: 三. HashMap, Hashtable, ConcurrentHashMap 之间的区别 HashMap是线程不安全的. 在多线程环境下, 使用: HashtableConcurrentHashMap 来确保线程安全. 一. Hashta…