(九)任务通知

欢迎入群共同学习交流

一、概念

(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();
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值