当前位置: 首页 > news >正文

FreeRTOS学习笔记(八)事件

文章目录

  • 前言
  • 一、事件
    • 1.1 事件的引入
    • 1.2 事件位和事件组
  • 二、事件的实现
    • 2.1 相关API函数
    • 2.2 实现流程


前言

  本章我们将展开事件的学习,着重比对和信号量的异同及优劣。


一、事件

1.1 事件的引入

  前面我们学习了使用信号量来完成同步,但是使用信号量来同步的话任务只能与单个的事件或任务进行同步。有时候某个任务可能会需要与多个事件或任务进行同步,此时信号量就无能为力了。
  事件是一种实现任务间通信的机制,多用于实现多任务之间的同步,但只能进行事件类型的通信,不能通过数据。它可以实现一对多,多对多的通信,即一个任务可以等待一(多)个事件发生;也可以是一(多)个事件都发生后唤醒任务。事件无排队性,多次向任务设置同一事件等同于只设置一次,且支持等待超时机制
  每个事件在获取的时候,用户可以选择感兴趣的事件,并选择读取事件信息标记,它有三个属性“逻辑与”“逻辑或”以及“是否清楚标记”。当任务等待事件同步时,可以通过任务感兴趣的事件位和信息标记位去判断事件是否符合要求,若满足则任务等待到对应事件去,反之任务会感觉超时时间继续等待。

1.2 事件位和事件组

  在FreeRTOS中,事件位(Event bits)用来表明某个事件是否发生,事件位通常用作事件标志。32位的每一位都可以单独表示一个事件,例如,第1位代表某个特定的事件,第2位代表另一个事件。任务可以通过设置、清除或者等待某个(或多个)特定的事件标志来实现同步。
  事件标志组(Event Groups)是一种轻量级的任务间同步机制,允许多个任务通过事件标志进行通信或协调。事件标志组提供了一种可以通过多个标志位表示任务状态或事件发生情况的方式,任务可以等待一个或多个标志位被设置。它也是一个 32 位的整数,[23:0]位的每一个位可以单独作为一个标志位,每个标志位可以是 0 或 1,分别代表某个事件未发生或已发生。

二、事件的实现

2.1 相关API函数

  FreeRTOS提供了一组API函数来操作事件标志组,主要包括:
xEventGroupCreate( )
  此函数用于创建一个事件标志组,所需要的内存通过动态内存管理方法分配。事件标志组可用的 bit 数和最大延时值portMAX_DELAY取决于event_groups的configUSE_16_BIT_TICKS宏定义 ,具体如下:

  • 1:16 位模式下,事件标志组有8个可用的位[7:0],最大延时为 0xffff,即 65535;
  • 0:32 位模式下,事件标志组有 24 个可用的位[23:0],最大延时为 0xffffffff,即 4,294,967,295。
// 创建事件标志组
EventGroupHandle_t xEventGroupCreate( void );

xEventGroupWaitBits( )
  某个任务可能需要与多个事件进行同步,那么这个任务就需要等待并判断多个事件位(标志),使用函数 xEventGroupWaitBits()可以完成这个功能。调用函数以后如果任务要等待的事件位还没有准备好(置 1 或清零)的话任务就会进入阻塞态,直到阻塞时间到达或者所等待的事件位准备好。

// 用于等待特定的事件标志被设置
EventBits_t xEventGroupWaitBits(EventGroupHandle_t xEventGroup,const EventBits_t uxBitsToWaitFor,const BaseType_t xClearOnExit,const BaseType_t xWaitForAllBits,TickType_t xTicksToWait );
  • 参数说明:
    • xEventGroup:标志组句柄
    • uxBitsToWaitFor:等待的标志位
    • xClearOnExit:是否在退出时清除等待的标志位
    • xWaitForAllBits:等待所有指定的标志位都被设置,还是只等待任意一个标志位被设置
    • xTicksToWait:等待时间

xEventGroupSetBits( )xEventGroupSetBitsFromISR( )
  这两个函数的作用都是设置指定的事件位为 1,但xEventGroupSetBits( )函数只能用在任务中,xEventGroupSetBitsFromISR( )用于中断服务函数,此函数原型如
下:

// 设置指定的标志位,通常用于通知任务某个事件发生
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet );
  • 参数:
    • xEventGroup: 要操作的事件标志组的句柄
    • uxBitsToClear: 指定要置 1 的事件位,比如要将 bit3 值 1 的话就设置为 0X08,如设置为 0X09 的话就是同时将 bit3 和 bit0 置 1
BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t * pxHigherPriorityTaskWoken );
  • 参数:
    • xEventGroup: 要操作的事件标志组的句柄
    • uxBitsToClear: 指定要置 1 的事件位
    • pxHigherPriorityTaskWoken:标记退出此函数以后是否进行任务切换
  • 返回值:
    • 成功:pdPASS
    • 失败:pdFALSE

  值得注意的是,我们还可以使用类似#define EVENT (0x01<<X)的宏定义进行置位,这种方式与使用 xEventGroupSetBits() 函数是配合使用的。通过宏定义事件位可以方便地指定要在事件标志组中设置的位,当调用 xEventGroupSetBits() 时,可以使用这些宏来明确需要设置哪些事件位。
xEventGroupClearBits( )xEventGroupClearBitsFromISR( )
  将事件标志组中的指定事件位清零,和置1的两个函数一样分别用于任务和中断。

