13、FreeRTOS 事件标志组

文章目录

  • 一、事件组(event group)的特性
    • 1.1 什么是事件标注组
    • 1.2 事件标注组的场景
    • 1.3 事件组的概念
    • 1.4 事件组的操作
  • 二、事件组API
    • 2.1 创建
    • 2.2 删除
    • 2.3 设置事件
    • 2.4 等待事件
    • 2.5 同步点

一、事件组(event group)的特性

1.1 什么是事件标注组

事件标志位:表明某个事件是否发生,联想:全局变量 flag。通常按位表示,每一个位表示一个事件(高8位 不算)

事件标志组是一组事件标志位的集合, 可以简单的理解事件标志组,就是一个整数。 事件标志组本质是一个 16 位32 位 无符号的数据类型 EventBits_t ,由 configUSE_16_BIT_TICKS 决定。 虽然使用了 32 位无符号的数据类型变量来存储事件标志, 但其中的高8位用作存储事件标志组的控制信息, 低 24 位用作存储事件标志 ,所以说一个事件组最多可以存储 24 个事件标志!

在这里插入图片描述

1.2 事件标注组的场景

学校组织秋游,组长在等待:

  • 张三:我到了
  • 李四:我到了
  • 王五:我到了
  • 组长说:好,大家都到齐了,出发!

秋游回来第二天就要提交一篇心得报告,组长在焦急等待:张三、李四、王五谁先写好就交谁的。

在这个日常生活场景中:

  • 出发:要等待这3个人都到齐,他们是"与"的关系 交

  • 报告:只需等待这3人中的任何一个,他们是"或"的关系

    在FreeRTOS中,可以使用事件组(event group)来解决这些问题。

1.3 事件组的概念

事件组可以简单地认为就是一个整数:

  • 每一位表示一个事件

  • 每一位事件的含义由程序员决定,比如:Bit0表示用来串口是否就绪,Bit1表示按键是否被按下

  • 这些位,值为1表示事件发生了,值为0表示事件没发生

  • 一个或多个任务、ISR都可以去写这些位;一个或多个任务、ISR都可以去读这些位

  • 可以等待某一位、某些位中的任意一个,也可以等待多位

    在这里插入图片描述

事件组用一个整数来表示,其中的高8位留给内核使用,只能用其他的位来表示事件。那么这个整数是 多少位的?

  • 如果configUSE_16_BIT_TICKS是1,那么这个整数就是16位的,低8位用来表示事件
  • 如果configUSE_16_BIT_TICKS是0,那么这个整数就是32位的,低24位用来表示事件
  • configUSE_16_BIT_TICKS是用来表示Tick Count的,怎么会影响事件组?这只是基于效率来考虑
    • 如果configUSE_16_BIT_TICKS是1,就表示该处理器使用16位更高效,所以事件组也使用16 位
    • 如果configUSE_16_BIT_TICKS是0,就表示该处理器使用32位更高效,所以事件组也使用32 位

1.4 事件组的操作

事件组和队列、信号量等不太一样,主要集中在2个地方

  • 唤醒谁?

    • 队列、信号量:事件发生时,只会唤醒一个任务
    • 事件组:事件发生时,会唤醒所有符号条件的任务,简单地说它有"广播"的作用
  • 是否清除事件?

    • 队列、信号量:是消耗型的资源,队列的数据被读走就没了;信号量被获取后就减少了
    • 事件组:被唤醒的任务有两个选择,可以让事件保留不动,也可以清除事件

以上图为列,事件组的常规操作如下

  • 先创建事件组

  • 任务C、D等待事件:

    • 等待什么事件?可以等待某一位、某些位中的任意一个,也可以等待多位。简单地说就 是"或"、"与"的关系。
    • 得到事件时,要不要清除?可选择清除、不清除。
  • 任务A、B产生事件:设置事件组里的某一位、某些位

二、事件组API

2.1 创建

使用事件组之前,要先创建,得到一个句柄;使用事件组时,要使用句柄来表明使用哪个事件组。 有两种创建方法:动态分配内存、静态分配内存。函数原型如下:

/* 创建一个事件组,返回它的句柄。
* 此函数内部会分配事件组结构体
* 返回值: 返回句柄,非NULL表示成功
*/
EventGroupHandle_t xEventGroupCreate( void );
/* 创建一个事件组,返回它的句柄。
* 此函数无需动态分配内存,所以需要先有一个StaticEventGroup_t结构体,并传入它的指针
* 返回值: 返回句柄,非NULL表示成功
*/
EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t *pxEventGroupBuffer );

2.2 删除

对于动态创建的事件组,不再需要它们时,可以删除它们以回收内存。 vEventGroupDelete可以用来删除事件组,函数原型如下:

