一、概念
(1)FreeRTOS从V8.2.0版本开始提供任务通知
(2)每个任务都有一个32位的通知值
(3)发送任务通知的几种情况
3.1 发送通知给任务,如果有通知未读,不覆盖通知值
3.2 发送通知给任务,直接覆盖通知值
3.3 发送通知给任务,设置通知值的一个或多个位,可以当做事件组来使用
3.4 发送通知给任务,递增通知值,可以当做计数信号量来使用
(4)只能有一个任务接收通知消息
(5)只有等待通知的任务可以被阻塞
(6)无需创建,属于任务控制块中的变量,创建任务时即创建完成
(7)中断/任务均能发送通知
(8)只有任务可以等待通知,而不允许中断中等待通知
(9)相较于传统方式性能快
(10)使用时需要使能configUSE_TASK_NOTIFICATIONS宏定义
二、使用函数
(1)xTaskNotifyGive发送通知,没有通知值(信号量类型)
(2)xTaskNotify发送通知,带通知值
(3)xTaskNotifyAndQuery发送通知,带通知值,并返回原通知值
(4)ulTaskNotifyTake等待通知(信号量类型)
(5)xTaskNotifyWait等待通知
(6)vTaskNotifyGiveFromISR中断版本的xTaskNotifyGive
(7)xTaskNotifyAndQueryFromISR中断版本的xTaskNotifyAndQuery
(8)xTaskNotifyFromISR中断版本的ulTaskNotifyTake
(9)xTaskNotifyStateClear清除所有未读消息
三、代码示例
(1)任务通知代替消息队列
#include "FreeRTOS.h"
#include "task.h"
#include "led.h"
#include "limits.h"
static void task1(void* param);
static void task2(void* param);
static TaskHandle_t task1Handler;
static TaskHandle_t task2Handler;
int main()
{
led_init();
portENTER_CRITICAL(); //进入临界区
BaseType_t xReturn;
/******创建任务1*******/
xReturn = xTaskCreate(task1,
"task1",
128,
NULL,
2,
&task1Handler);
if(xReturn==pdTRUE){}
/******创建任务2*******/
xReturn = xTaskCreate(task2,
"task2",
128,
NULL,
2,
&task2Handler);
if(xReturn==pdTRUE){}
portEXIT_CRITICAL(); //退出临界区
vTaskStartScheduler(); //开启任务调度器
while(1){
}
}
//发送消息
void task1(void* param)
{
BaseType_t xReturn = pdPASS;
uint32_t value1 = 1;
uint32_t value2 = 2;
while(1){
xReturn = xTaskNotify(task2Handler, //向哪个任务发送通知
value1, //发送的值
eSetValueWithOverwrite); //写入值方式
if(xReturn==pdTRUE){
vTaskDelay(1000);
}
xReturn = xTaskNotify(task2Handler, //向哪个任务发送通知
value2, //发送的值
eSetValueWithOverwrite); //写入值方式
if(xReturn==pdTRUE){
vTaskDelay(1000);
}
}
}
//接收消息
void task2(void* param)
{
BaseType_t xReturn;
uint32_t recv;
while(1){
xReturn = xTaskNotifyWait(0x0, //进入时要清除的位
ULONG_MAX, //退出时要清除的位,清除所有位
&recv, //接收的值
portMAX_DELAY); //等待超时时间
if(recv == 1 && xReturn==pdTRUE){
open();
}else if(recv == 2 && xReturn==pdTRUE){
close();
}
}
}
(2)任务通知替换二值信号量
#include "FreeRTOS.h"
#include "task.h"
#include "led.h"
#include "limits.h"
static void task1(void* param);
static void task2(void* param);
static TaskHandle_t task1Handler;
static TaskHandle_t task2Handler;
int main()
{
led_init();
portENTER_CRITICAL(); //进入临界区
BaseType_t xReturn;
/******创建任务1*******/
xReturn = xTaskCreate(task1,
"task1",
128,
NULL,
2,
&task1Handler);
if(xReturn==pdTRUE){}
/******创建任务2*******/
xReturn = xTaskCreate(task2,
"task2",
128,
NULL,
2,
&task2Handler);
if(xReturn==pdTRUE){}
portEXIT_CRITICAL(); //退出临界区
vTaskStartScheduler(); //开启任务调度器
while(1){
}
}
//发送消息
void task1(void* param)
{
while(1){
xTaskNotifyGive(task2Handler);
vTaskDelay(500);
}
}
//接收消息
void task2(void* param)
{
static int ledcnt=0;
while(1){
ulTaskNotifyTake(pdTRUE,portMAX_DELAY);
ledcnt=!ledcnt;
if(ledcnt==1){
open();
}else if(ledcnt==0){
close();
}
}
}
(3)任务通知代替计数信号量
#include "FreeRTOS.h"
#include "task.h"
#include "led.h"
#include "limits.h"
static void task1(void* param);
static void task2(void* param);
static TaskHandle_t task1Handler;
static TaskHandle_t task2Handler;
int main()
{
led_init();
portENTER_CRITICAL(); //进入临界区
BaseType_t xReturn;
/******创建任务1*******/
xReturn = xTaskCreate(task1,
"task1",
128,
NULL,
2,
&task1Handler);
if(xReturn==pdTRUE){}
/******创建任务2*******/
xReturn = xTaskCreate(task2,
"task2",
128,
NULL,
2,
&task2Handler);
if(xReturn==pdTRUE){}
portEXIT_CRITICAL(); //退出临界区
vTaskStartScheduler(); //开启任务调度器
while(1){
}
}
//发送消息
void task1(void* param)
{
while(1){
xTaskNotifyGive(task2Handler);
vTaskDelay(500);
}
}
//接收消息
void task2(void* param)
{
static int ledcnt=0;
uint32_t retu=0;
while(1){
retu = ulTaskNotifyTake(pdFALSE,0);
if(retu==1) ledcnt=!ledcnt;
if(ledcnt==1){
open();
}else if(ledcnt==0){
close();
}
}
}
(4)任务通知替代事件组
#include "FreeRTOS.h"
#include "task.h"
#include "led.h"
#include "limits.h"
static void task1(void* param);
static void task2(void* param);
static TaskHandle_t task1Handler;
static TaskHandle_t task2Handler;
#define EVENT1 (0x01<<1)
#define EVENT2 (0x01<<2)
int main()
{
led_init();
portENTER_CRITICAL(); //进入临界区
BaseType_t xReturn;
/******创建任务1*******/
xReturn = xTaskCreate(task1,
"task1",
128,
NULL,
2,
&task1Handler);
if(xReturn==pdTRUE){}
/******创建任务2*******/
xReturn = xTaskCreate(task2,
"task2",
128,
NULL,
2,
&task2Handler);
if(xReturn==pdTRUE){}
portEXIT_CRITICAL(); //退出临界区
vTaskStartScheduler(); //开启任务调度器
while(1){
}
}
//发送消息
void task1(void* param)
{
while(1){
xTaskNotify(task2Handler,
EVENT1,
eSetBits);//设置任务通知对应位
vTaskDelay(500);
xTaskNotify(task2Handler,
EVENT2,
eSetBits);//设置任务通知对应位
vTaskDelay(1000);
}
}
//接收消息
void task2(void* param)
{
uint32_t recv;
while(1){
xTaskNotifyWait(0x0,
ULONG_MAX,
&recv,
portMAX_DELAY);
if(recv == EVENT1){//事件或
open();
}else if(recv == EVENT2){
close();
}
}
}