【FreeRTOS基础入门】事件组与同步点

文章目录

  • 前言
  • 一、事件组是什么
    • 案例
    • 1.1 事件组的概念
  • 二、事件组的操作
    • 2.1 事件组与其他实现同步与互斥方法的区别
    • 2.2 创建事件组
    • 2.3 删除事件组
    • 2.4 设置事件
    • 2.5 等待事件
    • 2.6 示例代码
  • 三、同步点
    • 3.1 同步点是什么
    • 3.2 设置同步点
  • 总结


前言

FreeRTOS是一个广泛应用于嵌入式系统的实时操作系统内核,提供了丰富的功能和组件,以帮助开发者构建可靠的嵌入式应用程序。其中,事件组(Event Groups)是一种重要的机制,用于任务之间的事件通知和同步。本文将重点介绍FreeRTOS中事件组的基础知识,以帮助初学者更好地理解和应用这一功能。

在嵌入式系统中,多个任务可能需要协同工作,彼此之间需要进行事件通知和同步。事件组提供了一种有效的方式来管理和触发事件,从而实现任务之间的同步与通信。通过学习事件组的概念、使用方法以及实际应用场景,开发者可以更好地设计和实现复杂的嵌入式系统。


一、事件组是什么

案例

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

  • 张三:我到了
  • 李四:我到了
  • 王五:我到了
    组长说:好,大家都到齐了,出发!
    秋游回来第二天就要提交一篇心得报告,组长在焦急等待:张三、李四、王五谁先写好就交谁的。
    在这个日常生活场景中:
  • 出发:要等待这 3 个人都到齐,他们是"与"的关系
  • 交报告:只需等待这 3 人中的任何一个,他们是"或"的关系
    在 FreeRTOS 中,可以使用事件组(event group)来解决这些问题。

1.1 事件组的概念

在这里插入图片描述

事件组可以简单的认为就是一个整数,你可以去设置整数的某一位为1代表有事件,设置0为无事件。
你可以去等待一个位或者多个位
下面的为事件组结构体:

typedef struct xEventGroupDefinition
{
	EventBits_t uxEventBits;
	List_t xTasksWaitingForBits;		/*< List of tasks waiting for a bit to be set. */

	#if( configUSE_TRACE_FACILITY == 1 )
		UBaseType_t uxEventGroupNumber;
	#endif

	#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
		uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the event group is statically allocated to ensure no attempt is made to free the memory. */
	#endif
} EventGroup_t;

在这里插入图片描述

其中:uxEventBits成员为事件组,xTasksWaitingForBits用来存储等待事件的任务

事件组用一个整数来表示,其中的高 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 位

二、事件组的操作

2.1 事件组与其他实现同步与互斥方法的区别

事件组和队列、信号量等不太一样,主要集中在 2 个地方:
 唤醒谁?
 队列、信号量:事件发生时,只会唤醒一个任务
 事件组:事件发生时,会唤醒所有符号条件的任务,简单地说它有"广播"的
作用
 是否清除事件?
 队列、信号量:是消耗型的资源,队列的数据被读走就没了;信号量被获取后就减少了
在这里插入图片描述

 事件组:被唤醒的任务有两个选择,可以让事件保留不动,也可以清除事件以上图为列,事件组的常规操作如下:
 先创建事件组
 任务 C、D 等待事件:
 等待什么事件?可以等待某一位、某些位中的任意一个,也可以等待多位。
简单地说就是"或"、"与"的关系。
 得到事件时,要不要清除?可选择清除、不清除。
 任务 A、B 产生事件:设置事件组里的某一位、某些位

2.2 创建事件组

我们可以使用下面这个函数进行动态的创建事件组

EventGroupHandle_t xEventGroupCreate( void );

他返回的是一个事件组的handle

我们也可以加个static表示要创建静态的事件组

EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t * pxEventGroupBuffer );

你只需要提供事件组的Buffer即可。

2.3 删除事件组

我们可以使用下面这个函数删除一个事件组:

void vEventGroupDelete( EventGroupHandle_t xEventGroup );

参数为要删除事件组的handle

