官网:
https://www.freertos.org/RTOS-task-notifications.html
从v8.2 版本开始的,
RTOS的每个任务都有一个32位通知值, 在创建RTOS任务时初始化为零,任务控制块中的成员变量ulNotifiedValue就是这个通知值。
向这个接受任务发送任务通知以后,就会解除这个任务的阻塞状态。
任务通知可以通过以下方式更新接收任务的通知值:
-
设置接收任务的通知值而不覆盖以前的值
-
覆盖接收任务的通知值
-
在接收任务的通知值中设置一个或多个位
-
增加接收任务的通知值
合理、灵活的使用上面这些更改任务通知值的方法可以在一些场合中替代队列、二值信号量、计数信号量和事件标志组。使用任务通知来实现二值信号量功能的时候,解除任务阻塞的时间比直接使用二值信号量要快45%,并且使用的RAM更少。
性能优势和使用限制
与可用于执行等效功能的其他FreeRTOS功能相比,任务通知具有速度和RAM占用空间优势。正如所料,这些好处需要一些用例限制:
-
只有当一个任务可以成为事件的接收者时,才能使用RTOS任务通知。然而,在大多数现实世界的应用中满足了这种条件。
-
仅在使用RTOS任务通知代替队列的情况下; 虽然接收任务可以等待处于阻止状态的通知(因此不消耗任何CPU时间),但是如果发送无法立即完成,则发送任务无法在阻塞状态下等待发送完成。
函数:
模拟二值信号量:
发送任务通知:
vTaskNotifyGiveFromISR(led1_task_handle, &xHigherPriorityTaskWokenSem);
当任务通知值被用作二进制或计数信号量等效时,被通知的任务应该使用ulTaskNotifyTake(),而不是xTaskNotifyWait()。
xTaskNotifyGive()是一个调用xTaskNotify()的宏,其eAction参数设置为eIncrement,导致所有调用返回pdPASS。
接受任务通知:
ulTaskNotifyTake(pdTRUE, portMAX_DELAY );
模拟计数型信号量:
创建信号量:xSemaphoreCreateCounting
发送任务通知:
xTaskNotifyGive( led2_task_handle ); //发送任务通知,返回值都是pdpass 获取一次任务通知就减1.
接受任务通知:
ulTaskNotifyTake(pdFALSE, portMAX_DELAY );
模拟消息邮箱
有很多限制:
1. 只能发送32位的数据值。
2. 消息被保存为任务的任务通知值,而且一次只能保存一个任务通知值,相当于队列长度为1.
发送数据:
* xTaskNotify() eAction设置为:eSetValueWithOverwrite/eSetValueWithoutOverwrite(覆盖或者不更新的区别)
读取任务通知值:
* xTaskNotifyWait()
xTaskNotify( led1_task_handle, led2_task_cnt , eSetValueWithOverwrite);
xTaskNotifyWait(0x00, / *不要清除条目上的任何通知位。* /
ULONG_MAX, / *退出时将通知值重置为0. * /
&ulNotifiedValue,/ *通知值传递出 ulNotifiedValue。* /
portMAX_DELAY); / *无限期阻止。* /
模拟事件
要使用 ULONG_MAX 要包含 #include “limits.h”。
设置位: xTaskNotify(led3_task_handle, BIT0, eSetBits);
xTaskNotify(led3_task_handle, BIT4, eSetBits);
xTaskNotifyWait(0x00, ULONG_MAX, &tmp, portMAX_DELAY);
if(tmp & BIT0)
{
printf(“event0 runging\r\n”);
}
if(tmp & BIT4)
{
printf(“event4 runging\r\n”);
}