FreeRTOS事件组(Event Group)
1. 概念定位
对比维度 | 事件组 | 信号量 (Semaphore) | 消息队列 / 流 |
---|---|---|---|
核心目的 | 多位、广播式同步 | 互斥 / 计数 | 传递数据并同步 |
粒度 | 最多 24 位用户位 | 1 次 1 令牌 | 任意字节 / 项 |
等待条件 | 任意位 AND / OR | 获取令牌 | 取到数据 |
唤醒范围 | 满足条件的所有任务 | 每次唤醒 1 任务 | 每条数据唤醒 1 任务 |
适用场景:
- 多个任务需要对 同一事件 作出反应;
- 单个任务需等待 多种条件 同时满足;
- 不想用轮询,且要兼顾低功耗睡眠。
2. 数据结构
32-bit 标志字
┌───────┬───────────┬────────────┐
│ 系统位 │ 控制位 │ 用户位0-23 │
└───────┴───────────┴────────────┘
- 0-23 位:用户自定义事件;
- 高 8 位:FreeRTOS 内部使用(禁写)。
xEventGroupCreate()
动态创建(≈40 B);也可用 xEventGroupCreateStatic()
静态创建。
3. 关键 API
类别 | 原型 | 说明 |
---|---|---|
创建/删除 | xEventGroupCreate() vEventGroupDelete() | 删除前必须确保没有任务仍在等待 |
设置/清除位 | xEventGroupSetBits() xEventGroupClearBits() | 中断中用 …FromISR 版本 |
等待 | xEventGroupWaitBits(h,bits,clear,onAll,timeout) | clear =pdTRUE 时自动清零触发位; onAll =pdTRUE 为 AND,否则 OR |
同步屏障 | xEventGroupSync() | 多任务“栅栏” |
查询 | xEventGroupGetBits() | 非阻塞读取当前标志字 |
ISR 中 只能 调
SetBitsFromISR / ClearBitsFromISR
,不能Wait
。
4. 常见模式
4.1 AND 等待(所有子系统就绪)
enum { WIFI_OK = BIT0, AFE_OK = BIT1, CLOUD_OK = BIT2 };xEventGroupWaitBits(evt,WIFI_OK | AFE_OK | CLOUD_OK,pdFALSE, // 保留位pdTRUE, // 等全部portMAX_DELAY);
4.2 OR 等待(任一事件即唤醒)
EventBits_t bits = xEventGroupWaitBits(evt,BIT0 | BIT1 | BIT2,pdTRUE, // 自动清零触发位pdFALSE, // 任意即可pdMS_TO_TICKS(1000));
4.3 广播唤醒
同一位被 SetBits
,所有等待该位的任务都会被唤醒。
5. 性能与功耗
- O(1) 设置/清除;
- 任务真正阻塞于内核队列,可进入浅睡;
- 每组对象仅 ~40 B 堆内存。
6. 设计注意
- 仅使用 0-23 位;常量要
& 0x00FFFFFFu
; clearOnExit
在任务被唤醒后执行清零;- 多任务手动清同一位需自管同步;
- 中断里别频繁 “Set→Clear”,可合并事件。
7. POSIX 对照
POSIX 同类对象 | FreeRTOS 对应 |
---|---|
pthread_cond + mutex | EventGroup |
pthread_barrier | xEventGroupSync |
小结示例
event_group_ = xEventGroupCreate();// Wi-Fi 任务
xEventGroupSetBits(event_group_, WIFI_OK);// 统筹任务
xEventGroupWaitBits(event_group_,WIFI_OK | AFE_OK,pdFALSE,pdTRUE,pdMS_TO_TICKS(5000));
这样就能用一次 O(1) 操作完成多事件同步,比轮询或多个信号量更简洁高效。