2.4 设置事件

在任务中,你可以使用下面这个函数进行设置某一位:

EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,
 const EventBits_t uxBitsToSet );

参数二怎么填写?
他的定义是这样的:typedef TickType_t EventBits_t;类型就是uint32_t,如果你设置的是32位的话
我们可以来让他的某一个位为1,代表这个位有事件了
比如我们想让第5位就这样:1<<5,如果想要两个就使用1 << 5 | 1 << 4,使用或运算符

如果你需要在中断中使用,函数名称只需要加个ISR

BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, 
const EventBits_t uxBitsToSet, 
BaseType_t *pxHigherPriorityTaskWoken );

他的参数3用来告诉调用者,在设置事件组位的过程中是否有更高优先级的任务被唤醒了。
因此,当你调用 xEventGroupSetBitsFromISR 函数时,如果有更高优先级的任务被唤醒了,那么 pxHigherPriorityTaskWoken 参数会被设置为非零值;如果没有更高优先级的任务被唤醒,那么 pxHigherPriorityTaskWoken 参数会被设置为零。这样,在 ISR 结束后,FreeRTOS 就知道是否需要进行任务切换。

2.5 等待事件

我们可以使用下面这个函数来等待某个事件:

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

参数2意义为等待哪些位。参数3为是否在这个函数结束时清楚等待位。参数4为,如果你的参数2等待了多个位,比如0和5,是否要等待这两个位全部有了事件在唤醒任务,还是任意一个都行,他们可以填pdTRUE或者pdFLASE

2.6 示例代码

#include "FreeRTOS.h"
#include "task.h"
#include "event_groups.h"

// 定义事件组句柄
EventGroupHandle_t xEventGroup;

// 定义事件组位
#define BIT_0 (1 << 0)
#define BIT_1 (1 << 1)

// 任务1,等待事件组位 BIT_0
void vTask1(void *pvParameters) {
    while (1) {
        // 等待事件组位 BIT_0,设置 clear_on_exit 标志位,表示等待后清除
        EventBits_t uxBits = xEventGroupWaitBits(xEventGroup, BIT_0, pdTRUE, pdFALSE, portMAX_DELAY);
        if (uxBits & BIT_0) {
            // 收到 BIT_0 位的信号
            // 执行相应操作...
        }
    }
}

// 任务2,等待事件组位 BIT_1
void vTask2(void *pvParameters) {
    while (1) {
        // 等待事件组位 BIT_1,设置 clear_on_exit 标志位,表示等待后清除
        EventBits_t uxBits = xEventGroupWaitBits(xEventGroup, BIT_1, pdTRUE, pdFALSE, portMAX_DELAY);
        if (uxBits & BIT_1) {
            // 收到 BIT_1 位的信号
            // 执行相应操作...
        }
    }
}

// 主函数
int main(void) {
    // 创建事件组
    xEventGroup = xEventGroupCreate();

    // 创建任务1,优先级较高
    xTaskCreate(vTask1, "Task 1", configMINIMAL_STACK_SIZE, NULL, 2, NULL);

    // 创建任务2,优先级较低
    xTaskCreate(vTask2, "Task 2", configMINIMAL_STACK_SIZE, NULL, 1, NULL);

    // 启动调度器
    vTaskStartScheduler();

    // 如果调度器启动失败,进行错误处理
    for (;;);

    return 0;
}

三、同步点

3.1 同步点是什么

有一个事情需要多个任务协同,比如:
 任务 A:炒菜
 任务 B:买酒
 任务 C:摆台
 A、B、C 做好自己的事后,还要等别人做完;大家一起做完,才可开饭
同步点就是如果你做好了,你需要等待其他和你一起干这个事情的任务,如果没有做完就接着做,直到做完,当需要同步的任务都ok了,就进行下一步的执行,少一个没做完都不行

3.2 设置同步点

我们可以使用下面这个函数设置一个同步点:

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

参数2为你要设置哪些事件,表示你完成了这个事件
参数3表示你要等待哪些事件完成。
当你设置的参数3事件都ok之后,他就会往下走


总结

