FreeRTOS学习笔记-任务通知(FreeRTOS中文官网)

RTOS 任务通知
[API]

RTOS 任务通知 API 函数:

xTaskNotifyGive / xTaskNotifyGiveIndexed
[ RTOS任务通知 API ]


task.h

 BaseType_t xTaskNotifyGive( TaskHandle_t xTaskToNotify );

 BaseType_t xTaskNotifyGiveIndexed( TaskHandle_t xTaskToNotify, 
                                    UBaseType_t uxIndexToNotify );

每个任务都有一组“任务通知” (或仅“通知” ) ,每个 通知都包含状态和一个 32 位值。 直达任务通知是直接发送至任务的事件, 可以取消接收任务的阻塞状态,还 可以选择通过多种方式更新接收任务的某个通知值。 例如,通知可覆盖接收任务的通知值中的一个,或仅设置 更多位。

当任务通知 用作轻量级且更快的二进制或计数信号量 替代方案时,可以使用宏 xTaskNotifyGive ()。 FreeRTOS 信号用通过使用 xSemaphoreGive () API 函数给出,而 xTaskNotifyGive () 与其等效,使用接收 RTOS 任务的一个通知值代替信号量。

xTaskNotifyGive () 和 xTaskNotifyGiveIndexed () 是等效宏——唯一的区别是 xTaskNotifyGiveIndexed () 可以在始终在数组内任何任务通知上操作 ,而 xTaskNotifyGive () 始终在数组索引 0 处的任务通知上运行。

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

注意: 数组中每个通知都独立运行——任务一次只能阻止数组中的一个通知,并且不会被发送到任何其他数组索引的通知取消阻止。

xTaskNotifyGive () 不能从中断服务例程调用。 使用 vTaskNotifyGiveFromISR() 代替。

configUSE_TASK_NOTIFICATIONS 必须在 FreeRTOSConfig.h 中设置为 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 发送通知。

Returns:

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


用法示例:

[更多示例来自主 RTOS任务通知页面]

/* Prototypes of the two tasks created by main(). */
static void prvTask1( void *pvParameters );
static void prvTask2( void *pvParameters );

/* Handles for the tasks create by main(). */
static TaskHandle_t xTask1 = NULL, xTask2 = NULL;

/* Create two tasks that send notifications back and forth to each other, 
then start the RTOS scheduler. */
void main( void )
{
    xTaskCreate( prvTask1, "Task1", 200, NULL, tskIDLE_PRIORITY, &xTask1 );
    xTaskCreate( prvTask2, "Task2", 200, NULL, tskIDLE_PRIORITY, &xTask2 );
    vTaskStartScheduler();
}
/*-----------------------------------------------------------*/

/* prvTask1() uses the 'indexed' version of the API. */
static void prvTask1( void *pvParameters )
{
    for( ;; )
    {
        /* Send notification to prvTask2(), bringing it out of the 
        Blocked state. */
        xTaskNotifyGiveIndexed( xTask2, 0 );

        /* Block to wait for prvTask2() to notify this task. */
        ulTaskNotifyTakeIndexed( 0, pdTRUE, portMAX_DELAY );
    }
}
/*-----------------------------------------------------------*/

/* prvTask2() uses the original version of the API (without the 
'Indexed'). */
static void prvTask2( void *pvParameters )
{
    for( ;; )
    {
        /* Block to wait for prvTask1() to notify this task. */
        ulTaskNotifyTake( pdTRUE, portMAX_DELAY );

        /* Send a notification to prvTask1(), bringing it out of the 
        Blocked state. */
        xTaskNotifyGive( xTask1 );
    }
}

 

vTaskNotifyGiveFromISR / vTaskNotifyGiveIndexedFromISR
[RTOS 任务通知 API]


task.h

 void vTaskNotifyGiveFromISR( TaskHandle_t xTaskToNotify,
                              BaseType_t *pxHigherPriorityTaskWoken );

 void vTaskNotifyGiveIndexedFromISR( TaskHandle_t xTaskHandle, 
                                     UBaseType_t uxIndexToNotify, 
                                     BaseType_t *pxHigherPriorityTaskWoken );

可在中断服务程序 (ISR) 中使用的 xTaskNotifyGive() 和 xTaskNotifyGiveIndexed() 的版本。 请参阅文档页面,以获取关于 API 函数 xTaskNotifyGive() 的 操作描述和必要的配置参数, 以及向后兼容性信息。

参数:

xTaskToNotify  正被通知的 RTOS 任务的句柄,且该任务的通知值 正在递增。

要获取任务句柄,请使用 xTaskCreate() 创建任务并使用 pxCreatedTask 参数,或使用返回值创建任务 xTaskCreateStatic() 并存储该值,或在 xTaskGetHandle() 调用中使用任务的名称。

当前执行的 RTOS 任务的句柄通过以下方式 由 xTaskGetCurrentTaskHandle() API 函数返回。

uxIndexToNotify  目标任务通知值数组中的索引, 通知值将发送给该索引。

uxIndexToNotify 必须小于 configTASK_NOTIFICATION_ARRAY_ENTRIES。

xTaskNotifyGiveFromISR() 不具有此参数,并且始终 将通知发送到索引 0。

pxHigherPriorityTaskWoken *pxHigherPriorityTaskWoken 必须初始化为 0。

如果发送通知导致任务解除阻塞,并且被阻塞任务的优先级高于 当前运行的任务,vTaskNotifyGiveFromISR() 会将 *pxHigherPriorityTaskWoken 设 xTaskNotifyFromISR() 会将 *pxHigherPriorityTaskWoken 。

如果 vTaskNotifyGiveFromISR() 将此值设置为 pdTRUE , 则应在中断退出之前请求上下文切换 。 请参阅以下示例。

pxHigherPriorityTaskWoken 为可选参数,且可 设置为 NULL。


用法示例:

[更多示例来自主 RTOS 任务通知页面]

/* This is an example of a transmit function in a generic peripheral driver.  An
RTOS task calls the transmit function, then waits in the Blocked state (so not
using an CPU time) until it is notified that the transmission is complete.  The
transmission is performed by a DMA, and the DMA end interrupt is used to notify
the task. */

static TaskHandle_t xTaskToNotify = NULL;

/* The peripheral driver's transmit function. */
void StartTransmission( uint8_t *pcData, size_t xDataLength )
{
    /* At this point xTaskToNotify should be NULL as no transmission is in
    progress.  A mutex can be used to guard access to the peripheral if
    necessary. */
    configASSERT( xTaskToNotify == NULL );

    /* Store the handle of the calling task. */
    xTaskToNotify = xTaskGetCurrentTaskHandle();

    /* Start the transmission - an interrupt is generated when the transmission
    is complete. */
    vStartTransmit( pcData, xDatalength );
}
/*-----------------------------------------------------------*/

