首页 > 编程语言 >【FreeRTOS】事件组 event group(附源码)

【FreeRTOS】事件组 event group(附源码)

时间:2024-06-12 09:57:49浏览次数:17  
标签:group FreeRTOS 16 任务 源码 事件 设置 xEventGroup NULL

引言:事件组是一种用于同步多个任务之间的状态和行为的机制。在操作系统中,事件组通常由操作系统提供,用于实现任务间的通信和同步。
事件组通常包含一组独立的事件或标志,每个事件或标志都可以表示一种特定的状态或条件。任务可以等待事件组中的一个或多个事件被设置,也可以设置、清除或检查事件组中的事件状态。

1.事件组的概念

首先我们先用生活中的实例来举例一下什么是事件组,春游三个同学,三个同学一起出发前需要相互等待,这个出发就是的关系,三个同学春游之后需要交报告,这个报告就是的关系,其中一个人交即可,在FreeRTOS中,事件组event group可以解决上述的问题。

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

  • 的每一位表示一个事件
  • 每一位事件的含义由程序员决定,比如: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 位

事件组的操作:

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

1.唤醒谁?

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

2.是否清除事件?

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

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

先创建事件组,

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

任务A、B产生事件:设置事件组里的某一位、某些位

2.事件组的函数

创建:

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

删除:

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

设置事件:

可以设置事件组的某个位、某些位,使用的函数有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。

等待事件:

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",非阻塞条件,或称为"非阻塞条件成立";当"非阻塞条件成 立"后,该任务就可以变为就绪态。

3.示例:等待多个事件

要使用事件组,代码中要有如下操作:

* 1. 工程中添加event_groups.c */
/* 2. 源码中包含头文件 */
##include "event_groups.h"

假设大厨要等手下做完这些事才可以炒菜:洗菜、生火。
本程序创建3个任务:

  • 任务1:洗菜
  • 任务2:生火
  • 任务3:炒菜。

main函数代码如下,它创建了3个任务:

int main( void )
{
 prvSetupHardware();
 
    /* 创建递归锁 */
    xEventGroup = xEventGroupCreate( );
 if( xEventGroup != NULL )
 {
 /* 创建3个任务: 洗菜/生火/炒菜
 */
 xTaskCreate( vWashingTask, "Task1", 1000, NULL, 1, NULL );
 xTaskCreate( vFiringTask,  "Task2", 1000, NULL, 2, NULL );
 xTaskCreate( vCookingTask, "Task3", 1000, NULL, 3, NULL );
 /* 启动调度器 */
 vTaskStartScheduler();
 }
 else
 {
 /* 无法创建事件组 */
 }
 /* 如果程序运行到了这里就表示出错了, 一般是内存不足 */
 return 0;
}

标签:group,FreeRTOS,16,任务,源码,事件,设置,xEventGroup,NULL
From: https://blog.csdn.net/weixin_64593595/article/details/139593698