事件组作为FreeRTOS的一个重要特性,为嵌入式系统的开发提供了强大的事件管理机制。通过使用事件组,开发者可以轻松地实现任务之间的事件通知和同步,提高系统的灵活性和效率。在实际应用中,合理利用事件组可以简化任务之间的协作逻辑,使系统更加可靠和稳定。希望本文能够为初学者提供一个清晰的入门指南,让大家更好地利用FreeRTOS的事件组功能进行嵌入式开发。

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

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

相关文章

我的第一个浏览器插件网页一键上传的开发历史

前言 一键上传选中的网页内容&#xff0c;实现知识快速收藏。如飞书剪存&#xff0c;有道云剪报&#xff0c;MrDoc速记。早在2008年&#xff0c;我参考了有道云一键上传&#xff0c;实现了一个简单的浏览器插件&#xff0c;能方便保存网页内容到个人网站。这些插件目前都很难兼…

Day32 进程Process

文章目录 1.什么是进程1.1 概念1.2 特点1.3 进程段1.4 进程分类1.5 进程状态1.6 进程状态切换图1.7 调度进程 2.进程函数接口2.1 创建进程 fork()2.2 回收资源函数2.3 结束进程2.4 获取进程号 3.exec函数族&#xff08;了解&#xff09;4.守护进程 Daemon4.1 守护进程的特点4.2…

提升技术栈的秘诀:Spring Cloud学习网站带你飞跃职业瓶颈!

介绍&#xff1a;Spring Cloud是一个基于Spring Boot实现的微服务架构开发工具集。 Spring Cloud利用Spring Boot的开发便利性简化了分布式系统基础设施的开发。例如&#xff0c;服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等都是其内置的功能。它的优势包括…

LangChain支持哔哩哔哩视频总结

是基于LangChain框架下的开发&#xff0c;所以最开始请先 pip install Langchain pip install bilibili-api-python 技术要点&#xff1a; 使用Langchain框架自带的Document loaders 修改BiliBiliLoader的源码&#xff0c;自带的并不支持当前b站的视频加载 源码文件修改&a…

前端架构: 实现脚手架终端UI样式之ANSI escape code, Chalk, Ora介绍

在脚手架当中实现命令行的UI显示 1 &#xff09;概述 在命令行中&#xff0c;如果想实现除传统的常规文本以外的内容比如想对字体进行加粗斜体下划线&#xff0c;包括对它改变颜色改变前景色改变后景色等等需要借助一个叫做 ANSI escape code 这样的一个概念它其实是一个标准&…

文献速递:GAN医学影像合成--基于生成对抗网络的肺部图像分类的多域医学图像翻译生成

文献速递&#xff1a;GAN医学影像合成–基于生成对抗网络的肺部图像分类的多域医学图像翻译生成 01 文献速递介绍 在2019年底&#xff0c;一种称为2019冠状病毒病&#xff08;COVID-19&#xff09;的新型冠状病毒肺炎出现&#xff0c;迅速成为全球性大流行。感染COVID-19可以…

18.贪心算法

排序贪心 区间贪心 删数贪心 统计二进制下有多少1 int Getbit_1(int n){int cnt0;while(n){nn&(n-1);cnt;}return cnt; }暴力加一维前缀和优化 #include <iostream> #include <climits> using namespace std; #define int long long const int N2e510; in…

热门游泳耳机哪个牌子好,吐血整理全网高口碑机型!

近年来&#xff0c;游泳已经成为众多人们喜爱的运动项目之一。而在游泳过程中&#xff0c;许多人希望能够享受到音乐的陪伴&#xff0c;以增加运动的乐趣。然而&#xff0c;由于阻力、防水和水压等问题&#xff0c;传统的耳机并不能满足游泳者的需求。因此&#xff0c;在市面上…

基于JAVA+SpringBoot+Vue的前后端分离的电子商城

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目背景介绍&#xff1a; 在当今数字化时代&…

bat判断vmware 是否已安装

要通过批处理脚本&#xff08;.bat&#xff09;判断VMware是否已安装&#xff0c;您可以尝试以下方法&#xff1a; 检查VMware的进程 您可以检查VMware相关的进程是否在运行。例如&#xff0c;VMware Workstation的进程名通常是vmware-workstation.exe。 echo off tasklist /…