/* The transmit end interrupt. */
void vTransmitEndISR( void )
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;

    /* At this point xTaskToNotify should not be NULL as a transmission was
    in progress. */
    configASSERT( xTaskToNotify != NULL );

    /* Notify the task that the transmission is complete. */
    vTaskNotifyGiveIndexedFromISR( xTaskToNotify, 0, &xHigherPriorityTaskWoken );

    /* There are no transmissions in progress, so no tasks to notify. */
    xTaskToNotify = NULL;

    /* If xHigherPriorityTaskWoken is now set to pdTRUE then a context switch
    should be performed to ensure the interrupt returns directly to the highest
    priority task.  The macro used for this purpose is dependent on the port in
    use and may be called portEND_SWITCHING_ISR(). */
    portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
/*-----------------------------------------------------------*/

/* The task that initiates the transmission, then enters the Blocked state (so
not consuming any CPU time) to wait for it to complete. */
void vAFunctionCalledFromATask( uint8_t ucDataToTransmit, size_t xDataLength )
{
uint32_t ulNotificationValue;
const TickType_t xMaxBlockTime = pdMS_TO_TICKS( 200 );

    /* Start the transmission by calling the function shown above. */
    StartTransmission( ucDataToTransmit, xDataLength );

    /* Wait for the transmission to complete. */
    ulNotificationValue = ulTaskNotifyTakeIndexed( 0, pdFALSE, xMaxBlockTime );

    if( ulNotificationValue == 1 )
    {
        /* The transmission ended as expected. */
    }
    else
    {
        /* The call to ulTaskNotifyTake() timed out. */
    }
}

ulTaskNotifyTake / ulTaskNotifyTakeIndexed
[RTOS 任务通知 API]


task.h

 uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit,
                            TickType_t xTicksToWait );
 
 uint32_t ulTaskNotifyTakeIndexed( UBaseType_t uxIndexToWaitOn, 
                                   BaseType_t xClearCountOnExit, 
                                   TickType_t xTicksToWait );

每个任务都有一组“任务通知” (或仅“通知” ) ,每个 通知都包含状态和一个 32 位值。 直达任务通知是直接发送至任务的事件, 可以取消接收任务的阻塞状态,还 可以选择通过多种方式更新接收任务的某个通知值。 例如,通知可覆盖接收任务的通知值中的一个,或仅设置 接收任务的通知值中的一个或多个比特位。

ulTaskNotifyTake() 是一个宏,在任务通知 被用作更快、更轻的二进制 或计数信号量替代时使用。 使用 xSemaphoreTake() API 函数获取 FreeRTOS 信号量,ulTaskNotifyTake() 是使用通知值代替信号量的等效宏。

ulTaskNotifyTake() 和 ulTaskNotifyTakeIndexed() 是等效的宏,它们唯一的区别 是 ulTaskNotifyTakeIndexed() 可以在数组内的任何任务通知上运行, 而 ulTaskNotifyTake() 始终在数组索引 0 处的任务通知上运行。

当任务使用通知值作为二进制或计数信号量时, 其他任务和中断应使用 xTaskNotifyGive() 宏,或 eAction 参数设置为 eIncrement 的 xTaskNotify() 函数 (二者等效)。

ulTaskNotifyTake() 可以在退出时清除任务的通知值为 0, 在这种情况下,通知值起到二进制信号量的作用; 或在退出时递减任务的通知值,在这种情况下, 通知值更像是计数信号量。

RTOS 任务可以使用 ulTaskNotifyTake() [可选]进入阻塞状态以等待 任务的通知值。 任务处于阻塞状态时 不消耗任何 CPU 时间。

注意:数组中每个通知都独立运行——在数组中的一个通知上一次只能阻塞一个任务,并且该任务不会被发送到任何其他数组索引处的通知取消阻塞。

然而当通知被挂起时,xTaskNotifyWait() 将返回, 当任务的通知值不为 0 时,ulTaskNotifyTake() 将返回, 并在返回之前递减任务的通知值。

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

向后兼容性信息:
在 FreeRTOS V10.4.0 之前,每个任务有一个单一的“通知值”,且 所有任务通知 API 函数都在该值上运行。用通知值的数组 更换单个通知值需要 新的 API 函数集,该函数集应能在数组内处理 特定通知。 ulTaskNotifyTake() 是原始 API 函数,并且 通过始终在数组内索引 0 处的通知值上运行保持 向后兼容。调用 ulTaskNotifyTake() 等于调用 ulTaskNotifyTakeIndexed(),其中 uxIndexToWaitOn 参数设置为 0。

参数:

uxIndexToWaitOn  调用任务的数组中通知值的索引, 调用任务将在该通知值上等待通知 变成非零。

uxIndexToWaitOn 必须小于 configTASK_NOTIFICATION_ARRAY_ENTRIES。

xTaskNotifyTake() 没有此参数,总是在索引 0 处等待通知。

xClearCountOnExit 如果收到 RTOS 任务通知且 xClearCountOnExit 设置为 pdFALSE,则 RTOS 任务的通知值 在 ulTaskNotifyTake() 退出之前递减。 这 等同于 通过成功调用 xSemaphoreTake() 而递减计数信号量的值。

如果收到 RTOS 任务通知且 xClearCountOnExit 设置为 pdTRUE,则 RTOS 任务的通知值 在 ulTaskNotifyTake() 退出之前重设为 0。 这 等同于在成功调用 xSemaphoreTake() 后 将二进制信号量的值保留为 0 (或为空,或为“不可用” )。

xTicksToWait  在阻塞状态下等待接收通知的最长时间, 如果通知在 ulTaskNotifyTake() 被调用时 尚未挂起。

处于阻塞状态的 RTOS 任务不会消耗 任何 CPU 时间。

时间以 RTOS tick 周期为单位。 宏 pdMS_TO_TICKS() 可以 将以毫秒为单位的时间 转换成以 tick 为单位的时间。

Returns:

被递减或清楚之前的任务通知值的值 (请参阅 xClearCountOnExit 的说明)。


用法示例:

[更多示例来自主 RTOS 任务通知页面]