/*
* xEventGroup: 事件组句柄,你要删除哪个事件组
*/
void vEventGroupDelete( EventGroupHandle_t xEventGroup )

2.3 设置事件

可以设置事件组的某个位、某些位,使用的函数有2个:

  • 在任务中使用 xEventGroupSetBits()
  • 在ISR中使用 xEventGroupSetBitsFromISR()

有一个或多个任务在等待事件,如果这些事件符合这些任务的期望,那么任务还会被唤醒。

函数原型如下:

/* 设置事件组中的位
* xEventGroup: 哪个事件组
* uxBitsToSet: 设置哪些位?
* 如果uxBitsToSet的bitX, bitY为1, 那么事件组中的bitX, bitY被设置为1
* 可以用来设置多个位,比如 0x15 就表示设置bit4, bit2, bit0
* 返回值: 返回原来的事件值(没什么意义, 因为很可能已经被其他任务修改了)
*/
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,const EventBits_t uxBitsToSet );
/* 设置事件组中的位
* xEventGroup: 哪个事件组
* uxBitsToSet: 设置哪些位?
* 如果uxBitsToSet的bitX, bitY为1, 那么事件组中的bitX, bitY被设置为1
* 可以用来设置多个位,比如 0x15 就表示设置bit4, bit2, bit0
* pxHigherPriorityTaskWoken: 有没有导致更高优先级的任务进入就绪态? pdTRUE-有,
pdFALSE-没有
* 返回值: pdPASS-成功, pdFALSE-失败
*/
BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup,
										const EventBits_t uxBitsToSet,
										BaseType_t * pxHigherPriorityTaskWoken );

值得注意的是,ISR中的函数,比如队列函数 xQueueSendToBackFromISR 、信号量函数 xSemaphoreGiveFromISR ,它们会唤醒某个任务,最多只会唤醒1个任务。

但是设置事件组时,有可能导致多个任务被唤醒,这会带来很大的不确定性。所以 xEventGroupSetBitsFromISR 函数不是直接去设置事件组,而是给一个FreeRTOS后台任务 (daemon task) 发送队列数据,由这个任务来设置事件组。

如果后台任务的优先级比当前被中断的任务优先级高, xEventGroupSetBitsFromISR 会设置 *pxHigherPriorityTaskWoken pdTRUE。 如果daemon task成功地把队列数据发送给了后台任务,那么 xEventGroupSetBitsFromISR 的返回值 就是pdPASS

2.4 等待事件

使用xEventGroupWaitBits来等待事件,可以等待某一位、某些位中的任意一个,也可以等待多位; 等到期望的事件后,还可以清除某些位。

函数原型如下:

EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
                                    const EventBits_t uxBitsToWaitFor,
                                    const BaseType_t xClearOnExit,
                                    const BaseType_t xWaitForAllBits,
                                    TickType_t xTicksToWait );

先引入一个概念:unblock condition。一个任务在等待事件发生时,它处于阻塞状态;当期望的时间 发生时,这个状态就叫"unblock condition",非阻塞条件,或称为"非阻塞条件成立";当"非阻塞条件成 立"后,该任务就可以变为就绪态。

函数参数说明列表如下:

参数说明
xEventGroup等待哪个事件组?
uxBitsToWaitFor等待哪些位?哪些位要被测试?
xWaitForAllBits怎么测试?是"AND"还是"OR"?
pdTRUE: 等待的位,全部为1;
pdFALSE: 等待的位,某一个为1即可
xClearOnExit函数提出前是否要清除事件?
pdTRUE: 清除uxBitsToWaitFor指定的位
pdFALSE: 不清除
xTicksToWait如果期待的事件未发生,阻塞多久。
可以设置为0:判断后即刻返回;
可设置为portMAX_DELAY:一定等到成功才返回;
可以设置为期望的Tick Count,一般用 pdMS_TO_TICKS() 把ms转换为Tick Count
返回值返回的是事件值,
如果期待的事件发生了,返回的是"非阻塞条件成立"时的事件值;
如果是超时退出,返回的是超时时刻的事件值。

举例如下:

事件组的值uxBitsToWaitForxWaitForAllBits说明
01000101pdTRUE任务期望bit0,bit2都为1,
当前值只有bit2满足,任务进入阻塞 态;
当事件组中bit0,bit2都为1时退出阻 塞态
01000110pdFALSE任务期望bit0,bit2某一个为1,
当前值满足,所以任务成功退出
01000110pdTRUE任务期望bit1,bit2都为1,
当前值不满足,任务进入阻塞态;
当事件组中bit1,bit2都为1时退出阻 塞态