// 清除指定的标志位,常用于复位某个事件状态
EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear );
  • 参数:
    • xEventGroup: 要操作的事件标志组的句柄
    • uxBitsToClear: 要清零的事件位
BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, 
const EventBits_t uxBitsToSet );
  • 参数:
    • xEventGroup: 要操作的事件标志组的句柄
    • uxBitsToClear: 指定要置 1 的事件位
  • 返回值:
    • 成功:pdPASS
    • 失败:pdFALSE

xEventGroupGetBits( )xEventGroupGetBitsFromISR( )
  我们可以通过 FreeRTOS 提供的 API 函数来查询事件标准组值,FreeRTOS 一共提供了两个这样的 API 函数:

// 用于任务获取当前事件标志组的值
EventBits_t xEventGroupGetBits( EventGroupHandle_t xEventGroup )
  • 参数:
    • xEventGroup: 要获取的事件标志组的句柄
// 用于中断获取当前事件标志组的值
EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup )
  • 参数:
    • xEventGroup: 要获取的事件标志组的句柄。

2.2 实现流程

  1. 宏定义的设置:事件标志组的实现过程中有一些关键的宏定义,这些定义用于配置事件标志组和任务调度相关的操作。
      EventBits_t: 表示事件标志的存储类型,实际上是 TickType_t 类型,由configUSE_16_BIT_TICKS 设置(前面提到过),具体定义如下:
typedef TickType_t EventBits_t;

  xEventGroupSetBits: 用于设置事件标志的宏,用于触发指定的事件位:

// 这里 uxBitsToSet 是需要设置的事件位。
#define xEventGroupSetBits( xEventGroup, uxBitsToSet ) \xEventGroupSetBitsFromISR( xEventGroup, uxBitsToSet, NULL )
  1. 创建事件标志组:创建一个事件标志组使用 xEventGroupCreate() 函数。此函数会在内存中分配一个事件标志组的数据结构,并初始化为全 0 的事件位。
  2. 设置事件位:要设置某些事件位,可以使用 xEventGroupSetBits() 函数。此函数将指定的事件位设置为 1,同时检查是否有任何任务正等待这些位,并唤醒它们。
  3. 等待事件位:任务可以通过 xEventGroupWaitBits() 函数等待某些事件位被设置。该函数会将调用任务置为阻塞状态,直到指定的事件位发生变化。
  4. 清除事件位:利用xEventGroupClearBits() 函数用于手动清除某些事件位。

免责声明:本文参考了网上公开资料,仅用于学习交流,若有错误或侵权请联系笔者。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • echarts 3D地图
  • 可信的人类与人工智能协作:基于人类反馈和物理知识的安全自主驾驶强化学习
  • JAVA开源项目 校园管理系统 计算机毕业设计
  • python fastapi 打包exe
  • mysql笔记7(单表查询)
  • Python知识点:如何使用Python进行日志处理与分析
  • 2024icpc南京站
  • go-zero的快速实战(完整)
  • 基础 Web 开发
  • R134a制冷剂简介
  • clickhouse适用的业务场景
  • 编写XBOX控制器实现鼠标键盘输入
  • 数学建模笔记—— 回归分析
  • MultiSnapRecyclerView:让Android RecyclerView的滚动停靠更灵活
  • oracle 用游标为什么会比for循环慢?
  • 【node学习】协程
  • 【跃迁之路】【699天】程序员高效学习方法论探索系列(实验阶段456-2019.1.19)...
  • Docker: 容器互访的三种方式
  • DOM的那些事
  • ES6--对象的扩展
  • EventListener原理
  • iOS编译提示和导航提示
  • javascript 总结(常用工具类的封装)
  • Java方法详解
  • Java深入 - 深入理解Java集合
  • JS基础之数据类型、对象、原型、原型链、继承
  • Spring Cloud Feign的两种使用姿势
  • Spring思维导图,让Spring不再难懂(mvc篇)
  • uni-app项目数字滚动
  • 爱情 北京女病人
  • 纯 javascript 半自动式下滑一定高度,导航栏固定
  • 基于游标的分页接口实现
  • 配置 PM2 实现代码自动发布
  • 系统认识JavaScript正则表达式
  • 用mpvue开发微信小程序
  • 掌握面试——弹出框的实现(一道题中包含布局/js设计模式)
  • 字符串匹配基础上
  • k8s使用glusterfs实现动态持久化存储
  • 积累各种好的链接
  • 继 XDL 之后,阿里妈妈开源大规模分布式图表征学习框架 Euler ...
  • !!Dom4j 学习笔记
  • # Swust 12th acm 邀请赛# [ E ] 01 String [题解]
  • (+3)1.3敏捷宣言与敏捷过程的特点
  • (4)事件处理——(7)简单事件(Simple events)
  • (6) 深入探索Python-Pandas库的核心数据结构:DataFrame全面解析
  • (k8s)Kubernetes 从0到1容器编排之旅
  • (八)c52学习之旅-中断实验
  • (超简单)使用vuepress搭建自己的博客并部署到github pages上
  • (附源码)ssm高校志愿者服务系统 毕业设计 011648
  • (机器学习-深度学习快速入门)第一章第一节:Python环境和数据分析
  • (论文阅读32/100)Flowing convnets for human pose estimation in videos
  • (论文阅读笔记)Network planning with deep reinforcement learning
  • (七)c52学习之旅-中断
  • *Django中的Ajax 纯js的书写样式1
  • .[hudsonL@cock.li].mkp勒索病毒数据怎么处理|数据解密恢复