FreeRTOS 直接任务通知取代事件组
在 FreeRTOS 中,任务之间的同步和通信有好几种方法,其中直接任务通知和事件组是最常用的两种。尽管直接任务通知有时可以替代事件组,但它们各有适用场景和优缺点需要详细讨论。
直接任务通知 vs 事件组
-
直接任务通知:
- 效率高:直接任务通知和任务控制块(TCB)关联,省了内存和处理开销。🐮
- 简单:API调用简单明了,适合解决一些简单的任务同步问题。😎
- 只限单任务哦:每个任务只能有一个通知值,不能直接等待多个事件组. 😕
-
事件组:
- 灵活:比较灵活的,可以让一个任务等待多个事件组,还能设定和清除多个标志位. 🎉
- 有点复杂啦:只适合解决比较复杂的任务同步和事件处理的麻烦事. 😅
- 消耗有点大:相比起直接任务通知,事件组需要更多的内存和处理时间,要啥啥都有. 😔
任务通知是一种简单的机制,用于任务间的同步和通信。通过使用 xTaskNotify()
发送通知给一个或多个任务,接收通知的任务可以使用 xTaskNotifyWait()
或 ulTaskNotifyTake()
等函数来等待通知。任务通知可以设置为二进制模式或计数模式,分别适用于不同的应用场景。它适用于轻量级的任务间通信和同步,因为它的实现相对简单,不需要依赖全局变量或队列。
事件组是一个更为灵活的任务同步机制,它管理了一个32位的位掩码,每个位代表一个事件。任务可以等待多个事件中的任何组合,当满足条件时,任务可以继续执行。通过 xEventGroupSetBits()
和 xEventGroupClearBits()
来设置和清除事件组的位,而可以通过 xEventGroupWaitBits()
或 xEventGroupSync()
等函数来等待特定的事件组合。事件组提供了更复杂的任务同步和通信功能,适用于需要处理多种任务间交互的场景,但相对于任务通知,可能需要更多的代码实现和一些性能开销。
示例:使用直接任务通知替代事件组
示例 Task2给Task1发送通知。
#include <Arduino.h>
// 定义任务通知值
#define NOTIFY_VALUE_1 (1 << 0)
#define NOTIFY_VALUE_2 (1 << 1)
// 任务句柄
TaskHandle_t Task1_Handle;
TaskHandle_t Task2_Handle;
// 任务1
void Task1(void *pvParameters) {
for (;;) {
// 等待任务通知
uint32_t notificationValue;
if(xTaskNotifyWait(0, NOTIFY_VALUE_1 | NOTIFY_VALUE_2, ¬ificationValue, portMAX_DELAY) == pdPASS) {
// 收到通知后执行任务
Serial.print("Task 1: 收到通知 值为: ");
Serial.println(notificationValue);
// 处理任务1
}
}
}
// 任务2
void Task2(void *pvParameters) {
for (;;) {
// 发送任务通知给任务1
xTaskNotify(Task1_Handle, NOTIFY_VALUE_2, eSetBits);
// 等待一段时间
delay(1000);
}
}
void setup() {
// 初始化串口
Serial.begin(115200);
// 创建任务1
xTaskCreate(Task1, "Task1", 10000, NULL, 1, &Task1_Handle);
// 创建任务2
xTaskCreate(Task2, "Task2", 10000, NULL, 1, &Task2_Handle);
}
void loop() {
// 等待一段时间
delay(1000);
}
总结
直接任务通知和事件组各有优缺点。直接任务通知高效、简单,但适用场景有限;事件组灵活、功能强大,但需要更多的内存和处理时间。