你可以使用 xEventGroupWaitBits() 等待期望的事件,它发生之后再使用xEventGroupClearBits() 来清除。但是这两个函数之间,有可能被其他任务或中断抢占,它们可能会修改事件组。 可以使用设置 xClearOnExitpdTRUE,使得对事件组的测试、清零都在 xEventGroupWaitBits() 函数内部完成,这是一个原子操作

2.5 同步点

有一个事情需要多个任务协同,比如:

  • 任务A:炒菜
  • 任务B:买酒
  • 任务C:摆台
  • A、B、C做好自己的事后,还要等别人做完;大家一起做完,才可开饭

使用 xEventGroupSync() 函数可以同步多个任务:

  • 可以设置某位、某些位,表示自己做了什么事
  • 可以等待某位、某些位,表示要等等其他任务
  • 期望的时间发生后,xEventGroupSync()才会成功返回。
  • xEventGroupSync 成功返回后,会清除事件

xEventGroupSync 函数原型如下:

EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup,
                                const EventBits_t uxBitsToSet,
                                const EventBits_t uxBitsToWaitFor,
                                TickType_t xTicksToWait );

参数列表如下:

参数说明
xEventGroup哪个事件组?
uxBitsToSet要设置哪些事件?我完成了哪些事件?
比如0x05(二进制为0101)会导致事件组的bit0,bit2被设置为1
uxBitsToWaitFor等待那个位、哪些位?
比如0x15(二级制10101),表示要等待bit0,bit2,bit4都为1
xTicksToWait如果期待的事件未发生,阻塞多久。
可以设置为0:判断后即刻返回;
可设置为portMAX_DELAY:一定等到成功才返回;
可以设置为期望的Tick Count,一般用 pdMS_TO_TICKS() 把ms转换为Tick Count
返回值返回的是事件值,
如果期待的事件发生了,返回的是"非阻塞条件成立"时的事件值;
如果是超时退出,返回的是超时时刻的事件值。

文章是自己总结而记录,有些知识点没说明白的,请各位看官多多提意见,多多交流,欢迎大家留言
如果技术交流可以加以下群,方便沟通
QQ群:370278903
点击链接加入群聊【蜡笔小芯的嵌入式交流群】
![])

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2024kali linux上安装java8

