【FreeRTOS(十三)】任务通知
创始人
2024-03-17 13:33:46
0

文章目录

  • 任务通知
    • 发送通知
      • 带有通知值发送 xTaskNotify
      • 不带通知值发送 xTaskNotifyGive
    • 任务通知
      • 获取任务通知 ulTaskNotifyTake
      • 等待任务通知 xTaskNotifyWait
    • 代码示例:任务通知同步(ulTaskNotifyTake、xTaskNotifyGive)
    • 代码示例:任务通知值(xTaskNotify 、xTaskNotifyWait )

任务通知

任务通知在 FreeRTOS 中是一个可选的功能,要使用任务通知的话就需要将宏configUSE_TASK_NOTIFICATIONS 定义为 1。

FreeRTOS 的每个任务都有一个 32 位的通知值,任务控制块中的成员变量 ulNotifiedValue就是这个通知值。任务通知是一个事件,假如某个任务通知的接收任务因为等待任务通知而阻塞的话,向这个接收任务发送任务通知以后就会解除这个任务的阻塞状态。也可以更新接收任务的任务通知值,任务通知可以通过如下方法更新接收任务的通知值:

  • 不覆盖接收任务的通知值(如果上次发送给接收任务的通知还没被处理)。
  • 覆盖接收任务的通知值。
  • 更新接收任务通知值的一个或多个 bit。
  • 增加接收任务的通知值。

合理、灵活的使用上面这些更改任务通知值的方法可以在一些场合中替代队列、二值信号量、计数型信号量和事件标志组。使用任务通知来实现二值信号量功能的时候,解除任务阻塞的时间比直接使用二值信号量要快 45%(FreeRTOS 官方测试结果,使用 v8.1.2 版本中的二值信号量,GCC 编译器,-O2 优化的条件下测试的,没有使能断言函数 configASSERT()),并且使用的 RAM 更少!

任务通知的发送使用函数xTaskNotify()或者 xTaskNotifyGive()(还有此函数的中断版本)来完 成 , 这 个 通 知 值 会 一 直 被 保 存 着 , 直 到 接 收 任 务 调 用 函 数 xTaskNotifyWait() 或 者ulTaskNotifyTake()来获取这个通知值。假如接收任务因为等待任务通知而阻塞的话那么在接收到任务通知以后就会解除阻塞态。
任务通知虽然可以提高速度,并且减少 RAM 的使用,但是任务通知也是有使用限制的:

  • FreeRTOS 的任务通知只能有一个接收任务,其实大多数的应用都是这种情况。
  • 接收任务可以因为接收任务通知而进入阻塞态,但是发送任务不会因为任务通知发送
    失败而阻塞。


发送通知


带有通知值发送 xTaskNotify

发送任务通知,此函数发送任务通知的时候带有通知值,此函数是个宏,真正执行的函数 xTaskGenericNotify()

BaseType_t xTaskNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction );参数:xTaskToNotify: 任务句柄,指定任务通知是发送给哪个任务的。ulValue: 任务通知值。eAction: 任务通知更新的方法,eNotifyAction 是个枚举类型typedef enum{eNoAction = 0,eSetBits, //更新指定的 biteIncrement, //通知值加一eSetValueWithOverwrite, //覆写的方式更新通知值eSetValueWithoutOverwrite //不覆写通知值} eNotifyAction;返回值:pdFAIL: 当参数 eAction 设置为 eSetValueWithoutOverwrite 的时候,如果任务通知值没有更新成功就返回 pdFAIL。pdPASS: eAction 设置为其他选项的时候统一返回 pdPASS。

不带通知值发送 xTaskNotifyGive

发送任务通知,相对于函数 xTaskNotify(),此函数发送任务通知的时候不带有通知值。此函数只是将任务通知值简单的加一,此函数是个宏,真正执行的是函数 xTaskGenericNotify()

BaseType_t xTaskNotifyGive( TaskHandle_t xTaskToNotify );参数:xTaskToNotify: 任务句柄,指定任务通知是发送给哪个任务的。返回值:pdPASS: 此函数只会返回 pdPASS。


任务通知


获取任务通知 ulTaskNotifyTake

获取任务通知函数,当任务通知用作二值信号量或者计数型信号量的时候可以使用此函数来获取信号量。

uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait );参数:xClearCountOnExit: 参数为 pdFALSE 的话在退出函数 ulTaskNotifyTake()的时候任务通知值减一,类似计数型信号量。当此参数为 pdTRUE 的话在退出函数的时候任务任务通知值清零,类似二值信号量。xTickToWait: 阻塞时间。返回值:任何值 : 任务通知值减少或者清零之前的值。

等待任务通知 xTaskNotifyWait

