当前位置: 首页 > news >正文

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

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

摘要

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

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

此时,使用 任务通知(Task Notification) 是最佳选择。
任务通知是 FreeRTOS 提供的最轻量级任务通信机制,它不需要额外的内存开销,比队列和信号量更高效。

2025最新超详细FreeRTOS入门教程

文章目录

  • 2025最新超详细FreeRTOS入门教程:第八章 FreeRTOS任务通知
    • 摘要
    • 一、任务通知的基本概念
      • 1. 定义
      • 2. 特点
    • 二、任务通知 API
      • 1. 发送任务通知
      • 2. 等待任务通知
      • 3. 类似信号量的 API
      • 4. ISR 中发送任务通知
    • 三、任务通知使用示例
      • 示例1:ISR 通知任务
      • 示例2:任务间通信(传递整数)
    • 四、任务通知的工作机制
    • 五、任务通知与队列/信号量对比
    • 六、常见应用场景
    • 七、调试与监控
    • 八、常见问题与解决方法
    • 九、经验总结
    • 十、总结


一、任务通知的基本概念

1. 定义

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

2. 特点

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

二、任务通知 API

1. 发送任务通知

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

2. 等待任务通知

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

3. 类似信号量的 API

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

4. ISR 中发送任务通知

BaseType_t xTaskNotifyFromISR(TaskHandle_t xTaskToNotify,uint32_t ulValue,eNotifyAction eAction,BaseType_t *pxHigherPriorityTaskWoken
);

三、任务通知使用示例

示例1:ISR 通知任务

#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:任务间通信(传递整数)

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软件定时器 ——将学习如何在任务之外调度定时操作。



文章转载自:

http://8XMh1yFQ.xbtLt.cn
http://ph5CxFIP.xbtLt.cn
http://VT50HqqY.xbtLt.cn
http://6VnK0mv2.xbtLt.cn
http://R9KxMKV9.xbtLt.cn
http://CfKDjOCs.xbtLt.cn
http://Eo7oV01w.xbtLt.cn
http://VTHtxx7C.xbtLt.cn
http://W5wO66fM.xbtLt.cn
http://EQzMZavR.xbtLt.cn
http://L87LGuXZ.xbtLt.cn
http://0lFSUQ56.xbtLt.cn
http://LLu6vaiT.xbtLt.cn
http://ybD9l4g4.xbtLt.cn
http://SINiRJdZ.xbtLt.cn
http://83NxhmVQ.xbtLt.cn
http://QLMMJ8Wo.xbtLt.cn
http://YNmSHWpp.xbtLt.cn
http://o1nqNYo9.xbtLt.cn
http://wQWMUyZ4.xbtLt.cn
http://n2Ln8WZ9.xbtLt.cn
http://LzpAVxtz.xbtLt.cn
http://LjPwTHFa.xbtLt.cn
http://gIBPPX30.xbtLt.cn
http://tJW7fN7D.xbtLt.cn
http://VYL1ZnWx.xbtLt.cn
http://Wg72eaPS.xbtLt.cn
http://ij2ygJrG.xbtLt.cn
http://BAlnE4H5.xbtLt.cn
http://tgaW7YmN.xbtLt.cn
http://www.dtcms.com/a/374407.html

相关文章:

  • Puter+CPolar低成本替代商业网盘,打造私有云新势力
  • Deepoc科技之暖:智能助盲设备如何为视障家人点亮生活
  • 详细的vmware虚拟机安装教程
  • uni-app 项目中使用自定义字体
  • springboot maven 多环境配置入门与实战
  • 时序数据库选型指南:基于大数据视角的IoTDB应用优势分析详解!
  • 炫光活体检测技术:通过光学技术实现高效、安全的身份验证,有效防御多种伪造手段。
  • sqlite3的加解密全过程
  • Django REST Framework 中 @action 装饰器详解
  • 【Docker】一键将运行中的容器打包成镜像并导出
  • LLVM 数据结构简介
  • MCP与http、websocket的关系
  • 【modbus学习】
  • 【linux】sed/awk命令检索区间日志
  • 瑞派虹泰环城总院 | 打造“一站式宠物诊疗空间”,定义全国宠物医疗新高度
  • 数据分析画图显示中文
  • 嵌入式ARM架构学习3——启动代码
  • 2025云计算趋势:Serverless与AI大模型如何赋能中小企业
  • 如何利用 AWS 服务器优化跨境电商和 SEO 战略?
  • 大数据毕业设计-基于Python的中文起点网小说数据分析平台(高分计算机毕业设计选题·定制开发·真正大数据)
  • 小程序开发单行日历可滑动
  • 项目日记 -日志系统 -搭建基础框架
  • 计算机网络第四章(4)——网络层《ARP协议》
  • 探迹SalesGPT
  • 带有 Attention 机制的 Encoder-Decoder 架构模型分析
  • 利用易语言编写,逻辑为按照数字越大抽取率越前
  • leetcode 219 存在重复元素II
  • Redis(缓存)
  • ARP 协议
  • 169.在Vue3中使用OpenLayers + D3实现地图区块呈现不同颜色的效果