• FreeRTOS学习笔记-任务通知


    概述

    每个任务都有一个32位的通知值,在创建任务时该值被初始化为零。 任务通知是直接发送到任务的事件,它可以解除对接收任务的阻塞,并可以选择更新接收任务的通知值。任务通知功能与信号量类似,但更简洁。

    关键函数说明

    头文件

    #include "freertos/task.h"
    
    
    • 1
    • 2

    获取通知

    uint32_t ulTaskNotifyTake( 
    			BaseType_t xClearCountOnExit, //pdTRUE:函数退出时将通知值清零 == 二值信号量; pdFALSE:函数退出时将通知值减1 == 计数信号量
    			TickType_t xTicksToWait );//等待时间
    
    • 1
    • 2
    • 3

    发送通知

    xTaskNotify()用于将事件直接发送到任务,可以选择以下列方式之一更新接收任务的通知值:

    • 将32位数字写入通知值
    • 将通知值加一(递增)
    • 在通知值中设置一个或多个位
    • 保持通知值不变
    BaseType_t xTaskNotify( 
    			TaskHandle_t xTaskToNotify,//任务句柄
    			uint32_t ulValue,//用于更新通知值,其解释方式取决于eAction参数得.
    			eNotifyAction eAction );
    
    • 1
    • 2
    • 3
    • 4

    eAction 参数说明:

    • eNoAction :通知任务,但通知值不变,该情况下 ulValue 无效
    • eSetBits:任务通知值与 ulValue 按位进行或运算
    • eIncrement:任务通知值递增,该情况下 ulValue 无效
    • eSetValueWithOverwrite:用 ulValue 强制覆盖通知值
    • eSetValueWithoutOverwrite:用 ulValue 覆盖通知值,若任务已经有一个待处理通知,则不会覆盖,并返回 pdFAIL

    释放通知

    xTaskNotifyGive() 是一个宏,调用了 xTaskNotify() 函数并将 eAction 参数设置为 eIncrement(增量)

    BaseType_t xTaskNotifyGive( TaskHandle_t xTaskToNotify );//任务句柄
    
    • 1

    等待通知

    BaseType_t xTaskNotifyWait( 
    			uint32_t ulBitsToClearOnEntry,//函数等待前清除相应bit,0xffffffff (ULONG_MAX):将清除所有bit
    			uint32_t ulBitsToClearOnExit,//函数退出时清除相应bit,
    			uint32_t *pulNotificationValue,//通知值指针,通过该指针可获取通知值
    			TickType_t xTicksToWait );//等待时间
    //返回值:pdTRUE : 接收到通知; pdFALSE: 超时
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    示例代码

    消息同步(用任务通知实现二值信号量功能)

    #include 
    #include "sdkconfig.h"
    #include "freertos/FreeRTOS.h"
    #include "freertos/task.h"
    #include "esp_system.h"
    #include "esp_spi_flash.h"
    
    int iCount = 100;
    
    void mytask1(void *pvParameter)
    {
        ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
        for (int i = 0; i < 5; i++)
        {
            printf("task1: iCount = %d\n", iCount);
            vTaskDelay(1000 / portTICK_PERIOD_MS);
            iCount++;
        }
        vTaskDelete(NULL);
    }
    void mytask2(void *pvParameter)
    {
        ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
        for (int i = 0; i < 5; i++)
        {
            printf("task2: iCount = %d\n", iCount);
            vTaskDelay(1000 / portTICK_PERIOD_MS);
            iCount++;
        }
        vTaskDelete(NULL);
    }
    void app_main(void)
    {
        TaskHandle_t myTastHandle1 = NULL;
        TaskHandle_t myTastHandle2 = NULL;
        xTaskCreate(mytask1, "mytask1", 1024 * 5, NULL, 1, &myTastHandle1);
        xTaskCreate(mytask2, "mytask2", 1024 * 5, NULL, 1, &myTastHandle2);
        printf("app_main: Create task1 and task2 \n");
    
        //通知任务1计算5s
        xTaskNotifyGive(myTastHandle1);
        vTaskDelay(10000 / portTICK_PERIOD_MS);
    
        //通知任务2计算5s
        xTaskNotifyGive(myTastHandle2);
        vTaskDelay(10000 / portTICK_PERIOD_MS);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    效果

    app_main: Create task1 and task2
    task1: iCount = 100
    task1: iCount = 101
    task1: iCount = 102
    task1: iCount = 103
    task1: iCount = 104
    task2: iCount = 105
    task2: iCount = 106
    task2: iCount = 107
    task2: iCount = 108
    task2: iCount = 109

    通知值

    #include 
    #include "sdkconfig.h"
    #include "freertos/FreeRTOS.h"
    #include "freertos/task.h"
    #include "esp_system.h"
    #include "esp_spi_flash.h"
    
    #define Notify_0_BIT (1 << 0)
    #define Notify_1_BIT (1 << 1)
    #define Notify_2_BIT (1 << 2)
    
    void mytask1(void *pvParameter)
    {
        uint32_t value;
        printf("task1 start \n");
        while (1)
        {
            xTaskNotifyWait(
                0,              //函数等待前清除相应bit,0xffffffff (ULONG_MAX):将清除所有bit
                ULONG_MAX,      //函数退出时清除相应bit,
                &value,         //通知值指针,通过该指针可获取通知值
                portMAX_DELAY); //等待时间
            if ((value & 0x01) != 0)
            {
                /* Bit 0 was set - process whichever event is represented by bit 0. */
                printf("Bit 0 was set \n");
            }
            if ((value & 0x02) != 0)
            {
                /* Bit 1 was set - process whichever event is represented by bit 1. */
                printf("Bit 1 was set \n");
            }
            if ((value & 0x04) != 0)
            {
                /* Bit 2 was set - process whichever event is represented by bit 2. */
                printf("Bit 2 was set \n");
            }
            printf("----------------------\n");
        }
    }
    
    void app_main(void)
    {
        TaskHandle_t myTastHandle1 = NULL;
        xTaskCreate(mytask1, "mytask1", 1024 * 5, NULL, 1, &myTastHandle1);
    
        //通知任务1计算5s
        while (1)
        {
            vTaskDelay(5000 / portTICK_PERIOD_MS);
            xTaskNotify(
                myTastHandle1,
                Notify_0_BIT | Notify_1_BIT | Notify_2_BIT, //用于更新通知值,其解释方式取决于eAction参数得.
                eSetBits);
            vTaskDelay(5000 / portTICK_PERIOD_MS);
            xTaskNotify(
                myTastHandle1,
                Notify_0_BIT, //用于更新通知值,其解释方式取决于eAction参数得.
                eSetBits);
            vTaskDelay(5000 / portTICK_PERIOD_MS);
            xTaskNotify(
                myTastHandle1,
                Notify_1_BIT, //用于更新通知值,其解释方式取决于eAction参数得.
                eSetBits);
            vTaskDelay(5000 / portTICK_PERIOD_MS);
            xTaskNotify(
                myTastHandle1,
                Notify_2_BIT, //用于更新通知值,其解释方式取决于eAction参数得.
                eSetBits);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71

    效果

    task1 start
    Bit 0 was set 
    Bit 1 was set 
    Bit 2 was set
    ----------------------
    Bit 0 was set 
    ----------------------
    Bit 1 was set 
    ----------------------
    Bit 2 was set 
    ----------------------
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
  • 相关阅读:
    SpringBoot面试题6:Spring Boot 2.X 有什么新特性?与 1.X 有什么区别?
    SpringCloud学习(七)----- 使用Feign调用别的微服务的方法
    C内存管理
    深度学习与python theano
    13.8 - 软件测试工作量及成本估算 3.9 - 软件测试成本估算示例
    写个rpc调用,试试自己了解多少
    Dev 使用汇总
    【洛谷 P8780】[蓝桥杯 2022 省 B] 刷题统计 题解(贪心算法+模拟+四则运算)
    用 Kafka + DolphinDB 实时计算K线
    启动服务报错:Command line is too long Shorten command line for xxx or also for Spri
  • 原文地址:https://blog.csdn.net/ai_ljh/article/details/126812925