FreeRTOS学习笔记>任务通知

1. 任务通知的概念

FreeRTOS 从 V8.2.0 版本开始引入了任务通知功能。每个任务都有一个 32 位的通知值,任务通知可以替代二值信号量、计数信号量、事件组,甚至可以替代长度为 1 的队列(用于传递一个 32 位整数或指针值)。相比传统的通信方式,任务通知更加高效、节省内存空间,并且不需要创建额外的通信对象(如信号量或队列)。

2. 任务通知的优点

  • 性能优势:使用任务通知解除阻塞的任务比使用信号量等传统通信方式快约 45%。
  • 内存节省:不需要为任务通知创建额外的信号量、队列等,节省了 RAM 内存空间。
  • 简化设计:任务通知的使用更加简单直接,不需要创建复杂的通信对象。

3. 任务通知的使用

要使用任务通知,需要在 FreeRTOSConfig.h 文件中将宏 configUSE_TASK_NOTIFICATIONS 设置为 1。通常情况下,该宏默认是启用的。

任务通知有以下几种发送方式:

  1. 发送通知,不覆盖未读通知值
    • 如果任务已有未读的通知值,新通知不会覆盖旧的通知值。
  2. 发送通知,直接覆盖通知值
    • 无论任务是否有未读通知值,新的通知值将直接覆盖旧值。
  3. 发送通知,设置通知值的某些位
    • 可以通过设置通知值的某些位来使用通知值作为事件组。
  4. 发送通知,递增通知值
    • 可以通过递增通知值的方式将其用作计数信号量。

4. 任务通知的API函数

1. xTaskNotify()

BaseType_t xTaskNotify( TaskHandle_t xTaskToNotify,
                        uint32_t ulValue,
                        eNotifyAction eAction );
  • xTaskToNotify:要通知的任务句柄。
  • ulValue:通知值。
  • eAction:指定通知方式,可以是以下之一:
    • eSetBits:设置通知值的某些位(可以将通知用作事件组)。
    • eIncrement:递增通知值(可以将通知用作计数信号量)。
    • eSetValueWithOverwrite:直接覆盖通知值。
    • eSetValueWithoutOverwrite:如果已有未读通知值,则不覆盖。

2. xTaskNotifyGive()

void xTaskNotifyGive( TaskHandle_t xTaskToNotify );
  • xTaskToNotify:要通知的任务句柄。该函数是 xTaskNotify() 的简化形式,用于递增通知值。

3. ulTaskNotifyTake()

uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait );
  • xClearCountOnExit:指定是否在退出时清除通知值。
  • xTicksToWait:等待通知的时间。

4. xTaskNotifyWait()

BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry,
                            uint32_t ulBitsToClearOnExit,
                            uint32_t *pulNotificationValue,
                            TickType_t xTicksToWait );
  • ulBitsToClearOnEntry:在进入函数时清除的通知值的某些位。
  • ulBitsToClearOnExit:在退出函数时清除的通知值的某些位。
  • pulNotificationValue:指向通知值的指针。
  • xTicksToWait:等待通知的时间。

5. 任务通知的使用示例

以下是一个使用任务通知的简单示例,演示了如何使用任务通知来替代信号量。

// 任务 A:等待任务 B 发送通知
void TaskA(void *pvParameters) {
    uint32_t ulNotificationValue;

    for (;;) {
        // 等待通知,不清除位,并指定最大等待时间
        ulNotificationValue = ulTaskNotifyTake(pdFALSE, portMAX_DELAY);

        if (ulNotificationValue > 0) {
            // 执行接收到通知后的操作
        }
    }
}

// 任务 B:发送通知给任务 A
void TaskB(void *pvParameters) {
    for (;;) {
        // 执行任务 B 的一些操作

        // 发送通知给任务 A,使用递增通知值方式
        xTaskNotifyGive(xTaskAHandle);

        // 等待下一次通知
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

6. 任务通知的局限性

虽然任务通知具有显著的优点,但也有以下限制:

  • 单任务接收:任务通知只能由一个指定任务接收,不能用于多个任务的同步。
  • 发送任务不会阻塞:发送通知的任务不会因为发送失败而阻塞。

7. 总结

任务通知为 FreeRTOS 提供了一种高效、灵活的任务间通信方式,可以替代传统的信号量、队列等机制。在需要高效通信且只涉及单一任务的场景下,任务通知是一个理想的选择。然而,对于需要多个任务同步的场景,传统的 IPC 机制仍然有其独特的优势。

欢迎指出博客中的错误,如果你觉得对你有用,记得点赞三连,有问题可留言,会及时回复

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HKElec

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值