Przeglądaj źródła

wiki: 14-任务通知新增实验4 xTaskNotifyIndexed 1对多通知

OpenCode 1 dzień temu
rodzic
commit
d06118266f

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

@@ -89,6 +89,9 @@ FreeRTOS 已经有队列、信号量、事件标志组这些 IPC 机制,为什
 | `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` | 中断中发送(信号量模式) |
 
@@ -268,12 +271,109 @@ void task2(void *pvParameters)
 }
 ```
 
+### 实验4:xTaskNotifyIndexed — 通知数组 1对多 (P19)
+
+**需求**:KEY1 → task2 通知数组[0] = 10,KEY2 → task2 通知数组[1] = 20,KEY3 → task3 通知数组[0] = 99。每个任务通过 `xTaskNotifyWaitIndexed(index)` 阻塞读取指定数组元素。
+
+**原理**:`configTASK_NOTIFICATION_ARRAY_ENTRIES = 3` 使每个任务的 TCB 中有一个长度 3 的 `uint32_t` 通知数组。`xTaskNotifyIndexed(task, index, ...)` 本质是**写 task->notifications[index]**,`xTaskNotifyWaitIndexed(index, ...)` 本质是**阻塞读 task->notifications[index]**。
+
+**代码来源:**`22_EX_TaskNotify/Core/Src/freertos_demo.c`
+
+```c
+/* configTASK_NOTIFICATION_ARRAY_ENTRIES = 3 使每个任务拥有 3 个通知数组元素 */
+
+void task1(void *const pvParameters)
+{
+  uint8_t key = 0;
+  BaseType_t res = 0;
+  while (1)
+  {
+    key = Key_Detect();
+    if (key == KEY1_PRESS)
+    {
+      /* xTaskNotifyIndexed = 写 task2 通知数组[0] = 10(覆写) */
+      res = xTaskNotifyIndexed(
+          task2_handle, 0, 10, eSetValueWithOverwrite
+      );
+      if (res == pdPASS)
+        printf("task1: task2->通知数组[0] = 10\r\n");
+    }
+    else if (key == KEY2_PRESS)
+    {
+      /* xTaskNotifyIndexed = 写 task2 通知数组[1] = 20(覆写) */
+      res = xTaskNotifyIndexed(
+          task2_handle, 1, 20, eSetValueWithOverwrite
+      );
+      if (res == pdPASS)
+        printf("task1: task2->通知数组[1] = 20\r\n");
+    }
+    else if (key == KEY3_PRESS)
+    {
+      /* xTaskNotifyIndexed = 写 task3 通知数组[0] = 99(覆写) */
+      res = xTaskNotifyIndexed(
+          task3_handle, 0, 99, eSetValueWithOverwrite
+      );
+      if (res == pdPASS)
+        printf("task1: task3->通知数组[0] = 99\r\n");
+    }
+    vTaskDelay(500);
+  }
+}
+
+void task2(void *const pvParameters)
+{
+  uint32_t notify_value = 0;
+  BaseType_t res = 0;
+  while (1)
+  {
+    printf("task2阻塞等待通知数组[0]...\r\n");
+
+    /* xTaskNotifyWaitIndexed(0) = 阻塞读通知数组[0],出口清零 */
+    res = xTaskNotifyWaitIndexed(
+        0, 0x00000000, 0xffffffff, &notify_value, portMAX_DELAY
+    );
+    if (res == pdTRUE)
+      printf("task2: 通知数组[0] = %ld\r\n", notify_value);
+
+    printf("task2阻塞等待通知数组[1]...\r\n");
+
+    /* xTaskNotifyWaitIndexed(1) = 阻塞读通知数组[1],出口清零 */
+    res = xTaskNotifyWaitIndexed(
+        1, 0x00000000, 0xffffffff, &notify_value, portMAX_DELAY
+    );
+    if (res == pdTRUE)
+      printf("task2: 通知数组[1] = %ld\r\n", notify_value);
+
+    vTaskDelay(200);
+  }
+}
+
+void task3(void *const pvParameters)
+{
+  uint32_t notify_value = 0;
+  BaseType_t res = 0;
+  while (1)
+  {
+    printf("task3阻塞等待通知数组[0]...\r\n");
+
+    /* xTaskNotifyWaitIndexed(0) = 阻塞读通知数组[0],出口清零 */
+    res = xTaskNotifyWaitIndexed(
+        0, 0x00000000, 0xffffffff, &notify_value, portMAX_DELAY
+    );
+    if (res == pdTRUE)
+      printf("task3: 通知数组[0] = %ld\r\n", notify_value);
+
+    vTaskDelay(200);
+  }
+}
+```
+
 ### 关键配置
 
 ```c
 /* FreeRTOSConfig.h */
 #define configUSE_TASK_NOTIFICATIONS             1   /* 使能任务通知(默认已使能) */
-#define configTASK_NOTIFICATION_ARRAY_ENTRIES    1   /* 通知数组大小,v10.4起支持多通知 */
+#define configTASK_NOTIFICATION_ARRAY_ENTRIES    3   /* 通知数组大小,v10.4起支持多通知。实验1-3用1,实验4用3 */
 ```
 
 ## 核心函数速查表