FreeRTOS中任务通知作为邮箱的使用
引言
在嵌入式系统开发中,任务间的通信是非常重要的一部分。FreeRTOS提供了多种任务间通信的方式,如队列、信号量、事件标志组等。然而,这些通信方式可能会带来一些额外的开销。为了提供一种更高效的通信方式,FreeRTOS引入了任务通知功能。任务通知可以被用作轻量级的邮箱,提供了一种高效的任务间通信方式。
任务通知简介
任务通知是FreeRTOS提供的一种轻量级的任务间通信方式。每个任务都有一个与之关联的32位无符号整数,该整数就是任务通知的值。任务可以等待其任务通知的值被设置,也可以检查其任务通知的值是否已经被设置。
任务通知作为邮箱的使用
任务通知的值可以被用作邮箱的值。使用xTaskNotify()
和xTaskNotifyFromISR()
函数可以将数据发送给任务。其中,函数的eAction
参数可以设置为eSetValueWithOverwrite
或eSetValueWithoutOverwrite
。如果eAction
设置为eSetValueWithOverwrite
,那么即使接收任务已经有一个通知待处理,接收任务的通知值也会被更新。如果eAction
设置为eSetValueWithoutOverwrite
,那么只有在接收任务没有待处理的通知时,接收任务的通知值才会被更新。
🚨需要注意xTaskNotifyFromISR()
它可以在中断服务例程(ISR)中被调用,而xTaskNotify()
函数不应该在中断服务例程(ISR)中被调用。这是因为xTaskNotify()
可能会导致上下文切换。如果在ISR中调用xTaskNotify()
并导致上下文切换,那么可能会出现未定义的行为。
相反,应该使用xTaskNotifyFromISR()
函数在ISR中发送任务通知。xTaskNotifyFromISR()
函数是专门为在ISR中使用而设计的,它可以安全地在ISR中调用,并且在返回到任务级别代码之前,会进行必要的上下文切换。
示例
在这个示例中,Task1
每秒发送一次任务通知给Task2
。Task2
则在接收到任务通知后,打印出通知的值。这就是如何使用FreeRTOS的任务通知作为邮箱的一个简单示例。
#include <Arduino.h>
#include <FreeRTOS.h>
// 定义任务句柄
TaskHandle_t Task1;
TaskHandle_t Task2;
void setup() {
// 创建任务
xTaskCreate(Task1code, "Task1", 10000, NULL, 1, &Task1);
xTaskCreate(Task2code, "Task2", 10000, NULL, 1, &Task2);
}
void loop() {
// 空循环
}
void Task1code(void * pvParameters) {
for (;;) {
// 使用任务通知发送数据
xTaskNotify(Task2, 0x01, eSetValueWithOverwrite);
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
void Task2code(void * pvParameters) {
uint32_t ulNotificationValue;
for (;;) {
// 等待接收任务通知
if (xTaskNotifyWait(0x00, 0xFFFFFFFF, &ulNotificationValue, portMAX_DELAY) == pdTRUE) {
// 当接收到任务通知时,处理数据
Serial.println("接收到任务通知,值为:" + String(ulNotificationValue));
}
}
}
结论
总的来说,FreeRTOS的任务通知作为轻量级邮箱的使用,可以提供一种高效的任务间通信方式。但在使用时,需要考虑其局限性,以确保其适用于特定的应用场景。希望本文能够帮助你理解如何在FreeRTOS中使用任务通知作为邮箱,以及如何根据实际需求选择合适的任务间通信方式。
参考文献
FreeRTOS官方文档:任务通知
FreeRTOS官方文档:任务通知作为轻量级二值信号量