是用来获取任务通知的,不过此函数比 ulTaskNotifyTake()更为强大,不管任务通知用作二值信号量、计数型信号量、队列和事件标志组中的哪一种,都可以使用此函数来获取任务通知。但是当任务通知用作位置信号量和计数型信号量的时候推荐使用函数
ulTaskNotifyTake()

BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry,uint32_t ulBitsToClearOnExit, uint32_t * pulNotificationValue, TickType_t xTicksToWait );参数:ulBitsToClearOnEntry:当没有接收到任务通知的时候将任务通知值与此参数的取反值进行按位与运算,当此参数为 0xffffffff 或者 ULONG_MAX 的时候就会将任务通知值清零。ulBitsToClearOnExit:如果接收到了任务通知,在做完相应的处理退出函数之前将任务通知值与此参数的取反值进行按位与运算,当此参数为 0xffffffff 或者ULONG_MAX 的时候就会将任务通知值清零。pulNotificationValue:此参数用来保存任务通知值。xTickToWait: 阻塞时间。返回值:pdTRUE: 获取到了任务通知。pdFALSE: 任务通知获取失败。

代码示例:任务通知同步(ulTaskNotifyTake、xTaskNotifyGive)

#include 
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_spi_flash.h"static TaskHandle_t xTask1 = NULL;void Task1(void *pvParam)
{while (1){printf("----------------!\n");printf("task1 wait notification!\n");ulTaskNotifyTake(pdTRUE, portMAX_DELAY);printf("----------------!\n");printf("task1 got notification!\n");vTaskDelay(pdMS_TO_TICKS(3000));}
}void Task2(void *pvParam)
{while (1){vTaskDelay(pdMS_TO_TICKS(5000));printf("----------------!\n");printf("task2 notify task1!\n");xTaskNotifyGive(xTask1);}
}void app_main(void)
{vTaskSuspendAll();xTaskCreate(Task1, "Task1", 1024 * 5, NULL, 1, &xTask1);xTaskCreate(Task2, "Task2", 1024 * 5, NULL, 1, NULL);xTaskResumeAll();
}

代码示例:任务通知值(xTaskNotify 、xTaskNotifyWait )

#include 
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_spi_flash.h"static TaskHandle_t xTask1 = NULL;void Task1(void *pvParam)
{uint32_t ulNotifiedValue;while (1){printf("----------------!\n");printf("task1 wait notification!\n");xTaskNotifyWait(0x00,             /* Don't clear any notification bits on entry. */ULONG_MAX,        /* Reset the notification value to 0 on exit. */&ulNotifiedValue, /* Notified value pass out in ulNotifiedValue. */portMAX_DELAY);   /* Block indefinitely. *//* Process any events that have been latched in the notified value. */if ((ulNotifiedValue & 0x01) != 0){/* Bit 0 was set - process whichever event is represented by bit 0. */printf("task1 process bit0 event!\n");}if ((ulNotifiedValue & 0x02) != 0){/* Bit 1 was set - process whichever event is represented by bit 1. */printf("task1 process bit1 event!\n");}if ((ulNotifiedValue & 0x04) != 0){/* Bit 2 was set - process whichever event is represented by bit 2. */printf("task1 process bit2 event!\n");}vTaskDelay(pdMS_TO_TICKS(3000));}
}void Task2(void *pvParam)
{while (1){vTaskDelay(pdMS_TO_TICKS(5000));printf("----------------!\n");printf("task2 notify bit0!\n");xTaskNotify(xTask1, 0x01, eSetValueWithOverwrite);vTaskDelay(pdMS_TO_TICKS(5000));printf("task2 notify bit1!\n");xTaskNotify(xTask1, 0x02, eSetValueWithOverwrite);vTaskDelay(pdMS_TO_TICKS(5000));printf("task2 notify bit2!\n");xTaskNotify(xTask1, 0x04, eSetValueWithOverwrite);vTaskDelay(pdMS_TO_TICKS(5000));}
}void app_main(void)
{vTaskSuspendAll();xTaskCreate(Task1, "Task1", 1024 * 5, NULL, 1, &xTask1);xTaskCreate(Task2, "Task2", 1024 * 5, NULL, 1, NULL);xTaskResumeAll();
}

相关内容

热门资讯

AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
​ToDesk 远程工具安装及... 目录 前言 ToDesk 优势 ToDesk 下载安装 ToDesk 功能展示 文件传输 设备链接 ...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWR报告解读 WORKLOAD REPOSITORY PDB report (PDB snapshots) AW...
AWS管理控制台菜单和权限 要在AWS管理控制台中创建菜单和权限,您可以使用AWS Identity and Access Ma...
群晖外网访问终极解决方法:IP... 写在前面的话 受够了群晖的quickconnet的小水管了,急需一个新的解决方法&#x...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...