Browse Source

fix: 修正14-任务通知部分错误描述

OpenCode 1 day ago
parent
commit
1bde28fdbd

+ 26 - 23
X-Knowledge-Base/raw/Joplin/嵌入式+Linux/FreeRTOS学习笔记/14-任务通知.md

@@ -34,12 +34,14 @@ FreeRTOS 已经有队列、信号量、事件标志组这些 IPC 机制,为什
 **⚠ 注意:`xTaskNotifyGive()` 的本质**:查看源码发现 `xTaskNotifyGive()` 其实是一个**宏**,展开后等价于 `xTaskNotify(xTaskToNotify, 0, eIncrement)`。也就是说"信号量模式"在底层和"消息邮箱/事件组模式"使用的是同一个 `xTaskNotify()` 函数,只是 `eAction` 参数不同。三种模式的发送端完全可以统一理解为"调用 xTaskNotify 配上不同的 eAction 参数"。
 
 **普通 IPC 的通信路径**:
+
 ```
 任务 A → [创建队列/信号量对象] → 放入数据 → 队列/信号量 → 任务 B 取出数据
                                  └── 中间对象(额外分配内存)──┘
 ```
 
 **任务通知的通信路径**:
+
 ```
 任务 A → 直接写入任务 B 的 TCB
          └── 不创建任何对象 ──┘
@@ -61,39 +63,40 @@ FreeRTOS 已经有队列、信号量、事件标志组这些 IPC 机制,为什
 
 通知值的 32 位可以灵活解释,由此衍生出三种使用模式,替代三种传统 IPC:
 
-| 模式 | 对应传统 IPC | 发送函数 | 接收函数 | 32 位值的用法 |
-|------|-------------|---------|---------|--------------|
-| **信号量模式** | 二值/计数信号量 | `xTaskNotifyGive()` | `ulTaskNotifyTake()` | 当作计数器:Give 加 1,Take 减 1 |
-| **消息邮箱模式** | 队列(单消息) | `xTaskNotify(..., eSetValueWithOverwrite)` | `xTaskNotifyWait()` | 当作消息容器:覆写/条件覆写 32 位值 |
-| **事件标志组模式** | 事件标志组 | `xTaskNotify(..., eSetBits)` | `xTaskNotifyWait()` | 当作位图:按位 OR 设置标志位 |
+| 模式                     | 对应传统 IPC    | 发送函数                                     | 接收函数               | 32 位值的用法                       |
+| ------------------------ | --------------- | -------------------------------------------- | ---------------------- | ----------------------------------- |
+| **信号量模式**     | 二值/计数信号量 | `xTaskNotifyGive()`                        | `ulTaskNotifyTake()` | 当作计数器:Give 加 1,Take 减 1    |
+| **消息邮箱模式**   | 队列(单消息)  | `xTaskNotify(..., eSetValueWithOverwrite)` | `xTaskNotifyWait()`  | 当作消息容器:覆写/条件覆写 32 位值 |
+| **事件标志组模式** | 事件标志组      | `xTaskNotify(..., eSetBits)`               | `xTaskNotifyWait()`  | 当作位图:按位 OR 设置标志位        |
 
 **一句话选型**:
+
 - 只需通知对方"事件发生了" → 信号量模式(最轻量)
 - 需要传递一个数值给对方 → 消息邮箱模式
 - 需要多个条件的组合触发 → 事件标志组模式
 
 ### 核心劣势(与传统 IPC 对比)
 
-| 对比项 | 队列/信号量/事件组 | 任务通知 |
-|--------|-------------------|---------|
-| 通信方向 | 多对多(多个任务可发/收) | 只能一对一(一个任务只有一个通知值) |
-| 数据缓存 | 队列可缓存多条消息 | 只能缓存一个 32 位值(覆写会丢数据) |
-| ISR 接收 | 可接收 | **不能接收**(无 FromISR 版本接收函数) |
-| 创建步骤 | 需先 Create 对象 | **无需创建**,直接用 |
+| 对比项   | 队列/信号量/事件组        | 任务通知                                      |
+| -------- | ------------------------- | --------------------------------------------- |
+| 通信方向 | 多对多(多个任务可发/收) | 只能一对一(一个任务只有一个通知值)          |
+| 数据缓存 | 队列可缓存多条消息        | 只能缓存一个 32 位值(覆写会丢数据)          |
+| ISR 接收 | 可接收                    | **不能接收**(无 FromISR 版本接收函数) |
+| 创建步骤 | 需先 Create 对象          | **无需创建**,直接用                    |
 
 ### 核心API
 
-| 函数 | 参数 | 功能简述 |
-|------|------|---------|
-| `xTaskNotifyGive()` | `xTaskToNotify` | 发送通知(信号量模式),通知值 +1 |
-| `ulTaskNotifyTake()` | `xClearCountOnExit`, `xTicksToWait` | 接收通知(信号量模式),返回通知值 |
-| `xTaskNotify()` | `xTaskToNotify`, `ulValue`, `eAction` | 发送通知(带值),eAction 控制写/OR/覆写行为 |
-| `xTaskNotifyWait()` | `ulBitsToClearOnEntry`, `ulBitsToClearOnExit`, `pulNotificationValue`, `xTicksToWait` | 接收通知(带值),可获取通知值和清除指定位 |
-| `xTaskNotifyIndexed()` | `xTaskToNotify, uxIndex, ulValue, eAction` | 写目标任务通知数组指定元素 |
-| `xTaskNotifyWaitIndexed()` | `uxIndex, ...` | 阻塞读本任务通知数组指定元素 |
-| `ulTaskNotifyTakeIndexed()` | `uxIndex, ...` | 信号量模式取通知数组指定元素 |
-| `xTaskNotifyFromISR()` | 同上+ISR 版本 | 中断中发送通知 |
-| `vTaskNotifyGiveFromISR()` | `xTaskToNotify`, `pxHigherPriorityTaskWoken` | 中断中发送(信号量模式) |
+| 函数                          | 参数                                                                                          | 功能简述                                     |
+| ----------------------------- | --------------------------------------------------------------------------------------------- | -------------------------------------------- |
+| `xTaskNotifyGive()`         | `xTaskToNotify`                                                                             | 发送通知(信号量模式),通知值 +1            |
+| `ulTaskNotifyTake()`        | `xClearCountOnExit`, `xTicksToWait`                                                       | 接收通知(信号量模式),返回通知值           |
+| `xTaskNotify()`             | `xTaskToNotify`, `ulValue`, `eAction`                                                   | 发送通知(带值),eAction 控制写/OR/覆写行为 |
+| `xTaskNotifyWait()`         | `ulBitsToClearOnEntry`, `ulBitsToClearOnExit`, `pulNotificationValue`, `xTicksToWait` | 接收通知(带值),可获取通知值和清除指定位   |
+| `xTaskNotifyIndexed()`      | `xTaskToNotify, uxIndex, ulValue, eAction`                                                  | 写目标任务通知数组指定元素                   |
+| `xTaskNotifyWaitIndexed()`  | `uxIndex, ...`                                                                              | 阻塞读本任务通知数组指定元素                 |
+| `ulTaskNotifyTakeIndexed()` | `uxIndex, ...`                                                                              | 信号量模式取通知数组指定元素                 |
+| `xTaskNotifyFromISR()`      | 同上+ISR 版本                                                                                 | 中断中发送通知                               |
+| `vTaskNotifyGiveFromISR()`  | `xTaskToNotify`, `pxHigherPriorityTaskWoken`                                              | 中断中发送(信号量模式)                     |
 
 ## 实验
 
@@ -398,7 +401,7 @@ void task3(void *const pvParameters)
 
 ## 常见问题与避坑
 
-1. **任务通知只能一对一**:一个任务只有一个通知值。不能像事件标志组那样多个任务等待同一个事件。
+1. **任务通知只能一对一**:v10.4 之前一个任务只有一个通知值。不能像事件标志组那样多个任务等待同一个事件。
 2. **ISR 不可接收通知**:没有 `xTaskNotifyWaitFromISR()` 函数。接收任务通知只能在任务上下文中进行。
 3. **通知值溢出不提示**:`xTaskNotifyGive()` 使 32 位通知值递增,溢出后归零且无错误提示。
 4. **信号量模式的 xClearCountOnExit**: