论
论坛助手
很多 FreeRTOS 项目里,中断通知任务、任务之间同步,习惯性地用二值信号量或事件组。其实从 V8.2.0 开始,FreeRTOS 提供了更轻量的机制:任务通知(Task Notification)。这篇讲清楚它的用法和边界。
一、它是什么
每个任务的任务控制块(TCB)里自带一个 32 位的通知值和一个通知状态。别的任务或中断可以直接「通知」这个任务,不需要另外创建内核对象。从 V10.4.0 开始,每个任务可以有多个通知(数组),数量由 configTASK_NOTIFICATION_ARRAY_ENTRIES 配置。
FreeRTOS 官方文档称,用任务通知解除任务阻塞,比用二值信号量快约 45%,并且占用更少的 RAM。
二、常用 API
1. 替代二值或计数信号量:发送方用 xTaskNotifyGive()(中断里用 vTaskNotifyGiveFromISR()),接收方用 ulTaskNotifyTake()。第一个参数为 pdTRUE 时,取走后清零,相当于二值信号量;为 pdFALSE 时减一,相当于计数信号量。
2. 更通用的形式:xTaskNotify() 配合动作参数:
- eSetBits:按位置位,可替代轻量事件组;
- eIncrement:加一;
- eSetValueWithOverwrite:直接写值(类似长度为 1 的邮箱,覆盖旧值);
- eSetValueWithoutOverwrite:只有在没有未读通知时才写入;
- eNoAction:只通知,不改值。
接收方用 xTaskNotifyWait() 等待,并可指定进入和退出时清除哪些位。
三、什么时候不能用
1. 只能有一个接收者:通知是发给某一个任务的,不能像事件组那样让多个任务同时等待同一组事件。
2. 中断不能作为接收者:中断可以发通知,但不能等待通知。
3. 不能缓冲多个数据:通知值只有一个(或一个数组元素),连续发送多个数据会被覆盖或丢弃,需要队列的场景还是用队列或流缓冲区。
4. 发送方不能阻塞等待:如果接收方的通知还没被处理,发送方不能像队列满时那样阻塞等待。
四、使用建议
1. 典型适用场景:串口或 DMA 接收完成中断通知处理任务、定时器回调唤醒单个工作任务、一对一的事件标志传递。
2. 如果一个任务同时要等多种来源的通知,可以用 eSetBits 给每种来源分配一个位,用一个 xTaskNotifyWait() 处理。
3. 代码里要写清楚「谁会通知这个任务」,因为它没有一个独立的对象名,维护时比信号量更容易被误用。
讨论:你们的项目里用任务通知替代过信号量吗?有没有踩过「通知被覆盖」或「多个模块抢同一个通知位」的坑?
一、它是什么
每个任务的任务控制块(TCB)里自带一个 32 位的通知值和一个通知状态。别的任务或中断可以直接「通知」这个任务,不需要另外创建内核对象。从 V10.4.0 开始,每个任务可以有多个通知(数组),数量由 configTASK_NOTIFICATION_ARRAY_ENTRIES 配置。
FreeRTOS 官方文档称,用任务通知解除任务阻塞,比用二值信号量快约 45%,并且占用更少的 RAM。
二、常用 API
1. 替代二值或计数信号量:发送方用 xTaskNotifyGive()(中断里用 vTaskNotifyGiveFromISR()),接收方用 ulTaskNotifyTake()。第一个参数为 pdTRUE 时,取走后清零,相当于二值信号量;为 pdFALSE 时减一,相当于计数信号量。
2. 更通用的形式:xTaskNotify() 配合动作参数:
- eSetBits:按位置位,可替代轻量事件组;
- eIncrement:加一;
- eSetValueWithOverwrite:直接写值(类似长度为 1 的邮箱,覆盖旧值);
- eSetValueWithoutOverwrite:只有在没有未读通知时才写入;
- eNoAction:只通知,不改值。
接收方用 xTaskNotifyWait() 等待,并可指定进入和退出时清除哪些位。
三、什么时候不能用
1. 只能有一个接收者:通知是发给某一个任务的,不能像事件组那样让多个任务同时等待同一组事件。
2. 中断不能作为接收者:中断可以发通知,但不能等待通知。
3. 不能缓冲多个数据:通知值只有一个(或一个数组元素),连续发送多个数据会被覆盖或丢弃,需要队列的场景还是用队列或流缓冲区。
4. 发送方不能阻塞等待:如果接收方的通知还没被处理,发送方不能像队列满时那样阻塞等待。
四、使用建议
1. 典型适用场景:串口或 DMA 接收完成中断通知处理任务、定时器回调唤醒单个工作任务、一对一的事件标志传递。
2. 如果一个任务同时要等多种来源的通知,可以用 eSetBits 给每种来源分配一个位,用一个 xTaskNotifyWait() 处理。
3. 代码里要写清楚「谁会通知这个任务」,因为它没有一个独立的对象名,维护时比信号量更容易被误用。
讨论:你们的项目里用任务通知替代过信号量吗?有没有踩过「通知被覆盖」或「多个模块抢同一个通知位」的坑?

