已更新 2025年7月

xTaskNotifyGive 和 xTaskNotifyGiveIndexed

[RTOS 任务通知 API]

task.h

1 BaseType_t xTaskNotifyGive( TaskHandle_t xTaskToNotify );
2
3 BaseType_t xTaskNotifyGiveIndexed( TaskHandle_t xTaskToNotify,
4 UBaseType_t uxIndexToNotify );

每项任务都有一个“任务通知”数组(或简称“通知”), 每条通知都包含一个状态和一个 32 位的值。直达任务通知是 直接发送给任务的事件,可以解除接收任务的阻塞状态, 还可以通过多种不同的方式更新接收任务的某个通知值。 例如,通知可覆盖接收任务的某个通知值,或仅设置 接收任务某个通知值中的一个或多个位。

xTaskNotifyGive() 宏可在 将任务通知用作速度更快的轻量级二进制或计数信号量的替代方案时使用。 FreeRTOS 信号量通过 xSemaphoreGive() API 函数释放,而 xTaskNotifyGive() 与其等效,使用接收 RTOS 任务的某个通知值代替信号量。

xTaskNotifyGive() 与 xTaskNotifyGiveIndexed() 是等效宏,唯一区别在于 xTaskNotifyGiveIndexed() 可以操作数组中的任何任务通知,而 xTaskNotifyGive() 总是操作数组中索引为 0 的任务通知。

当任务通知值用作二进制或计数信号量的等效物时, 接收通知的任务应该使用 ulTaskNotifyTake() API 函数来等待通知, 而不是使用 xTaskNotifyWait() API 函数。

**注意:**数组中的所有通知均独立操作, 即一项任务在同一时间只能在数组中的一条通知上处于阻塞状态,并且不会被发送到其他数组索引的通知解除阻塞状态。

xTaskNotifyGive() 不能在中断服务程序中调用。 请使用 vTaskNotifyGiveFromISR() 代替。

必须在 FreeRTOSConfig.h 中将 configUSE_TASK_NOTIFICATIONS 设置为 1 (或保留为未定义状态),才可使用这些宏。常量 configTASK_NOTIFICATION_ARRAY_ENTRIES 决定了 每项任务的任务通知数组中的索引数。

向后兼容性信息:

在 FreeRTOS V10.4.0 之前,每项任务只有一个“通知值”, 所有任务通知 API 函数都只能操作这一个值。用通知值数组 替代单个通知值需要 一组新的 API 函数,以处理数组中的特定通知。 xTaskNotifyGive() 是原始 API 函数, 为保持向后兼容, 始终操作数组中索引为 0 的通知值。调用 xTaskNotifyGive() 等同于调用 xTaskNotifyGiveIndexed(),其中 uxIndexToNotify 参数设置为 0。

参数:

  • xTaskToNotify

    接收通知的 RTOS 任务的句柄,通知值会递增。可通过以下方法获取任务句柄: 使用 xTaskCreate() 创建任务,并通过 pxCreatedTask 参数获取句柄; 使用 xTaskCreateStatic() 创建任务,并存储返回值作为句柄; 调用 xTaskGetHandle(),通过任务名称获取句柄。当前正在执行的 RTOS 任务的句柄 由 xTaskGetCurrentTaskHandle() API 函数返回。

  • uxIndexToNotify

    目标任务的通知值数组中要向其发送通知的索引。 uxIndexToNotify 必须小于 configTASK_NOTIFICATION_ARRAY_ENTRIES。 xTaskNotifyGive() 没有此参数,并且总是将通知发送到索引 0。

返回:

xTaskNotifyGiveIndexed() 是一个宏,调用 xTaskNotifyIndexed(), 并将 eAction 参数设置为 eIncrement,因此所有调用都返回 pdPASS。

用法示例:

[更多示例请参阅 RTOS 任务通知主页面]

1/* Prototypes of the two tasks created by main(). */
2static void prvTask1( void *pvParameters );
3static void prvTask2( void *pvParameters );
4
5
6/* Handles for the tasks create by main(). */
7static TaskHandle_t xTask1 = NULL, xTask2 = NULL;
8
9/* Create two tasks that send notifications back and forth to each other,
10 then start the RTOS scheduler. */
11void main( void )
12{
13 xTaskCreate( prvTask1, "Task1", 200, NULL, tskIDLE_PRIORITY, &xTask1 );
14 xTaskCreate( prvTask2, "Task2", 200, NULL, tskIDLE_PRIORITY, &xTask2 );
15 vTaskStartScheduler();
16}
17
18/*-----------------------------------------------------------*/
19
20/* prvTask1() uses the 'indexed' version of the API. */
21static void prvTask1( void *pvParameters )
22{
23 for( ;; )
24 {
25 /* Send notification to prvTask2(), bringing it out of the
26 Blocked state. */
27 xTaskNotifyGiveIndexed( xTask2, 0 );
28
29 /* Block to wait for prvTask2() to notify this task. */
30 ulTaskNotifyTakeIndexed( 0, pdTRUE, portMAX_DELAY );
31 }
32}
33
34/*-----------------------------------------------------------*/
35
36/* prvTask2() uses the original version of the API (without the
37 'Indexed'). */
38static void prvTask2( void *pvParameters )
39{
40 for( ;; )
41 {
42 /* Block to wait for prvTask1() to notify this task. */
43 ulTaskNotifyTake( pdTRUE, portMAX_DELAY );
44
45 /* Send a notification to prvTask1(), bringing it out of the
46 Blocked state. */
47 xTaskNotifyGive( xTask1 );
48 }
49}