2025最新超详细FreeRTOS入门教程:第八章 FreeRTOS任务通知

2025最新超详细FreeRTOS入门教程:第八章 FreeRTOS任务通知

摘要

在前几章中,我们依次学习了 队列、信号量、互斥量、事件组 等任务间通信与同步机制。虽然这些工具功能强大,但在某些轻量级场景下,它们可能显得"过于复杂",比如:

  • 任务之间只需要传递一个整数值
  • ISR 只需要快速通知任务执行一次操作
  • 需要更快、更轻量的同步方式

此时,使用 任务通知(Task Notification) 是最佳选择。

任务通知是 FreeRTOS 提供的最轻量级任务通信机制,它不需要额外的内存开销,比队列和信号量更高效。

文章目录


一、任务通知的基本概念

1. 定义

  • 每个任务都有一个 32 位通知值,由 FreeRTOS 内核维护
  • 任务可以等待通知、发送通知
  • 通知既可以当作 二值信号量 使用,也可以当作 计数信号量/事件标志/消息传递 使用

2. 特点

  • 每个任务最多有一个通知值(可扩展为多个通知数组,FreeRTOS V10.4+ 引入 TaskNotifyTakeIndexed
  • 不需要额外的句柄对象(不像队列、信号量需要额外 RAM)
  • 速度最快,适合 ISR 与任务之间的通信

通知 通知值 中断 任务1 任务2 任务3


二、任务通知 API

1. 发送任务通知

c 复制代码
BaseType_t xTaskNotify(
   TaskHandle_t xTaskToNotify,
   uint32_t ulValue,
   eNotifyAction eAction
);
  • eAction 取值:
    • eSetBits:对通知值执行按位或
    • eIncrement:通知值自增
    • eSetValueWithOverwrite:覆盖写入
    • eSetValueWithoutOverwrite:不覆盖已有通知

2. 等待任务通知

c 复制代码
BaseType_t xTaskNotifyWait(
   uint32_t ulBitsToClearOnEntry,
   uint32_t ulBitsToClearOnExit,
   uint32_t *pulNotificationValue,
   TickType_t xTicksToWait
);
  • ulBitsToClearOnEntry:进入等待前清除的位
  • ulBitsToClearOnExit:退出等待后清除的位
  • pulNotificationValue:输出通知值
  • xTicksToWait:阻塞等待时间

3. 类似信号量的 API

c 复制代码
uint32_t ulTaskNotifyTake(BaseType_t xClearCountOnExit,
                          TickType_t xTicksToWait);
  • 用于实现 二值/计数信号量
  • xClearCountOnExit = pdTRUE:退出时清零
  • 返回值:成功接收到的次数

4. ISR 中发送任务通知

c 复制代码
BaseType_t xTaskNotifyFromISR(
   TaskHandle_t xTaskToNotify,
   uint32_t ulValue,
   eNotifyAction eAction,
   BaseType_t *pxHigherPriorityTaskWoken
);

三、任务通知使用示例

示例1:ISR 通知任务

c 复制代码
#include "FreeRTOS.h"
#include "task.h"

TaskHandle_t xHandleTask;

void vTaskHandler(void *pvParameters)
{
    uint32_t ulNotifiedValue;
    for(;;)
    {
        if(xTaskNotifyWait(0x00, 0xFFFFFFFF, &ulNotifiedValue, portMAX_DELAY) == pdTRUE)
        {
            printf("任务被中断唤醒, 值=%lu\n", ulNotifiedValue);
        }
    }
}

void EXTI0_IRQHandler(void)
{
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
    xTaskNotifyFromISR(xHandleTask, 1, eIncrement, &xHigherPriorityTaskWoken);
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

int main(void)
{
    HAL_Init();
    SystemClock_Config();

    xTaskCreate(vTaskHandler, "Handler", 128, NULL, 2, &xHandleTask);

    vTaskStartScheduler();
}

运行结果:

  • 每次中断触发,任务收到通知并打印计数

示例2:任务间通信(传递整数)

c 复制代码
TaskHandle_t xTaskSender, xTaskReceiver;

void vTaskSender(void *pvParameters)
{
    uint32_t count = 0;
    for(;;)
    {
        count++;
        xTaskNotify(xTaskReceiver, count, eSetValueWithOverwrite);
        vTaskDelay(1000);
    }
}

void vTaskReceiver(void *pvParameters)
{
    uint32_t ulValue;
    for(;;)
    {
        if(xTaskNotifyWait(0, 0, &ulValue, portMAX_DELAY) == pdTRUE)
        {
            printf("接收值=%lu\n", ulValue);
        }
    }
}

四、任务通知的工作机制

调用 xTaskNotifyWait ISR/任务发出通知 任务被唤醒并读取值 清除通知位 未通知 等待 已通知 处理


五、任务通知与队列/信号量对比

特性 任务通知 队列 信号量
速度 ✅ 最快 ❌ 较慢 中等
内存占用 ✅ 无额外对象 ❌ 队列结构体 ❌ 信号量对象
传递数据 ✅ 支持整数/位图 ✅ 任意数据
ISR 使用
多任务等待 ❌ 仅单任务

六、常见应用场景

  1. 任务与中断同步
    • ISR 中快速通知任务处理事件
  2. 任务间轻量通信
    • 不需要完整队列机制,只需传递整数
  3. 任务事件触发
    • 使用按位通知,代替事件组的轻量版本

七、调试与监控

  • 使用 uxTaskGetStackHighWaterMark() 检查任务是否正常运行
  • 使用 vTaskGetInfo() 获取任务通知状态
  • 注意避免丢失通知(覆盖写模式可能导致数据丢失)

八、常见问题与解决方法

问题 可能原因 解决方法
通知丢失 使用覆盖写模式 改用 eIncrement 或事件组
ISR 报错 使用了错误 API 改用 xTaskNotifyFromISR
多任务等待通知失败 每个任务只能有一个通知值 使用事件组/队列替代
通知无法清零 xTaskNotifyWait 参数设置错误 检查清除位参数

九、经验总结

📌 开发建议

  1. 若只是 ISR 与任务间的 单一事件触发,优先使用任务通知
  2. 若需要多个任务等待,使用事件组或队列
  3. 若需要传递复杂数据结构,使用队列
  4. 在高实时性场景,任务通知是最快的通信方式

十、总结

通过本章学习,你已经掌握:

  • 任务通知的概念与机制
  • 发送与接收任务通知的 API
  • 在 ISR 与任务之间使用任务通知
  • 与队列/信号量的对比和适用场景

任务通知是 FreeRTOS 中最轻量的同步与通信工具,在性能要求高的嵌入式系统中非常有价值。


🔗 FreeRTOS专栏👉 下一章:2025最新超详细FreeRTOS入门教程:第九章 FreeRTOS软件定时器 ------将学习如何在任务之外调度定时操作。


相关推荐
TDengine (老段)2 分钟前
TDengine 免费版说明
java·大数据·数据库·物联网·时序数据库·tdengine
hongmai6668881 小时前
ESP32-C61-WROOM-1-N8R2:Wi-Fi 6与RISC-V融合的中坚力量
人工智能·单片机·嵌入式硬件·物联网·智能家居·risc-v
hai3152475431 小时前
芯片设计的空间框架:以电流步距与相位为核心
硬件架构·硬件工程·材料工程
aixingkong9211 小时前
Atlas 950 1024卡SuperPoD推测分析
网络·人工智能·硬件架构·硬件工程
步步精BBJconn1 小时前
从GPU服务器到数据中心:AI服务器高压连接器的应用与发展趋势
大数据·运维·服务器·人工智能·科技·物联网
炸膛坦客10 小时前
单片机/C/C++八股:(二十六)IIC 专题(I²C)---- 上集
c语言·c++·单片机
MetrixAeroCore12 小时前
自动售货机库存上报异常物联网卡DNS解析失败修复教程
物联网
ANSIOT13 小时前
安朔科技蓝牙无感开锁方案,靠近自动解锁
网络·科技·物联网
微硬创新13 小时前
耐达讯自动化 CC-Link IE 转 PROFINET网关在污水厂智能化升级实战
人工智能·物联网·网络协议·自动化·信息与通信
华清远见IT开放实验室15 小时前
实验室建设案例 | 石家庄科技信息职业学院嵌入式实验室——从底层硬件到系统应用,一所应用型高校的嵌入式人才培养这样落地
linux·arm开发·stm32·嵌入式硬件·高校·实验室建设