相关文章

  • 龙哥量化:通达信一线一柱主图指标公式源码
    如果您需要代写公式,请联系我。龙哥QQ:591438821龙哥微信:Long622889 {指标介绍:线上买、线下卖;柱上买、柱下卖;线优先于柱。}X_1:=FILTER(ABS(HIGH-REF(CLOSE,1))/REF(CLOSE,1)>0.05,10);STICKLINE(CLOSE,REF(IF(HIGH<REF(LOW,1),REF(LOW,1),HIGH),BARSLAST(X_1)),REF(LOW,BAR......
  • 龙哥量化:通达信状元指标公式源码
    如果您需要代写公式,请联系我。龙哥QQ:591438821龙哥微信:Long622889 VAR2X:=(CLOSE-LLV(LOW,9))/(HHV(HIGH,9)-LLV(LOW,9))*100;VAR3X:=SMA(VAR2X,4,1);VAR4X:=SMA(VAR3X,2,1);VAR5X:=SMA(VAR4X,2,1);VAR7:=crOSS(VAR4X,VAR5X)ANDVAR4X<35;VAR8:=VAR7AND vol>REF(VOL,1)*......
  • TimerWheel(计时轮)在Rust中的实现及源码解析
    计时器轮(TimerWheel),模拟时钟格式组成的高效计时器TimerWheel算法原理环形数据结构:TimerWheel,即时间轮,是一个环形的数据结构,类似于时钟的面,被等分为多个格子或槽位(slot)。槽位时间间隔:每个槽位代表一个固定的时间间隔,例如1毫秒、1秒等。这个时间间隔决定了定时器的精度。......
  • 龙哥量化:通达信空信号,可以买入翻倍的指标公式源码
    如果您需要代写公式,请联系我。龙哥QQ:591438821龙哥微信:Long622889  {当多空线上穿0轴以后并且沿着45度向上运行时可视为有效突破,此时的信号可视为有效信号。信号出现在平台盘整期间,或者是小多头回调之后向上拉升之际,此时的信号最为有效,其它时间的信号要仔细辨别,下跌趋势......
  • 龙哥量化:通达信筹码操盘,筹码来的副图源码
    如果您需要代写公式,请联系我。龙哥QQ:591438821龙哥微信:Long622889 DRAWGBK(ISLASTBAR,RGB(60,60,60),RGB(0,0,0),0,'0',0);机构控盘区:160,COLORMAGENTA,LINETHICK1;DRAWTEXT(ISLASTBAR,机构控盘区,'--←机构控盘区'),COLORMAGENTA;主升浪:150,COLORRED,LINETHICK1......
  • 龙哥量化:通达信决胜千里主图指标公式源码
    如果您需要代写公式,请联系我。龙哥QQ:591438821龙哥微信:Long622889B1:=EMA(C,2);紫1:=EMA(B1,2)COLORMAGENTA;色1:=EMA(紫1,2)COLORMAGENTA;线1:=EMA(色1,2)COLORMAGENTA;浮盈线:=EMA(紫1,5)COLORLIMAGENTA,LINETHICK2;成本线:=EMA(色1,13)COLORYELLOW,LINETHICK2;限时:=1;重......
  • 龙哥量化:诺曼底防线副图指标公式源码
    如果您需要代写公式,请联系我。龙哥QQ:591438821龙哥微信:Long622889VAR1:=(HHV(H,13)-LLV(L,13));VAR2:=(HHV(H,13)-C);VAR3:=(C-LLV(L,13));VAR4:=VAR2/VAR1*100-70;VAR5:=(C-LLV(L,55))/(HHV(H,55)-LLV(L,55))*100;VAR6:=(2*C+H+L)/4;VAR7:=SMA((VAR3/VAR1*100),3,1);VAR8:=......
  • 短视频评论截流源码开发思路C#
    源码图镇帖一:准备工作这里我们采用了云技术,并不是通过客户端进行评论数据提取1.1:UI自动操作技术UI自动操作技术,顾名思义就是无需人工干预通过代码的方式让软件进行模拟人工操作,认为是脚本也好什么都可以。这和脚本还不一样,这里就不细说了。为什么获取短视频评论需要自动......
  • 行行比较,高逼格的SQL写法!【送源码】
    环境准备数据库版本:MySQL5.7.20-log建表SQLDROPTABLEIFEXISTS`t_ware_sale_statistics`;CREATETABLE`t_ware_sale_statistics`(`id`bigint(20)NOTNULLAUTO_INCREMENTCOMMENT'主键id',`business_id`bigint(20)NOTNULLCOMMENT'业务机构编码',......
  • 温泉镇旅游微信小程序的设计与实现(论文+源码)_kaic
    摘要旅游业随着经济的快速发展呈现出一派欣欣向荣的景象,尤其是近两年来,各个行业运用科技以及因特网来促进旅游迅速发展,逐渐都显示出了的问题,特别突出的是在线上推广,其缺点也是特别明显。尽管在新冠肺炎的冲击下,许多重要的旅游胜地和娱乐场所都被关闭,但是我认为,在未来,我国会在......