1 kali下载Java 8安装包 访问Oracle官网或其他可信的Java下载站点,如华为云的开源镜像站(例如:https://repo.huaweicloud.com/java/jdk/8u202-b08/jdk-8u202-linux-x64.tar.gz)。 确保下载的是与你的Kali Linux系统架构&#xf…

Collection工具类

Collection工具类的介绍 Collection 是一个操作Set、List和Map等集合的工具类Collection中提供了一些列静态的方法对集合元素进行排序、查询和修改的等操作 Collection的排序操作(均为Static方法) 1,reverse(List)&…

刷t2、、、

、、 public class ThisTest {public static void main(String args[]) {int i;for (;;) {System.out.println(1);}} } while()的循环条件等于for中循环条件。循环体会有一个条件改变等于for中类似自增条件。while()判断条件一般在while前面会初始化跟for中初始化一样。这样 w…

Linux入门攻坚——23、DNS和BIND基础入门1

DNS——Domain Name Service,协议(C/S,53/udp,53/tcp) BIND——Berkeley Internet Name Domain,ISC(www.isc.org) 互联网络上主机之间的通信依靠的是IP,而人或程序一般使…

GT2512-STBA 三菱触摸屏12.1寸型

T2512-STBA参数说明:12.1"、SVGA 800*600、65536色、TFT彩色液晶显示屏、AC电源、32MB内存 三菱触摸屏GT2512-STBA性能规格详细说明: [显示部] 显示软元件:TFT彩色液晶显示屏 画面尺寸:12.1寸 分辨率:SVGA 80…

Windows10环境搭建http服务器

我 的 个 人 主 页:👉👉 失心疯的个人主页 👈👈 入 门 教 程 推 荐 :👉👉 Python零基础入门教程合集 👈👈 虚 拟 环 境 搭 建 :👉&…

连锁收银系统的五大功能

连锁收银系统是零售行业中不可或缺的工具,它为连锁店铺提供了必要的管理和运营支持。一个完善的连锁收银系统应当具备以下五大功能,以满足不断发展的零售业务需求。 1. 进销存管理 进销存管理是连锁店铺运营的核心,也是连锁收银系统不可或缺…

每日两题 / 101. 对称二叉树 230. 二叉搜索树中第K小的元素(LeetCode热题100)

101. 对称二叉树 - 力扣(LeetCode) 用两个指针同时遍历树的左右子树即可 每次遍历时,一个指针向左,另一个就要向右。一个向右,另一个就要向左 /*** Definition for a binary tree node.* struct TreeNode {* in…

生信人写程序1. Perl语言模板及配置

生物信息领域常用语言 个人认为:是否能熟悉使用Shell(项目流程搭建)R(数据统计与可视化)Perl/Python/Java…(胶水语言,数据格式转换,软件间衔接)三门语言是一位合格生物信息工程师的标准。 生物信息常用语言非常广泛,我常用的有…

【C++】学习笔记——模板进阶

文章目录 十一、模板进阶1. 非类型模板参数2. 按需实例化3. 模板的特化类模板的特化 4. 模板的分离编译 未完待续 十一、模板进阶 1. 非类型模板参数 模板参数分为类型形参和非类型形参 。类型形参即:出现在模板参数列表中,跟在class或者typename之类的…

经典权限五张表功能实现

文章目录 用户模块(未使用框架)查询功能实现步骤代码 新增功能实现步骤代码 修改功能实现步骤代码实现 删除功能实现步骤代码实现 用户模块会了,其他两个模块与其类似 用户模块(未使用框架) 查询功能 这里将模糊查询和分页查询写在一起 实现步骤 前端&#xff1…

泵站远程监控

在科技日新月异的今天,智能化管理已经成为各行业提升效率、降低成本的关键手段。特别是在水利领域,泵站作为水资源调配的重要节点,其运行效率和安全稳定性直接关系到整个供水系统的稳定。HiWoo Cloud平台凭借其强大的物联网和云计算技术&…

两重惊喜!奥特曼预告GPT-4和ChatGPT重大更新,Open AI要放大招

OpenAI在今天官宣13日(下周一10点)开启线上直播,将会展示全新的ChatGPT demo的演示以及GPT-4的重大更新! OpenAI首席执行官Sam Altman在X上表示,这些的发布会,公司不会宣布下一代对话式人工智能GPT-5或人工…

游戏安全干货报告干货下载 |《2023年度游戏安全观察与实践报告》

AIGC浪潮从大洋彼岸袭来,使得全球资本市场看好AIGC将对游戏行业“成本”与“效率”带来革命性的变化;年末,国家新闻出版署一次性批准了105款国产游戏版号,为历史之最;全年亦有不少“某某大厂裁撤游戏业务”、“某某游戏…

C语言写扫雷游戏(数组和函数实践)

目录 最后是代码啦! 手把手教你用C语言写一个扫雷游戏! 1.我们搭建一下这个多文件形式的扫雷游戏文件结构 2.在主函数里面设置一个包含游戏框架的菜单 菜单可以方便游戏玩家选择要进行的动作和不断地进行下一局。 3.switch语句连接不同的结果 菜单可…

C++实现一个简单的控制cpu利用率的程序

写一个程序&#xff0c;让控制cpu利用率在20%左右 思路很简单&#xff1a;每个循环控制sleep的时间占比 #include <iostream> #include <chrono> #include <unistd.h>int main() {int ratio 20;int base_time 1000;int sleeptime base_time * (100-ratio…

信息系统架构模型_3.企业数据交换总线

1.企业数据交换总线 实践中&#xff0c;还有一种较常用的架构&#xff0c;即企业数据交换总线&#xff0c;即不同的企业应用之间进行信息交换的公共通道&#xff0c;如图1所示。 图1 企业数据交换总线架构 这种架构在大型企业不同应用系统进行信息交换时使用较普遍&am…

uniapp管理后台编写,基于uniadmin和vue3实现uniapp小程序的管理后台

一&#xff0c;创建uniAdmin项目 打开开发者工具Hbuilder,然后点击左上角的文件&#xff0c;点新建&#xff0c;点项目。如下图。 选择uniadmin&#xff0c;编写项目名&#xff0c;然后使用vue3 记得选用阿里云服务器&#xff0c;因为最便宜 点击创建&#xff0c;等待项目创…

2024年4月12日饿了么春招实习试题【第三题】-题目+题解+在线评测,2024.4.12,饿了么机试【Kruskal 算法, 最小生成树】

2024年4月12日饿了么春招实习试题【第三题】-题目题解在线评测&#xff0c;2024.4.12&#xff0c;饿了么机试 &#x1f3e9;题目一描述&#xff1a;样例1样例2解题思路一&#xff1a;[Kruskal 算法](https://baike.baidu.com/item/%E5%85%8B%E9%B2%81%E6%96%AF%E5%8D%A1%E5%B0%…

牛客网Java实战项目--仿牛客网社区的学习笔记

仿牛客网社区的学习笔记 1. 项目环境搭建1.1 开发社区首页 2.开发社区登录模块2.1 发送邮件2.2 开发注册功能2.3 会话管理2.4 生成验证码2.5 开发登录、退出功能2.6 显示登录信息 4 Redis实现点赞关注4.1 Spring整合Redis访问Redis的方法&#xff1a; 4.2 Redis实现点赞4.2.1 点…