事件标志组
一、概念
1、事件标志
事件是一种实现任务间通信的机制,主要用于实现多任务间的同步,但事件通信只能是事件类型的通信,无数据传输。与信号量不同的是,它可以实现一对多,多对多的同步。即一个任务可以等待多个事件的发生:可以是任意一个事件发生时唤醒任务进行事件处理;也可以是几个事件都发生后才唤醒任务进行事件处理。同样,也可以是多个任务同步多个事件。
事件标志可以简化成一个个flag标志,在学习阶段,我们常在全局定义一个flag变量来控制某个事件或功能。
例如:led点灯
c
uint8_t led_flag;
if (led_flag == 1)
{
led_open(); // 灯打开
}
else if (led_flag != 1)
{
led_close(); // 灯关闭
}
有个疑问?我都能直接通过flag控制,为什么我还需要用事件标志组?
答:全局变量固然是最快最直接的,但是考虑到安全问题,变量放在全局谁都可以访问,谁都可以修改,这就非常不安全,所以用事件标志组就可以避免这样的事情。事件标志组相比于全局变量有更加便利的功能,设定置位标准,更强的逻辑判断等功能。
2、事件标志组
事件标志组是由多个事件组成,保存事件组的状态。事件组存储在一个EventBits_t类型的变量中,该变量在事件组结构体中定义。
宏定义configUSE_16_BIT_TICKS:定义事件存储组大小的
configUSE_16_BIT_TICKS为1时,变量uxEventBits就是16位的,其中有8个位用来存储事件组

configUSE_16_BIT_TICKS定义为0,那么变量uxEventBits就是32位的, 其中有24个位用来存储事件组

在STM32中,我们一般将configUSE_16_BIT_TICKS定义为0,那么uxEventBits是32位的,有24个位用来实现事件标志组。每一位代表一个事件,任务通过"逻辑与"或"逻辑或"与一个或多个事件建立关联,形成一个事件组。
例如,如果一个事件组的值是0x92(二进制1001 0010),那么只有事件位1、4和7被设置,因此只有由1、4和7表示的事件发生。下图显示了EventBits_t类型的变量,它设置了事件位1、4和7,并清除了所有其他事件位,使事件组的值为0x92。

任务可以通过设置事件位来实现事件的触发和等待操作。FreeRTOS 的事件仅用于同步,不提供数据传输功能。
二、函数接口
1、头文件
c
#include "event_groups.h"
2、事件标志组创建
c
EventGroupHandle_t xEventGroupCreate(void)
- 函数说明:事件标志组创建,并用返回值的句柄对事件标志组操作。
- 参数:无
- 返回值:
- 成功:返回 事件标志组的句柄。
- 失败:返回 NULL。
3、事件标志组删除
c
void vEventGroupDelete( EventGroupHandle_t xEventGroup )
- 函数说明:用事件标志组句柄删除事件标志组。
- 参数:
xEventGroup:事件标志组的句柄
- 返回值:无
4、事件标志组指定事件置位
c
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToSet )
- 函数说明:用句柄指定某事件在某事件标志组的某个位置(记住宏定义
configUSE_16_BIT_TICKS的配置)。 - 参数:
xEventGroup:事件标志组的句柄uxBitsToSet:指定事件的标志位
- 返回值:
- 成功:返回调用
xEventGroupSetBits()时事件组中的值(uxBitsToSet的值)。 - 失败:没有失败返回值。注意:返回0(
pdPASS),会误以为是失败,其实是第0位被置位了,是正常现象,并没有失败。
- 成功:返回调用
- 例子:
为LED 设置事件标志组并将其设置在第0位
c
xEventGroupSetBits( xEventGroup_led, (1 << 0) ); // (1 << 0)可以通过这样快速选位置,不需要直接进行计算
5、事件标志组指定事件置位(中断)
c
BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToSet,
BaseType_t *pxHigherPriorityTaskWoken )
- 函数说明:用句柄指定某事件在某事件标志组的某个位置,该函数用在中断中。
- 参数:
xEventGroup:事件标志组的句柄uxBitsToSet:指定事件的标志位pxHigherPriorityTaskWoken:在使用之前必须初始化成pdFALSE。如果API函数(即xEventGroupSetBitsFromISR)导致一个任务解锁,并且解锁的任务优先级高于当前运行的任务,则API函数(即xEventGroupSetBitsFromISR)将pxHigherPriorityTaskWoken设置成pdTRUE。在中断退出前,触发一次任务切换。pxHigherPriorityTaskWoken作为一个可选参数,可以设置为NULL。
- 返回值:
- 成功:返回
pdPASS - 失败:返回
pdFAIL
- 成功:返回
6、等待事件标志组
c
EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToWaitFor,
const BaseType_t xClearOnExit,
const BaseType_t xWaitForAllBits,
TickType_t xTicksToWait )
- 函数说明:用句柄指定等待某事件标志组中某位或某几位置位。
- 参数:
xEventGroup:事件标志组的句柄uxBitsToWaitFor:指定等待的位置(事件),如果是多个位置 可以采取 与(|) 的方式。xClearOnExit:- 为
pdTRUE:在运行xEventGroupWaitBits函数之后,自动将uxBitsToWaitFor指定置位过的位置(事件)清除(复原)。举个例子:某个位置(事件)置位(flag 由0变为1),xEventGroupWaitBits函数触发之后,这个位置(事件)自动清除(flag由1变为0) - 为
pdFALSE:不会自动清除。
- 为
xWaitForAllBits:- 为
pdTRUE:触发逻辑是 逻辑与,即uxBitsToWaitFor中某个位置(事件)置位后,就会触发这个函数。 - 为
pdFALSE:触发逻辑是 逻辑或,即uxBitsToWaitFor中全部位置(事件)置位后,就会触发这个函数。
- 为
xTicksToWait:-最大超时时间,单位为系统节拍周期,常量portTICK_PERIOD_MS用于辅助把时间转换成 MS。当超过时间后,函数会往下执行,而不是阻塞。
- 返回值:函数在阻塞过程中,触发了的位置(事件)的数值。
- 例子:
等待LED 设置事件标志组,LED位置(位0)被触发。
c
#define BIT_0 (1 << 0)
EventBits_t bits;
bits = xEventGroupWaitBits(
eventGroup_led, // 事件标志组句柄
BIT_0, // LED事件在0位置
pdTRUE, // 自动清除
pdFALSE, // 逻辑与,有置位就触发
portMAX_DELAY); // 一直阻塞
if (bits & BIT_0) // 手动判断 是否是LED位置触发
{
// ... LED 触发后相关逻辑(如:灯亮)
}
7、事件标志组指定位置清零
c
EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToClear )
- 函数说明:用句柄指定某事件标志清除。
- 参数:
xEventGroup:事件标志组的句柄uxBitsToClear:指定事件的标志位
- 返回值:事件组未清除之前的值(状态)。
8、事件标志组指定位置清零(中断)
c
BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToClear )
- 函数说明:用句柄指定某事件标志清除,该函数用在中断。
- 参数:
xEventGroup:事件标志组的句柄uxBitsToClear:指定事件的标志位
- 返回值:
- 成功:返回
pdPASS - 失败:返回
pdFAIL
- 成功:返回
注意事项:
若使用xEventGroupSetBitsFromISR、xEventGroupClearBitsFromISR等函数,官方要求3个宏定义生效,详细代码如下:
c
#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToSet,
BaseType_t *pxHigherPriorityTaskWoken )
{
........................
}
BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear )
{
........................
}
需要将上面3个宏定义置位1。
注:以上均为学习笔记!