/* An interrupt handler.  The interrupt handler does not perform any processing,
instead it unblocks a high priority task in which the event that generated the
interrupt is processed.  If the priority of the task is high enough then the
interrupt will return directly to the task (so it will interrupt one task but
return to a different task), so the processing will occur contiguously in time -
just as if all the processing had been done in the interrupt handler itself. */
void vANInterruptHandler( void )
{
BaseType_t xHigherPriorityTaskWoken;

    /* Clear the interrupt. */
    prvClearInterruptSource();

    /* xHigherPriorityTaskWoken must be initialised to pdFALSE.  If calling
    vTaskNotifyGiveFromISR() unblocks the handling task, and the priority of
    the handling task is higher than the priority of the currently running task,
    then xHigherPriorityTaskWoken will automatically get set to pdTRUE. */
    xHigherPriorityTaskWoken = pdFALSE;

    /* Unblock the handling task so the task can perform any processing necessitated
    by the interrupt.  xHandlingTask is the task's handle, which was obtained
    when the task was created. */
    vTaskNotifyGiveIndexedFromISR( xHandlingTask, 0, &xHigherPriorityTaskWoken );

    /* Force a context switch if xHigherPriorityTaskWoken is now set to pdTRUE.
    The macro used to do this is dependent on the port and may be called
    portEND_SWITCHING_ISR. */
    portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
/*-----------------------------------------------------------*/

/* A task that blocks waiting to be notified that the peripheral needs servicing,
processing all the events pending in the peripheral each time it is notified to 
do so. */
void vHandlingTask( void *pvParameters )
{
BaseType_t xEvent;

    for( ;; )
    {
        /* Block indefinitely (without a timeout, so no need to check the function's
        return value) to wait for a notification.  Here the RTOS task notification
        is being used as a binary semaphore, so the notification value is cleared
        to zero on exit.  NOTE!  Real applications should not block indefinitely,
        but instead time out occasionally in order to handle error conditions
        that may prevent the interrupt from sending any more notifications. */
        ulTaskNotifyTakeIndexed( 0,               /* Use the 0th notification */
                                 pdTRUE,          /* Clear the notification value 
                                                     before exiting. */
                                 portMAX_DELAY ); /* Block indefinitely. */

        /* The RTOS task notification is used as a binary (as opposed to a
        counting) semaphore, so only go back to wait for further notifications
        when all events pending in the peripheral have been processed. */
        do
        {
            xEvent = xQueryPeripheral();

            if( xEvent != NO_MORE_EVENTS )
            {
                vProcessPeripheralEvent( xEvent );
            }

        } while( xEvent != NO_MORE_EVENTS );
    }
}

xTaskNotify / xTaskNotifyIndexed
[RTOS 任务通知 API]


task.h

 BaseType_t xTaskNotify( TaskHandle_t xTaskToNotify,
                         uint32_t ulValue,
                         eNotifyAction eAction );

 BaseType_t xTaskNotifyIndexed( TaskHandle_t xTaskToNotify, 
                                UBaseType_t uxIndexToNotify, 
                                uint32_t ulValue, 
                                eNotifyAction eAction );

[如果你使用 RTOS 任务通知来实现二进制或计数 信号量类型行为,请使用更简单的 xTaskNotifyGive() API 函数,而不是 xTaskNotify()]

每个任务都有一个“任务通知”数组(或简称为“通知”),每个 通知都包含状态和一个 32 位值。 直达任务通知是直接发送至任务的事件, 可以取消接收任务的阻塞状态,还 可以选择通过多种方式更新接收任务的某个通知值。 例如,通知可覆写接收任务的某个通知值,或仅设置 接收任务的通知值中的一个或多个比特位。

xTaskNotify() 用于将事件 直接发送到 RTOS 任务并可能取消该任务的阻塞状态,还可选择 以下列方式更新接收任务的通知值:

  • 将 32 位数字写入通知值
  • 添加一个(递增)通知值
  • 设置通知值中的一个或多个位
  • 保持通知值不变

xTaskNotify() 和 xTaskNotifyIndexed() 是等效的函数 - 唯一的区别 是 xTaskNotifyIndexed() 可以对数组内的任何任务通知进行操作, 而 xTaskNotify() 始终对数组索引 0 处的任务通知进行操作。

不得从中断服务例程 (ISR) 调用此函数。 使用 xTaskNotifyFromISR() 代替。

configUSE_TASK_NOTIFICATIONS 必须在 FreeRTOSConfig.h 中设置为 1(或保留为未定义)以使这些函数可用。 常量configTASK_NOTIFICATION_ARRAY_ENTRIES 设置 任务通知的每个任务数组中的索引数量。

向后兼容性信息:
在 FreeRTOS V10.4.0 之前,每个任务有一个单一的“通知值”,且 所有任务通知 API 函数都在该值上运行。用通知值的数组 更换单个通知值需要 新的 API 函数集,该函数集应能在数组内处理 数组中的特定通知。 xTaskNotify() 是原始 API 函数,并且 通过始终对数组中索引 0 处的通知值进行操作来保持向后兼容 。调用 xTaskNotify() 相当于调用 xTaskNotifyIndexed(), 其 uxIndexToNotify 参数设置为 0。

参数:

xTaskToNotify  正在通知的 RTOS 任务的句柄。 这是目标任务。

要获取任务句柄, xTaskCreate() 创建任务并使用 pxCreatedTask 参数,或使用返回值创建任务xTaskCreateStatic() 并存储该值,或在 xTaskGetHandle() 调用中使用任务的名称。

当前执行的 RTOS 任务的句柄通过以下方式 由 xTaskGetCurrentTaskHandle() API 函数返回。

uxIndexToNotify 目标任务通知值数组中的索引, 通知值将发送给该索引。

uxIndexToNotify 必须小于 configTASK_NOTIFICATION_ARRAY_ENTRIES。

xTaskNotify() 没有此参数,并且始终向索引 0 发送通知。

ulValue  用于更新目标任务的通知值。 请参阅下面 eAction 参数的说明。
eAction  一种枚举类型,可以采用 下表中记录的值之一来执行相关操作。
eAction 设置已执行的操作
eNoAction目标任务接收事件,但其 通知值未更新。 在这种情况下,不使用 ulValue。

eSetBits目标任务的通知值 使用 ulValue 按位或运算。 例如, 如果 ulValue 设置为 0x01,则将在 目标任务的通知值中设置位 0。 同样,如果 ulValue 为 0x04,则将在 目标任务的通知值中设置位 2。 通过这种方式,RTOS 任务通知机制 可以用作 事件组的轻量级替代方案。

eIncrement目标任务的通知值 自增 1,使得调用 xTaskNotify() 相当于调用 xTaskNotifyGive()。 在这种情况下,不使用 ulValue。
eSetValueWithOverwrite目标任务的通知值 无条件设置为 ulValue。 因此, RTOS 任务通知机制可用作 xQueueOverwrite() 的轻量级替代方案。
eSetValueWithoutOrwrite如果目标任务没有 挂起的通知,则其通知值 将设置为 ulValue。

如果目标任务已经有 挂起的通知,则不会更新其通知值, 因为这样做会覆盖 之前使用的值。 在这种情况下, 调用 xTaskNotify() 失败,返回 pdFALSE。

因此,RTOS 任务通知机制可 在长度为 1 的队列上用作 xQueueSend() 在长度为 的轻量级替代方案。

Returns:

除 eAction 设置为 eSetValueWithoutOverwrite 且目标任务的通知值 因目标任务已有挂起的通知而无法更新之外, 在所有情况下均返回 pdPASS。


用法示例:

[更多示例来自主 RTOS 任务通知页面]

/* Set bit 8 in the 0th notification value of the task referenced by 
xTask1Handle. */
xTaskNotifyIndexed( xTask1Handle, 0, ( 1UL << 8UL ), eSetBits );

/* Send a notification to the task referenced by xTask2Handle, potentially
removing the task from the Blocked state, but without updating the task's
notification value. */
xTaskNotify( xTask2Handle, 0, eNoAction );

/* Set the notification value of the task referenced by xTask3Handle to 0x50,
even if the task had not read its previous notification value. */
xTaskNotify( xTask3Handle, 0x50, eSetValueWithOverwrite );

/* Set the notification value of the task referenced by xTask4Handle to 0xfff,
but only if to do so would not overwrite the task's existing notification
value before the task had obtained it (by a call to xTaskNotifyWait()
or ulTaskNotifyTake()). */
if( xTaskNotify( xTask4Handle, 0xfff, eSetValueWithoutOverwrite ) == pdPASS )
{
    /* The task's notification value was updated. */
}
else
{
    /* The task's notification value was not updated. */
}

xTaskNotifyAndQuery / xTaskNotifyAndQueryIndexed
[RTOS 直达任务通知 API]


task.h

 BaseType_t xTaskNotifyAndQuery( TaskHandle_t xTaskToNotify,
                                 uint32_t ulValue,
                                 eNotifyAction eAction,
                                 uint32_t *pulPreviousNotifyValue );
 
 BaseType_t xTaskNotifyAndQueryIndexed( TaskHandle_t xTaskToNotify, 
                                        UBaseType_t uxIndexToNotify, 
                                        uint32_t ulValue, 
                                        eNotifyAction eAction, 
                                        uint32_t *pulPreviousNotifyValue );

请参阅 RTOS 任务通知了解详情。

xTaskNotifyAndQueryIndexed() 执行的 操作与 xTaskNotifyIndexed() 相同, 还会在附加的 pulPreviousNotifyValue 参数中 返回目标任务的上一个通知值 (调用函数时的通知值,而不是函数返回时的通知值)。

xTaskNotifyAndQuery() 执行的 操作与 xTaskNotify() 相同, 同样,还会在附加的 pulPreviousNotifyValue 参数中 返回目标任务的上一个通知值 (调用函数时的通知值, 而不是函数返回时的通知值)。

不得从中断服务程序 (ISR) 调用此函数。 使用 xTaskNotifyAndQueryFromISR() 代替。

参数:

xTaskToNotify  正在通知的 RTOS 任务的句柄。 这是目标任务。

要获取任务句柄, xTaskCreate() 创建任务并使用 pxCreatedTask 参数,或使用返回值创建任务xTaskCreateStatic() 并存储该值,或在 xTaskGetHandle() 调用中使用任务的名称。

当前执行的 RTOS 任务的句柄通过以下方式 由 xTaskGetCurrentTaskHandle() API 函数返回。

uxIndexToNotify  目标任务通知值数组中的索引, 通知值将发送给该索引。

uxIndexToNotify 必须小于 configTASK_NOTIFICATION_ARRAY_ENTRIES。

ulValue  用于更新目标任务的通知值。 请参阅下面 eAction 参数的说明。
eAction  一种枚举类型,可以采用 下表中记录的值之一来执行相关操作。
pulPreviousNotifyValue 可用于在 xTaskNotifyAndQuery() 操作修改任何位之前 传递目标任务的通知值。

pulPreviousNotifyValue 是一个可选参数, 如不需要,可设置为 NULL。 如果未使用 pulPreviousNotifyValue, 则考虑使用 xTaskNotify() 来 代替 xTaskNotifyAndQuery()。

eAction 设置已执行的操作
eNoAction目标任务接收事件,但其 通知值未更新。 在这种情况下,不使用 ulValue。

eSetBits目标任务的通知值 使用 ulValue 按位或运算。 例如, 如果 ulValue 设置为 0x01,则将在 目标任务的通知值中设置位 0。 同样,如果 ulValue 为 0x04,则将在 目标任务的通知值中设置位 2。 通过这种方式,RTOS 任务通知机制 可以用作 事件组的轻量级替代方案。

eIncrement目标任务的通知值 按 1 递增,使调用 xTaskNotify() 相当于调用 xTaskNotifyGive()。 在这种情况下,不使用 ulValue。
eSetValueWithOverwrite目标任务的通知值 无条件设置为 ulValue。 因此, RTOS 任务通知机制可用作 xQueueOverwrite() 的轻量级替代方案。
eSetValueWithoutOrwrite如果目标任务没有 挂起的通知,则其通知值 将设置为 ulValue。

如果目标任务已经有 挂起的通知,则不会更新其通知值, 因为这样做会覆盖 之前使用的值。 在这种情况下, 调用 xTaskNotify() 失败,返回 pdFALSE。

因此,RTOS 任务通知机制可 在长度为 1 的队列上用作 xQueueSend() 在长度为 的轻量级替代方案。

Returns:

除 eAction 设置为 eSetValueWithoutOverwrite 且目标任务的通知值 因目标任务已有挂起的通知而无法更新之外, 在所有情况下均返回 pdPASS。


用法示例:

uint32_t ulPreviousValue;

/* Set bit 8 in the 0th notification value of the task referenced 
by xTask1Handle. Store the task's previous 0th notification 
value (before bit 8 is set) in ulPreviousValue. */
xTaskNotifyAndQueryIndexed( xTask1Handle, 
                            0, 
                            ( 1UL << 8UL ), 
                            eSetBits, 
                            &ulPreviousValue );

/* Send a notification to the task referenced by xTask2Handle, 
potentially removing the task from the Blocked state, but without 
updating the task's notification value.  Store the tasks notification 
value in ulPreviousValue. */
xTaskNotifyAndQuery( xTask2Handle, 0, eNoAction, &ulPreviousValue );

/* Set the notification value of the task referenced by xTask3Handle 
to 0x50, even if the task had not read its previous notification value. 
The task's previous notification value is of no interest so the last 
parameter is set to NULL. */
xTaskNotifyAndQuery( xTask3Handle, 0x50, eSetValueWithOverwrite,  NULL );

/* Set the notification value of the task referenced by xTask4Handle 
to 0xfff,
but only if to do so would not overwrite the task's existing notification
value before the task had obtained it (by a call to xTaskNotifyWait()
or ulTaskNotifyTake()).  The task's previous notification value is saved
in ulPreviousValue. */
if( xTaskNotifyAndQuery( xTask4Handle,
                         0xfff,
                         eSetValueWithoutOverwrite,
                         &ulPreviousValue ) == pdPASS )
{
    /* The task's notification value was updated. */
}
else
{
    /* The task's notification value was not updated. */
}

xTaskNotifyAndQueryFromISR / xTaskNotifyAndQueryIndexedFromISR
[ RTOS任务通知API 函数]


task.h

 BaseType_t xTaskNotifyAndQueryFromISR( 
                      TaskHandle_t xTaskToNotify,
                      uint32_t ulValue,
                      eNotifyAction eAction,
                      uint32_t *pulPreviousNotifyValue,
                      BaseType_t *pxHigherPriorityTaskWoken );

 BaseType_t xTaskNotifyAndQueryIndexedFromISR( 
                      TaskHandle_t xTaskToNotify,
                      UBaseType_t uxIndexToNotify
                      uint32_t ulValue,
                      eNotifyAction eAction,
                      uint32_t *pulPreviousNotifyValue,
                      BaseType_t *pxHigherPriorityTaskWoken );

请参阅 请参阅RTOS任务通知

xTaskNotifyAndQueryIndexedFromISR() 执行的操作 与xTaskNotifyIndexedFromISR() 执行的操作相同,此外, 还会在附加的 pulPreviousNotifyValue 参数中 返回目标任务的先前通知值 (函数被调用时的通知值,而不是函数返回时的通知值)。

xTaskNotifyAndQueryFromISR() 执行的操作与 xTaskNotifyFromISR() 执行的操作相同,此外 还会在附加的 pulPreviousNotifyValue 参数中 返回目标任务的先前通知值 (函数被调用时的通知值,而不是函数返回时的通知值)。

参数:

xTaskToNotify  正在通知的 RTOS 任务的句柄。 这是目标任务。

要获取任务句柄, xTaskCreate() 创建任务并使用 pxCreatedTask 参数,或使用返回值创建任务 xTaskCreateStatic() 并存储该值,或在 xTaskGetHandle() 调用中使用任务的名称。

当前执行的 RTOS 任务的句柄通过以下方式 由 xTaskGetCurrentTaskHandle() API 函数返回。

uxIndexToNotify  目标任务通知值数组中的索引, 通知值将发送给该索引。

uxIndexToNotify 必须小于 configTASK_NOTIFICATION_ARRAY_ENTRIES。

ulValue  用于更新目标任务的通知值。 请参阅下面 eAction 参数的说明。
eAction  一种枚举类型,可以采用 下表中记录的值之一来执行相关操作。
pulPreviousNotifyValue  可用于在xTaskNotifyAndQuery()操作修改任何位之前 传递目标任务的通知值。

pulPreviousNotifyValue是一个可选参数, 如不需要,可设置为 NULL。 如果未使用 pulPreviousNotifyValue, 则考虑使用 xTaskNotify() 来代替xTaskNotifyAndQuery()。

pxHigherPriorityTaskWoken * pxHigherPriorityTaskWoken必须初始化为pdFALSE (0)。

xTaskNotifyAndQueryFromISR ()将设置* pxHigherPriorityTaskWoken 如果发送通知导致一个任务解除阻塞,且解除阻塞的任务的优先级高于当前正在运行的任务, 那么xTaskNotifyFromISR()将把*pxHigherPriorityTaskWoken设置 为pdTRUE。

如果xTaskNotifyAndQueryFromISR()将该值设置为pdTRUE 那么应该在中断退出之前请求 切换上下文。请参阅以下示例。

pxHigherPriorityTaskWoken 为可选参数,且可 设置为 NULL。

eAction Setting已执行的操作
eNoAction目标任务接收事件,但其 通知值未更新。 在这种情况下,不使用 ulValue。

eSetBits目标任务的通知值 使用 ulValue 按位或运算。 例如, 如果 ulValue 设置为 0x01,则将在 目标任务的通知值中设置位 0。 同样,如果 ulValue 为 0x04,则将在 目标任务的通知值中设置位 2。 通过这种方式,RTOS 任务通知机制 可以用作 事件组的轻量级替代方案。

eIncrement目标任务的通知值 按 1 递增,使调用 xTaskNotify() 相当于调用 xTaskNotifyGive()。 在这种情况下,不使用 ulValue。
eSetValueWithOverwrite目标任务的通知值 无条件设置为 ulValue。 因此, RTOS 任务通知机制可用作 xQueueOverwrite()的轻量级替代方案。
eSetValueWithoutOrwrite如果目标任务没有 挂起的通知,则其通知值 将设置为 ulValue。

如果目标任务已经有 挂起的通知,则不会更新其通知值, 因为这样做会覆盖 之前使用的值。 在这种情况下, 调用 xTaskNotify() 失败,返回 pdFALSE。

因此,RTOS 任务通知机制可 在长度为 1 的队列上用作 xQueueSend() 在长度为 的轻量级替代方案。

Returns:

除 eAction 设置为 eSetValueWithoutOverwrite 且目标任务的通知值 因目标任务已有挂起的通知而无法更新之外, 在所有情况下均返回 pdPASS。


用法示例:

void vAnISR( void )
{
/* Must be Initialised to pdFALSE! */
BaseType_t xHigherPriorityTaskWoken = pdFALSE. 
uint32_t ulPreviousValue;

    /* Set bit 8 in the 0th notification value of the task referenced
    by xTask1Handle. Store the task's previous 0th notification value 
    (before bit 8 is set) in ulPreviousValue. */
    xTaskNotifyAndQueryIndexedFromISR( xTask1Handle,
                                       0,
                                       ( 1UL << 8UL ),
                                       eSetBits,
                                       &ulPreviousValue,
                                       &xHigherPriorityTaskWoken );

    /* The task's previous notification value is saved in 
    ulPreviousValue. */

    /* If the task referenced by xTask1Handle was in the Blocked 
    state, waiting for the notification, then it will now have been 
    moved from the Blocked state to the Ready state.  If its priority 
    is higher than the priority of the currently executing task (the 
    task this interrupt interrupted) then xHigherPriorityTaskWoken will 
    have been set to pdTRUE, and passing the variable into a call to 
    portYIELD_FROM_ISR() will result in the interrupt returning directly 
    to the unblocked task.  If xHigherPriorityTaskWoken is still pdFALSE 
    then passing it into portYIELD_FROM_ISR() will have no effect. */

    portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}

xTaskNotifyFromISR / xTaskNotifyIndexedFromISR
[RTOS 任务通知 API]


task.h

 BaseType_t xTaskNotifyFromISR( TaskHandle_t xTaskToNotify,
                                uint32_t ulValue,
                                eNotifyAction eAction,
                                BaseType_t *pxHigherPriorityTaskWoken );

 BaseType_t xTaskNotifyIndexedFromISR( TaskHandle_t xTaskToNotify, 
                                       UBaseType_t uxIndexToNotify, 
                                       uint32_t ulValue, 
                                       eNotifyAction eAction, 
                                       BaseType_t *pxHigherPriorityTaskWoken );

可从中断服务程序 (ISR) 中使用的 xTaskNotify() 和 xTaskNotifyIndexed() 版本。请参阅 xTaskNotify() API 函数的文档页面,了解有关其操作的描述和必要的配置参数,以及向后兼容性信息。

参数:

xTaskToNotify  正在通知的 RTOS 任务的句柄。 这是目标任务。

要获取任务句柄, xTaskCreate() 创建任务并使用 pxCreatedTask 参数,或使用返回值创建任务 xTaskCreateStatic() 并存储该值,或在 调用 xTaskGetHandle() 中使用任务的名称。

当前执行的 RTOS 任务的句柄通过以下方式 由 xTaskGetCurrentTaskHandle() API 函数返回。

uxIndexToNotify  目标任务通知值数组中的索引, 通知值将发送给该索引。

uxIndexToNotify 必须小于 configTASK_NOTIFICATION_ARRAY_ENTRIES。

xTaskNotifyFromISR() 中没有此参数,总是向索引 0 发送通知。

ulValue  用于更新目标任务的通知值。 请参阅下面 eAction 参数的说明。
eAction  一种枚举类型,可以采用 下表中记录的值之一来执行相关操作。
pxHigherPriorityTaskWoken *pxHigherPriorityTaskWoken 必须初始化为 0。

如果发送通知导致某个任务解除阻塞, 且被解除阻塞的任务的优先级高于当前运行的任务, xTaskNotifyFromISR() 会将 *pxHigherPriorityTaskWoken 设置为 pdTRUE。

如果 xTaskNotifyFromISR() 将此值设置为 pdTRUE, 则应在中断退出之前请求上下文切换 。 请参阅以下示例。

pxHigherPriorityTaskWoken 为可选参数,且可 设置为 NULL。

eAction Setting已执行的操作
eNoAction目标任务接收事件,但其 通知值未更新。 在这种情况下,不使用 ulValue。

eSetBits目标任务的通知值 使用 ulValue 按位或运算。 例如, 如果 ulValue 设置为 0x01,则将在 目标任务的通知值中设置位 0。 同样,如果 ulValue 为 0x04,则将在 目标任务的通知值中设置位 2。 通过这种方式,RTOS 任务通知机制 可以用作 事件组的轻量级替代方案。

eIncrement目标任务的通知值将 按 1 递增,使调用 xTaskNotifyFromISR() 相当于调用 vTaskNotifyGiveFromISR()。 在这种情况下,不使用 ulValue。
eSetValueWithOverwrite目标任务的通知值 无条件设置为 ulValue。 因此, RTOS 任务通知机制可用作 xQueueOverwrite() 的轻量级替代方案。
eSetValueWithoutOrwrite如果目标任务没有 挂起的通知,则其通知值 将设置为 ulValue。

如果目标任务已经有 挂起的通知,则不会更新其通知值, 因为这样做会覆盖 之前使用的值。 在这种情况下,调用 xTaskNotify() 会失败。

通过这种方式,RTOS 任务通知机制 在长度为 1 的队列上用作 xQueueSend() 的轻量级替代方案。

返回:

除了 eAction 被设置为 eSetValueWithoutOverwrite 且目标任务的通知值 因目标任务已有挂起的通知而无法更新之外, 在所有情况下均返回 pdPASS。


用法示例:

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

此示例演示了如何结合使用 xTaskNotifyFromISR() 和 eSetBits 操作。 请参阅 xTaskNotify() API 文档页面, 查看有关如何使用 eNoAction、eSetValueWithOverwrite 和 eSetValueWithoutOverwrite 行为的示例。


/* The interrupt handler does not perform any processing itself.  Instead it
it unblocks a high priority task in which the events that generated the
interrupt are processed.  If the priority of the task is high enough then the
interrupt will return directly to the task (so it will interrupt one task but
return to a different task), so the processing will occur contiguously in time -
just as if all the processing had been done in the interrupt handler itself.
The status of the interrupting peripheral is sent to the task using an RTOS task
notification. */
void vANInterruptHandler( void )
{
BaseType_t xHigherPriorityTaskWoken;
uint32_t ulStatusRegister;

    /* Read the interrupt status register which has a bit for each interrupt
    source (for example, maybe an Rx bit, a Tx bit, a buffer overrun bit, etc. */
    ulStatusRegister = ulReadPeripheralInterruptStatus();

    /* Clear the interrupts. */
    vClearPeripheralInterruptStatus( ulStatusRegister );

    /* xHigherPriorityTaskWoken must be initialised to pdFALSE.  If calling
    xTaskNotifyFromISR() unblocks the handling task, and the priority of
    the handling task is higher than the priority of the currently running task,
    then xHigherPriorityTaskWoken will automatically get set to pdTRUE. */
    xHigherPriorityTaskWoken = pdFALSE;

    /* Unblock the handling task so the task can perform any processing necessitated
    by the interrupt.  xHandlingTask is the task's handle, which was obtained
    when the task was created.  The handling task's 0th notification value
    is bitwise ORed with the interrupt status - ensuring bits that are already
    set are not overwritten. */
    xTaskNotifyIndexedFromISR( xHandlingTask,
                               0,
                               ulStatusRegister,
                               eSetBits,
                               &xHigherPriorityTaskWoken );

    /* Force a context switch if xHigherPriorityTaskWoken is now set to pdTRUE.
    The macro used to do this is dependent on the port and may be called
    portEND_SWITCHING_ISR. */
    portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
/* ----------------------------------------------------------- */

/* A task that blocks waiting to be notified that the peripheral needs servicing,
processing all the events pending in the peripheral each time it is notified to
do so. */
void vHandlingTask( void *pvParameters )
{
uint32_t ulInterruptStatus;

    for( ;; )
    {
        /* Block indefinitely (without a timeout, so no need to check the function's
        return value) to wait for a notification.  NOTE!  Real applications
        should not block indefinitely, but instead time out occasionally in order
        to handle error conditions that may prevent the interrupt from sending
        any more notifications. */
        xTaskNotifyWaitIndexed( 0,                  /* Wait for 0th Notificaition */
                                0x00,               /* Don't clear any bits on entry. */
                                ULONG_MAX,          /* Clear all bits on exit. */
                                &ulInterruptStatus, /* Receives the notification value. */
                                portMAX_DELAY );    /* Block indefinitely. */

        /* Process any bits set in the received notification value.  This assumes
        the peripheral sets bit 1 for an Rx interrupt, bit 2 for a Tx interrupt,
        and bit 3 for a buffer overrun interrupt. */
        if( ( ulInterruptStatus & 0x01 ) != 0x00 )
        {
            prvProcessRxInterrupt();
        }

        if( ( ulInterruptStatus & 0x02 ) != 0x00 )
        {
            prvProcessTxInterrupt();
        }

        if( ( ulInterruptStatus & 0x04 ) != 0x00 )
        {
            prvClearBufferOverrun();
        }
    }
}

xTaskNotifyWait / xTaskNotifyWaitIndexed
[RTOS 任务通知 API]


task.h


 BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry,
                             uint32_t ulBitsToClearOnExit,
                             uint32_t *pulNotificationValue,
                             TickType_t xTicksToWait );

 BaseType_t xTaskNotifyWaitIndexed( UBaseType_t uxIndexToWaitOn, 
                                    uint32_t ulBitsToClearOnEntry, 
                                    uint32_t ulBitsToClearOnExit, 
                                    uint32_t *pulNotificationValue, 
                                    TickType_t xTicksToWait );

[如果你使用 RTOS 任务通知来实现二进制或计数 信号量类型行为,请使用更简单的 ulTaskNotifyTake() API 函数, 而不要使用 xTaskNotifyWait()]

每个任务都有一组“任务通知” (或仅“通知” ),每个 通知都包含状态和一个 32 位值。 直达任务通知是直接发送至任务的事件, 可以取消阻塞接收任务,并 可以选择通过多种方式更新接收任务的某个通知值。 例如,通知可覆盖接收任务的一个通知值,或仅设置 接收任务的一个通知值中的一位或多位。

xTaskNotifyWait() 会等待调用任务接收通知,并有可选的超时。 如果等待的通知到达时,相关的接收 RTOS 任务已被阻塞且正在等待通知,则 接收 RTOS 任务将解除阻塞,通知也将清除。

注意:数组中每个通知都独立运行——在数组中的一个通知上一次只能阻塞一个任务,并且该任务不会被发送到任何其他数组索引的通知取消阻塞。

xTaskNotifyWait() 和 xTaskNotifyWaitIndexed() 是等效的宏,它们唯一的区别 是 xTaskNotifyWaitIndexed() 可以在数组内的任何任务通知上运行, 而 xTaskNotifyWait() 始终在数组索引 0 处的任务通知上运行。

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

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

向后兼容性信息:
在 FreeRTOS V10.4.0 之前,每个任务有一个单一的“通知值”,且 所有任务通知 API 函数都在该值上运行。用通知值的数组 更换单个通知值需要 新的 API 函数集,该函数集应能在数组内处理 特定通知。 xTaskNotifyWait() 是原始 API 函数,并 通过始终在数组内索引 0 处的通知值上运行来保持 向后兼容。调用 xTaskNotifyWait() 等于调用 xTaskNotifyWaitIndexed(),其中 uxIndexToWaitOn 参数设置为 0。

参数:

uxIndexToWaitOn  调用任务的数组中通知值的索引, 调用任务将在该通知值上等待接收 通知。

uxIndexToWaitOn 必须小于 configTASK_NOTIFICATION_ARRAY_ENTRIES。

xTaskNotifyWait() 没有此参数,总是在索引 0 处等待通知。

ulBitsToClearOnEntry 在 xTaskNotifyWait() 函数入口, ulBitsToClearOnEntry 中设置的任何位都将在调用 RTOS 任务通知值中 被清除(在任务等待新通知之前), 前提是在调用 xTaskNotifyWait() 时通知尚未 挂起。

例如,如果 ulBitsToClearOnEntry 为 0x01, 则任务通知值的位 0 将在函数入口 被清除。

将 ulBitsToClearOnEntry 设置为 0xffffffff (ULONG_MAX) 将 清除任务通知值中的所有位,有效 将值清除为 0。

ulBitsToClearOnExit  在 xTaskNotifyWait() 函数退出之前, ulBitsToClearOnExit 中设置的任何位都将在调用 RTOS 任务通知值中 被清除,前提是接收到通知。

在 RTOS 任务通知值保存到 *pulNotificationValue 中 之后清除位 (请参阅下面的 pulNotificationValue 的说明)。

例如,如果 ulBitsToClearOnExit 为 0x03,则位 0 和 位 1 将在函数退出之前 清除。

将 ulBitsToClearOnExit 设置为 0xffffffff (ULONG_MAX) 将 清除任务通知值中的所有位,有效 将值清除为 0。

pulNotificationValue  用于传出 RTOS 任务的通知值。 在由于 ulBitsToClearOnExit 的设置清除任何位之前,复制到 *pulNotificationValue 的值是 RTOS 任务的 通知值 。

如果不需要通知值,则设置 pulNotificationValue 为 NULL。

xTicksToWait  在阻塞状态下等待接收通知的最长时间, 前提是在调用 xTaskNotifyWait() 时通知尚未 挂起。

处于阻塞状态的 RTOS 任务不会消耗 任何 CPU 时间。

时间以 RTOS tick 周期为单位。 宏 pdMS_TO_TICKS() 可以 将以毫秒为单位的时间 转换成以 tick 为单位的时间。

Returns:

在调用 xTaskNotifyWait() 时,如果收到通知, 或通知已经挂起,则返回 pdTRUE。

如果调用 xTaskNotifyWait() 在收到通知之前超时, 则返回 pdFALSE。


用法示例:

[更多示例来自主 RTOS 任务通知页面]

/* This task shows bits within the RTOS task notification value being used to pass
different events to the task in the same way that flags in an event group might
be used for the same purpose. */
void vAnEventProcessingTask( void *pvParameters )
{
uint32_t ulNotifiedValue;

    for( ;; )
    {
        /* Block indefinitely (without a timeout, so no need to check the function's
        return value) to wait for a notification.

        Bits in this RTOS task's notification value are set by the notifying
        tasks and interrupts to indicate which events have occurred. */
        xTaskNotifyWaitIndexed( 0,         /* Wait for 0th notification. */
                                0x00,      /* Don't clear any notification bits on entry. */
                                ULONG_MAX, /* Reset the notification value to 0 on exit. */
                                &ulNotifiedValue, /* Notified value pass out in
                                                     ulNotifiedValue. */
                                portMAX_DELAY );  /* Block indefinitely. */

        /* Process any events that have been latched in the notified value. */

        if( ( ulNotifiedValue & 0x01 ) != 0 )
        {
            /* Bit 0 was set - process whichever event is represented by bit 0. */
            prvProcessBit0Event();
        }

        if( ( ulNotifiedValue & 0x02 ) != 0 )
        {
            /* Bit 1 was set - process whichever event is represented by bit 1. */
            prvProcessBit1Event();
        }

        if( ( ulNotifiedValue & 0x04 ) != 0 )
        {
            /* Bit 2 was set - process whichever event is represented by bit 2. */
            prvProcessBit2Event();
        }

        /* Etc. */
    }
}

xTaskNotifyStateClear / xTaskNotifyStateClearIndexed
[ RTOS任务通知API ]


task.h

 BaseType_t xTaskNotifyStateClear( TaskHandle_t xTask );

 BaseType_t xTaskNotifyStateClearIndexed( TaskHandle_t xTask, 
                                          UBaseType_t uxIndexToClear );

每个 RTOS 任务都有一个任务通知数组。 每条任务通知 都有通知状态 ,可以是“挂起”或“非挂起” , 以及一个 32 位通知值

如果通知被发送到通知数组中的索引,那么 该索引处的通知被称为“待定” ,直到任务读取 其通知值,或通过调用 xTaskNotifyStateClear () 将通知状态明确清除为“非挂起”为止 。

xTaskNotifyStateClear () 和 xTaskNotifyStateClearIndexed () 是等效宏——唯一的区别 是 xTaskNotifyStateClearIndexed () 可以在数组内任何任务通知上运行,而 xTaskNotifyStateClear () 始终在数组索引 0 处的任务通知上运行。

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

向后兼容性信息:
在 FreeRTOS V10.4.0 之前,每个任务有一个单一的“通知值”,且 所有任务通知 API 函数都在该值上运行。用通知值的数组 更换单个通知值需要 新的 API 函数集,该函数集应能在数组内处理 。 xTaskNotifyStateClear () 是原始 API 函数,并且 通过始终在数组内索引 0 处的通知值上操作来保留向后兼容性 。调用 xTaskNotifyStateClear () 等于调用 xTaskNotifyStateClearIndexed (),其中 uxIndexToNotify 参数设置为 0。

参数:

xTask  将收到此通知的 RTOS 任务的句柄 状态已清除。 将 xTask 设置为 NULL 以清除通知 调用任务的状态。

要获取任务句柄,请使用 xTaskCreate() 创建任务并使用 pxCreatedTask 参数,或使用返回值创建任务xTaskCreateStatic() 并存储该值,或在 调用 xTaskGetHandle() 中使用任务的名称。

当前执行的 RTOS 任务的句柄通过以下方式 由 xTaskGetCurrentTaskHandle() API 函数返回。

uxIndexToClear 待采取行动通知值索引内的目标任务数组 。 例如,将 uxIndexToClear 设置为 1 将清除数组内索引为 1 时的通知状态。

uxIndexToClear must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES。

ulTaskNotifyStateClear() 没有此参数,并且始终作用于 索引 0 的通知上。

Returns:

如果 xTask 引用的任务有挂起的通知,则通知 已清除,然后返回 pdTRUE。 如果 xTask 引用的任务 有待处理的通知,那么返回 pdFALSE。


用法示例:

[更多示例来自主 RTOS任务通知页面]

/* An example UART send function.  The function starts a UART transmission then
waits to be notified that the transmission is complete.  The transmission
complete notification is sent from the UART interrupt.  The calling task's
notification state is cleared before the transmission is started to ensure it is
not co-incidentally already pending before the task attempts to block on its
notification state. */
void vSerialPutString( const signed char * const pcStringToSend,
                       unsigned short usStringLength )
{
const TickType_t xMaxBlockTime = pdMS_TO_TICKS( 5000 );

    /* xSendingTask holds the handle of the task waiting for the transmission to
    complete.  If xSendingTask is NULL then a transmission is not in progress.
    Don't start to send a new string unless transmission of the previous string
    is complete. */
    if( ( xSendingTask == NULL ) && ( usStringLength > 0 ) )
    {
        /* Ensure the calling task's 0th notification state is not already
        pending. */
        xTaskNotifyStateClearIndexed( NULL, 0 );

        /* Store the handle of the transmitting task.  This is used to unblock
        the task when the transmission has completed. */
        xSendingTask = xTaskGetCurrentTaskHandle();

        /* Start sending the string - the transmission is then controlled by an
        interrupt. */
        UARTSendString( pcStringToSend, usStringLength );

        /* Wait in the Blocked state (so not using any CPU time) until the UART
        ISR sends the 0th notification to xSendingTask to notify (and unblock) the
        task when the transmission is complete. */
        ulTaskNotifyTake( 0, pdTRUE, xMaxBlockTime );
    }
}

ulTaskNotifyValueClear / ulTaskNotifyValueClearIndexed 
[RTOS 任务通知 API]


task.h  

uint32_t ulTaskNotifyValueClear( TaskHandle_t xTask, 
                                 uint32_t ulBitsToClear );

uint32_t ulTaskNotifyValueClearIndexed( TaskHandle_t xTask, 
                                        UBaseType_t uxIndexToClear,
                                        uint32_t ulBitsToClear );

每个 RTOS 任务都有一个任务通知数组。 每条任务通知 都有通知状态 ,可以是“挂起”或“非挂起” , 以及一个 32 位通知值

ulTaskNotifyValueClearIndexed() 清除 xTask 引用的任务的数组索引 uxIndexToClear 的通知值中 ulBitsToClear 位掩码指定的位。

ulTaskNotifyValueClear() 和 ulTaskNotifyValueClearIndexed() 是等效的宏 - 唯一的区别 是 ulTaskNotifyValueClearIndexed() 可以对 数组中的任何任务通知进行操作,而 ulTaskNotifyValueClear() 始终在数组索引 0 处对任务通知进行操作。

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

参数:

xTask将清除其通知值中的位的 RTOS 任务的句柄。将 xTask 设置为 NULL 以清除调用任务的通知值中的位。

若要获取任务句柄,请使用 xTaskCreate() 创建任务并使用 pxCreatedTask 参数,或使用 xTaskCreateStatic() 创建任务并存储返回值,或在调用 xTaskGetHandle() 时使用任务名称。

当前执行的 RTOS 任务的句柄由 xTaskGetCurrentTaskHandle() API 函数返回。

uxIndexToClear目标任务的通知值数组中的索引, 用于清除其中的位。 uxIndexToClear 必须小于 configTASK_NOTIFICATION_ARRAY_ENTRIES。 ulTaskNotifyValueClear() 没有此参数,并且始终清除 索引 0 处的通知值中的位。
ulBitsToClear要在 xTask 的通知值中清除的位的位掩码 。将位设置为 1 可清除任务的通知值中的相应位 。 将 ulBitsToClear 设置为 0xffffffff(32 位架构上的 UINT_MAX)以 将通知值清除为 0。 将 ulBitsToClear 设置为 0 以查询任务的 通知值,而不清除任何位。

Returns:

清除 ulBitsToClear 指定的位之前的目标任务的通知值。

用法示例:

   #define MESSAGE_RECEIVED_BIT 8
    #define TICKS_UNTIL_TIMEOUT  100

    unsigned long ulNotification, ulMessageReceivedMask;

    /* Clear any message received events. */
    ulMessageReceivedMask = 1u << MESSAGE_RECEIVED_BIT;
    ulTaskNotifyValueClear( ulMessageReceivedMask );

    /* Send a message that expects a response. */
    send_message();

    /* Block this task until it has another pending notification. In this example,
    the task only ever uses the MESSAGE_RECEIVED_BIT of its notification value, 
    so the next event can only ever be on message received. */
    xTaskNotifyWait( 0u, /* Don't clear any notification bits on entry. */
                     0u, /* Don't clear any notification bits on exit.  */
                     &ulNotification,
                     TICKS_UNTIL_TIMEOUT );

    /* If there wasn't a timeout, then the only possible event was received.
    In this example, that is the MESSAGE_RECEIVED_EVENT. */
    if( ulNotification == 0u ) 
    {
        /* Handle the response timeout. */
        process_response_timeout();
    } 
    else if( ulNotification == ulMessageReceivedMask )
    {
        /* Process the response event. */
        process_response();
        ulTaskNotifyValueClear( ulMessageReceivedMask );
    } 
    else 
    {
        /* The example task should only ever receive MESSAGE_RECEIVED_EVENTS. */
        process_error();
    }

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值