计网 - 域名解析的工作流程

文章目录 Pre引言1. DNS是什么2. 域名结构3. 域名解析的工作流程4. 常见的DNS记录类型5. DNS安全6. 未来的发展趋势 Pre 计网 - DNS 域名解析系统 引言 在我们日常使用互联网时&#xff0c;经常会输入各种域名来访问网站、发送电子邮件或连接其他网络服务。然而&#xff0c;我…

【命令行工具kubectl】

如何在k8s的任意节点使用用kubectl # 正常在node节点上是无法执行kubectl命令 [rootk8s-node-01 ~]# kubectl get pods The connection to the server localhost:8080 was refused - did you specify the right host or port?1、将master节点中/etc/kubernetes/,admin.conf拷…

性能分析5部曲:瓶颈分析与问题定位,如何快速解决瓶颈?

一、引言 很多做性能测试的同学都问过我这样一个问题&#xff1a;鱼哥(Carl_奕然)&#xff0c;你说性能测试的重点是什么? 我的回答很简单&#xff1a;瓶颈分析与问题定位。 在性能项目的整个周期&#xff0c;不管是脚本设计&#xff0c;脚本编写还是脚本执行&#xff0c;都…

fastjson解析自定义get方法导致空指针问题

背景 为了在日志中把出入参打印出来&#xff0c;以便验证链路和排查问题&#xff0c;在日志中将入参用fastjson格式化成字符串输出&#xff0c;结果遇到了NPE。 问题复现 示例代码 public static void main(String[] args) {OrganizationId orgId new OrganizationId();N…

Nginx -2

接着上文写 5.4.7 验证模块 需要输入用户名和密码 模块名称&#xff1a;ngx_http_auth_basic_module 访问控制基于模块 ngx_http_auth_basic_module 实现&#xff0c;可以通过匹配客户端资源进行限制 语法&#xff1a; Syntax: auth_basic string | off; Default: auth_ba…

RK3568平台开发系列讲解(Linux系统篇)编写I2C客户端驱动程序

🚀返回专栏总目录 文章目录 一、定义和注册I2C驱动程序二、在设备树中实例化I2C设备——新方法三、总结沉淀、分享、成长,让自己和他人都能有所收获!😄 配置I2C设备基本上分为两个步骤。 定义并注册I2C驱动程序定义并注册I2C设备在DT中,I2C设备属于非存储器映射设备系列…

MySQL报错:sql_mode=only_full_group_by解决方法

Linux环境 ubuntu 22.04 MySQL是8.0.35版本 问题描述 Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column auth_system.t_class_temp_config.id which is not functionally dependent on columns in GROUP BY clause; this is inco…

OOTDiffusion:一个开源可控的虚拟服装试穿工具,效果接近商用!

目录 前言介绍 主要功能 相关链接 安装部署 效果展示 前言介绍 继谷歌推出了Tryon Diffusion,阿里推出了Outfit Anything, 亚马逊也推出了Diffuse to Choose。至此几大头部电商也都在虚拟试衣技术上完成了布局。基于扩散模型的技术基本已经成为现在主流应…

2024最佳住宅代理IP服务商推荐

跨境出海已成为了近几年的最热趋势&#xff0c;大批量的企业开始开拓海外市场&#xff0c;而海外电商领域则是最受欢迎的切入口。新兴的tiktok、Temu&#xff0c;老牌的Amazon、Ebay&#xff0c;热门的Etsy、Mecari等等都是蓝海一片。跨境入门并不难&#xff0c;前期的准备中不…

Leetcoder Day18| 二叉树 part07

语言&#xff1a;Java/Go 今天做了一个小决定&#xff0c;如果时间不够的话&#xff0c;可以先看go去找工作&#xff0c;所以现在加上用go去刷题 530.二叉搜索树的最小绝对差 给你一棵所有节点为非负值的二叉搜索树&#xff0c;请你计算树中任意两节点的差的绝对值的最小值。…