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

【FreeRTOS】任务间通讯6: 任务通知- Task Notification

先看个收快递的例子:

  1. 快递柜 → Task Notification
    就像小区里的智能快递柜(每个柜子只能存一个包裹),Task Notification 是任务专属的“数据柜”,只能存一条通知信息(比如一个数字或标志位)。

  2. 快递员(发送者) → 其他任务/中断
    快递员(其他任务或中断)把你的包裹(通知数据)塞进你的专属柜子(xTaskNotify()),并生成一个取件码(唤醒任务)。

  3. 你(接收者) → 等待通知的任务
    你本来在沙发上睡觉(任务阻塞中,ulTaskNotifyTake()),突然手机收到取件码(通知到达),立马跳起来开柜取包裹(任务被唤醒,处理通知)。

  FreeRTOS中的任务通知,就是像快递柜这样的一个装置。

一. Task Notification 简介

    Task Notification 是 FreeRTOS 提供的一种轻量级任务间通信(IPC)机制,它允许任务或中断直接向另一个任务发送通知(Notification),而无需使用队列、信号量或事件组等中间对象。

1.1 功能与作用

  • 轻量级通信:比队列、信号量更高效,节省内存和 CPU 开销。

  • 直接唤醒任务:通知可以解除目标任务的阻塞状态(类似二进制信号量)。

  • 携带数据:可以传递一个 32 位整数值(类似队列,但只能存一个值)。

  • 多种通知模式

    • 覆盖模式eSetValueWithOverwrite):新通知覆盖旧值(默认)。

    • 累积模式eSetValueWithoutOverwrite):新通知不覆盖旧值(类似计数信号量)。

    • 增量模式eIncrement):每次通知使目标任务的 ulNotifiedValue +1(类似计数信号量)。

    • 设置位模式eSetBits):按位设置目标任务的通知值(类似事件组)。


二. Task Notification 使用流程

2.1 创建任务

    Task Notification 是 FreeRTOS 任务的 内置功能,不需要显式创建,每个任务自带一个通知状态:

  • ulNotifiedValue:存储通知值(32 位整数)。

  • ucNotifyState:记录通知状态(taskNOT_WAITING_NOTIFICATIONtaskWAITING_NOTIFICATION 等)。

2.2 发送通知

    使用 xTaskNotify() 或 xTaskNotifyFromISR()(中断中使用)发送通知:

BaseType_t xTaskNotify(TaskHandle_t xTaskToNotify,  // 目标任务句柄uint32_t ulValue,           // 通知值eNotifyAction eAction        // 通知模式(如 eSetValueWithOverwrite)
);

2.3 接收通知

    目标任务使用 ulTaskNotifyTake() 或 xTaskNotifyWait() 接收通知:

uint32_t ulTaskNotifyTake(BaseType_t xClearCountOnExit,  // pdTRUE:清零计数器;pdFALSE:减1TickType_t xTicksToWait        // 超时时间(portMAX_DELAY 表示永久阻塞)
);

2.4 销毁

    Task Notification 是任务的内置功能,无需销毁,任务删除时会自动清理。


三. 实战 Demo:任务通知模拟按键触发 LED

场景

  • 任务 1vSenderTask):模拟按键检测,检测到按键后发送通知。

  • 任务 2vReceiverTask):等待通知,收到通知后切换 LED 状态。

代码实现

#include "FreeRTOS.h"
#include "task.h"
#include "stdio.h"// 假设 LED 和按键的硬件操作函数
void LED_Toggle(void);
int Key_Scan(void);  // 返回 1 表示按键按下TaskHandle_t xReceiverHandle;// 发送任务(模拟按键检测)
void vSenderTask(void *pvParameters) {while (1) {if (Key_Scan() == 1) {printf("按键按下,发送通知!\n");xTaskNotify(xReceiverHandle, 0, eNoAction);  // 仅唤醒任务,不传值}vTaskDelay(pdMS_TO_TICKS(100));  // 100ms 检测一次按键}
}// 接收任务(控制 LED)
void vReceiverTask(void *pvParameters) {while (1) {// 等待通知(类似二进制信号量)ulTaskNotifyTake(pdTRUE, portMAX_DELAY);LED_Toggle();printf("收到通知,LED 状态切换!\n");}
}int main() {// 创建接收任务(优先级较高)xTaskCreate(vReceiverTask, "Receiver", 128, NULL, 2, &xReceiverHandle);// 创建发送任务(优先级较低)xTaskCreate(vSenderTask, "Sender", 128, NULL, 1, NULL);// 启动调度器vTaskStartScheduler();return 0;
}

四. Task Notification 的优缺点

4.1 优点

  • 高效:比队列、信号量快,减少上下文切换和内存占用。
  • 灵活:支持多种通知模式(覆盖、累积、位操作等)。
  • 内置功能:无需额外对象,直接绑定到任务。
  • 低延迟:直接唤醒目标任务,适合实时响应场景。

4.2 缺点

  • 单接收者:只能一对一通信,不能像队列或事件组那样广播。
  • 数据限制:只能携带一个 32 位值,无法传递复杂数据。
  • 无历史记录:新通知可能覆盖旧值(除非使用累积模式)。

五. 总结

  • 适用场景

    • 轻量级任务同步(替代二进制/计数信号量)。

    • 高速事件通知(如中断唤醒任务)。

  • 不适用场景

    • 需要传递大数据(用队列)。

    • 多任务监听同一事件(用事件组或队列)。

Task Notification 是 FreeRTOS 中 最快、最省资源 的 IPC 机制,合理使用能大幅提升系统性能!

http://www.dtcms.com/a/326571.html

相关文章:

  • python+requests+yaml实现接口自动化用例
  • 【软件分享】格式工厂FormatFactory便携版本(解压即用)
  • 介绍一下jQuery的AJAX异步请求
  • Salesforce案例:零售企业会员积分体系
  • 新人如何简化学习Vue3文件
  • LangChain框架之 invoke() 方法
  • 【每日一错】PDB之间数据迁移
  • 7.Java的继承
  • 分享一款基于STC8H8K32U-45I-LQFP48单片机的4路数字量输入输出模块
  • 多重时间聚合算法(MAPA)改进需求预测模型
  • Redis实现排行榜
  • C++11 auto关键字:智能类型推导指南
  • 字符串相关例题(查询子串在主串中的个数)
  • GB17761-2024标准与电动自行车防火安全的技术革新
  • 编译GCC-12.1.0
  • Linux内核网络设备框架及其注册流程分析
  • Cursor 实用技巧与常见难题解析:从入门到进阶的技术实践
  • Pytest项目_day11(fixture、conftest)
  • OSPF IP FRR 理论和实验
  • 当C#遇上Notepad++:实现GCode可视化编辑的跨界实践
  • 3.数据类型和类型装换
  • Qt——实现”Hello World“、认识对象树与Qt坐标系
  • 用 Node.js 玩转 Elasticsearch从安装到增删改查
  • 月报 Vol.02:新增条件编译属性 cfg、#alias属性、defer表达式,增加 tuple struct 支持
  • 【前端插件】Code-Inspector-Plugin:重新定义前端开发的调试与协作体验
  • 【CSS 布局】告别繁琐计算:CSS 现代布局技巧(gap, aspect-ratio, minmax)
  • CobaltStrike的搭建与使用
  • 数字IC后端层次化Hierarchical Flow子系统Sub-System模块 block partition和pin assignment细节盘点
  • C++算法(数据结构)版
  • 《深度解构:React与Redux构建复杂表单的底层逻辑与实践》