消息同步(Notitication Sync)

消息同步(Notitication Sync)

什么是任务通知 任务通知是一种轻量汲任务间通信和同步机制。任务通知允许一个任务向另一个任务发送简单的数值消息或者通知事件。任务通知提供了比信号量、队列等其他同步机制更高效的性能,非常适用于快速和频繁的任务间通信。 官方函数文档 2.14 xTaskNotify() [[FreeRTOS_Refere

什么是任务通知

任务通知是一种轻量汲任务间通信和同步机制。任务通知允许一个任务向另一个任务发送简单的数值消息或者通知事件。任务通知提供了比信号量、队列等其他同步机制更高效的性能,非常适用于快速和频繁的任务间通信。


官方函数文档

2.14 xTaskNotify()

[[FreeRTOS_Reference_Manual_V10.0.0.pdf#page=99&selection=2,0,4,13|FreeRTOS_Reference_Manual_V10.0.0, page 99]]


xTaskNotify()

#include "FreeRTOS.h"
#include "task.h"

BaseType_t xTaskNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction );

函数说明:

  • 向另一个任务发送通知。
  • 每个 Task 都包含 32bit 的通知值,在任务创建时,通知值是 0 。
  • 通过这个值,可以解锁一个处于阻塞状态的任务,也可以通过以下方法之一来更新接收任务的通知值:
    • 向通知值写入一个 32bit 的值通知值。
    • 添加一个(Increment)通知值。
    • 设置一个或多个比特的通知值。
    • 不更改通知值。

参数:

  • xTaskToNotify:任务句柄。
  • ulValue:用来更新任务的通知值。
  • eAction:通知任务时要执行的操作。
    • eNoAction:任务被通知,但是通知值未变更。
    • eSetBits:任务的通知值与ulValue的按位或运算。例如,ulValue的值是0x01,则通知值的 bit 0 会被置位;如果ulValue的值是0x04,则通知值的 bit 2 会被置位。eSetBits可被用作任务通知事件组的更快、更轻量的替代方案。
    • eIncrement:通知值自增一,在这种情况下ulValue并未被使用。
    • eSetValueWithOverwrite:任务的通知值无条件设为ulValue的值,即使在调用xTaskNotify()时任务已有待处理的通知。
    • eSetValueWithoutOverwrite:如果任务已有待处理的通知,则其通知值不会改变,并且xTaskNotify()返回pdFAIL。如果任务还没有待处理的通知,则其通知值设为ulValue

返回值:

  • 如果eAction被设置为eSetValueWithoutOverwrite并且任务的通知值并未更新,则返回pdFAIL。其他所有情况都返回pdPASS

xTaskNotifyWait()

#include "FreeRTOS.h"
#include "task.h"

BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *puNotificationValue, TickType_t xTicksToWait );

函数说明:

  • 用于等待任务通知。它允许一个任务等待一个或多个通知事件到达,并在接收到通知后返回相关的通知值。

参数:

  • ulBitsToClearOnEntry:指定在进入等待状态之前要清除的通知值中的位。如果设为 0 ,则在等待之前不清除任何位。
  • ulBitsToClearOnExit:指定在退出等待之后要清除的通知值中的位,可以用ULONG_MAX来清除所有位。
  • puNotificationValue:指定一个变量,该变量将接收任务通知值。如果不需要接收通知值,可以传入NULL
  • xTicksToWait:超时等待时间。

返回值:

  • pdTRUE:在制定的时间内接收到返回值。
  • pdFALSE:未在制定的时间内接收到返回值。

示例代码

#include <stdio.h>
#include <inttypes.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_flash.h"
#include "esp_system.h"
#include "freertos/event_groups.h"
#include "freertos/semphr.h"

static TaskHandle_t task_a_handle;
static TaskHandle_t task_b_handle;

void task_a(void *pvPara)
{
    uint32_t notification_value = 0;

    while (true) {
		// 等待接收通知值,在等待前晴空通知值,在等待后清空通知值,通知值存储在 ulValue 中,无限等待
		// 任务会进入阻塞状态
        xTaskNotifyWait(0x00, ULONG_MAX, &notification_value, portMAX_DELAY);

        printf("[TASK A]: notification_value = %ld\n", notification_value);

        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

void task_b(void *pvPara)
{
    uint32_t notification_value = 0;

    while (true) {
		// 对另一个任务发送通知,使用 ulValue,任务的通知值与 ulValue 按位 或 运算。
        xTaskNotify(task_a_handle, notification_value, eSetBits);

        notification_value++;

        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

void app_main(void)
{
    xTaskCreate(task_a, "Task A", 2048, NULL, 1, &task_a_handle);
    xTaskCreate(task_b, "Task B", 2048, NULL, 1, &task_b_handle);
}
Comment