在 FreeRTOS 中,事件标志组(Event Groups) 是一种用于任务间同步和事件管理的机制,允许任务等待多个事件的不同位组合(bitwise combinations)。以下是事件标志组相关的核心 API 函数及其动态创建和静态创建方式的详细说明:
1. 事件标志组的创建
(1) 动态创建事件标志组
EventGroupHandle_t xEventGroupCreate(void);
- 功能:动态分配内存并初始化一个事件标志组。
- 返回值:成功返回事件标志组句柄(
EventGroupHandle_t
),失败返回NULL
。 - 特点:
- 自动从 FreeRTOS 堆(heap)中分配内存。
- 无需手动释放内存(但需确保 FreeRTOS 堆空间足够)。
(2) 静态创建事件标志组
EventGroupHandle_t xEventGroupCreateStatic(StaticEventGroup_t *pxEventGroupBuffer);
- 功能:使用预分配的静态内存初始化一个事件标志组。
- 参数:
pxEventGroupBuffer
:指向用户分配的StaticEventGroup_t
类型的内存结构体。
- 返回值:成功返回事件标志组句柄,失败返回
NULL
。 - 特点:
- 需预先分配内存(通常是全局变量或静态变量)。
- 内存生命周期由用户管理。
2. 设置事件位
(1) 设置事件位(任务上下文)
EventBits_t xEventGroupSetBits(EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet);
- 功能:设置事件标志组中的指定位。
- 参数:
xEventGroup
:事件标志组句柄。uxBitsToSet
:要设置的位掩码(例如0x01
表示设置第 0 位)。
- 返回值:设置后的新事件位值。
- 注意:可能唤醒等待这些位的任务。
(2) 设置事件位(中断上下文)
BaseType_t xEventGroupSetBitsFromISR(
EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToSet,
BaseType_t *pxHigherPriorityTaskWoken
);
- 功能:在中断服务程序(ISR)中设置事件位。
- 参数:
xEventGroup
:事件标志组句柄。uxBitsToSet
:要设置的位掩码。pxHigherPriorityTaskWoken
:用于标记是否有高优先级任务被唤醒。
- 返回值:成功返回
pdPASS
,失败返回pdFAIL
。 - 注意:需使用
portYIELD_FROM_ISR()
手动触发上下文切换(如果需要)。
3. 清除事件位
(1) 清除事件位(任务上下文)
EventBits_t xEventGroupClearBits(EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear);
- 功能:清除事件标志组中的指定位。
- 参数:
xEventGroup
:事件标志组句柄。uxBitsToClear
:要清除的位掩码。
- 返回值:清除后的新事件位值。
(2) 清除事件位(中断上下文)
EventBits_t xEventGroupClearBitsFromISR(EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear);
- 功能:在中断服务程序(ISR)中清除事件位。
- 参数:同上。
- 返回值:操作成功返回
pdPASS
,否则pdFAIL
。
4. 等待事件位
EventBits_t xEventGroupWaitBits(
EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToWaitFor,
BaseType_t xClearOnExit,
BaseType_t xWaitForAllBits,
TickType_t xTicksToWait
);
- 功能:等待事件标志组中的指定位被设置。
- 参数:
xEventGroup
:事件标志组句柄。uxBitsToWaitFor
:要等待的位掩码。xClearOnExit
:是否在退出时清除这些位(pdTRUE
或pdFALSE
)。xWaitForAllBits
:是否等待所有位被设置(pdTRUE
表示“与”条件,pdFALSE
表示“或”条件)。xTicksToWait
:阻塞超时时间(单位:Tick,portMAX_DELAY
表示无限等待)。
- 返回值:满足条件的事件位值,超时返回
0
。
5. 获取当前事件位
EventBits_t xEventGroupGetBits(EventGroupHandle_t xEventGroup);
EventBits_t xEventGroupGetBitsFromISR(EventGroupHandle_t xEventGroup);
- 功能:获取当前事件标志组的值。
- 参数:事件标志组句柄。
- 返回值:当前事件位的值。
- 注意:
FromISR
版本用于中断上下文。
6. 删除事件标志组
void vEventGroupDelete(EventGroupHandle_t xEventGroup);
- 功能:删除动态创建的事件标志组,释放内存。
- 参数:事件标志组句柄。
动态 vs. 静态创建对比
特性 | 动态创建 | 静态创建 |
---|---|---|
内存分配 | 由 FreeRTOS 堆自动分配 | 用户预先分配内存 |
生命周期管理 | 自动释放(需调用 vEventGroupDelete ) | 用户手动管理内存 |
适用场景 | 临时或动态需求的事件标志组 | 长期存在或内存受限的系统 |
示例代码
动态创建和使用事件标志组:
// 创建事件标志组
EventGroupHandle_t xEventGroup = xEventGroupCreate();
// 任务中设置事件位
xEventGroupSetBits(xEventGroup, 0x01);
// 任务中等待事件位(等待第0位和第1位,任一位置1即唤醒)
EventBits_t uxBits = xEventGroupWaitBits(
xEventGroup,
0x03,
pdTRUE, // 退出时清除位
pdFALSE, // 任一位置1即可
portMAX_DELAY
);
静态创建事件标志组:
// 预先分配静态内存
StaticEventGroup_t xEventGroupBuffer;
EventGroupHandle_t xEventGroup = xEventGroupCreateStatic(&xEventGroupBuffer);
注意事项
- 事件位的位数:取决于
configUSE_16_BIT_TICKS
:- 若为
1
,事件位为 8 位(低 8 位有效)。 - 若为
0
,事件位为 24 位(低 24 位有效)。
- 若为
- 中断安全:在 ISR 中必须使用
FromISR
后缀的函数。 - 内存管理:静态创建需确保内存的持久性和正确对齐。
通过合理使用事件标志组,可以实现复杂的多任务同步逻辑,例如等待多个传感器数据就绪或组合触发条件。