目录
1.xTaskNotifyGive / xTaskNotifyGiveIndexed
发送任务通知,不带通知值并且不保留接收任务的通知值,此函数会将接收任务的通知值加一,用于任务中
2.vTaskNotifyGiveFromISR / vTaskNotifyGiveIndexedFromISR
3.ulTaskNotifyTake / ulTaskNotifyTakeIndexed
获取任务通知,可以设置在退出此函数的时候将任务通知值清零或者减一。当任务通知用作二值信号量或者计数信号量的时候使用此函数来获取信号量。
4.xTaskNotify / xTaskNotifyIndexed
发送通知,带有通知值并且不保留接收任务原通知值,用在任务中。
5.xTaskNotifyFromISR / xTaskNotifyIndexedFromISR
6.xTaskNotifyAndQuery / xTaskNotifyAndQueryIndexed
发送通知,带有通知值并且保留接收任务的原通知值,用在任务中。
7.xTaskNotifyAndQueryFromISR / xTaskNotifyAndQueryIndexedFromISR
任务通知(RTOS Task Notifications)
1.xTaskNotifyGive / xTaskNotifyGiveIndexed
发送任务通知,不带通知值并且不保留接收任务的通知值,此函数会将接收任务的通知值加一,用于任务中
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任务的句柄由xtaskgetcurrentttaskhandle () API函数返回。 |
uxIndexToNotify | 通知将发送到的目标任务通知值数组中的索引。 uxIndexToNotify必须小于configTASK_NOTIFICATION_ARRAY_ENTRIES。 xTaskNotifyGive()没有这个参数,总是发送通知到索引0。 |
返回值:
xTaskNotifyGiveIndexed()是一个宏,调用xTaskNotifyIndexed()与eAction参数设置为eIncrement,所以所有的调用返回pdPASS。
使用示例:
/* main()创建的两个任务的原型。 */
static void prvTask1( void *pvParameters );
static void prvTask2( void *pvParameters );
/* 由main()创建的任务句柄。 */
static TaskHandle_t xTask1 = NULL, xTask2 = NULL;
/* 创建两个来回发送通知的任务,然后启动RTOS调度器。 */
void main( void )
{
xTaskCreate( prvTask1, "Task1", 200, NULL, tskIDLE_PRIORITY, &xTask1 );
xTaskCreate( prvTask2, "Task2", 200, NULL, tskIDLE_PRIORITY, &xTask2 );
vTaskStartScheduler();
}
/*-----------------------------------------------------------*/
/* prvTask1()使用API的“indexed”版本。 */
static void prvTask1( void *pvParameters )
{
for( ;; )
{
/* 向prvTask2()发送通知,使其脱离阻塞状态。 */
xTaskNotifyGiveIndexed( xTask2, 0 );
/* 阻塞以等待prvTask2()通知此任务。 */
ulTaskNotifyTakeIndexed( 0, pdTRUE, portMAX_DELAY );
}
}
/*-----------------------------------------------------------*/
/* prvTask2()使用API的原始版本(没有'Indexed')。 */
static void prvTask2( void *pvParameters )
{
for( ;; )
{
/* 阻塞以等待prvTask1()通知此任务。 */
ulTaskNotifyTake( pdTRUE, portMAX_DELAY );
/* 向prvTask1()发送一个通知,使其脱离阻塞状态。 */
xTaskNotifyGive( xTask1 );
}
}
2.vTaskNotifyGiveFromISR / vTaskNotifyGiveIndexedFromISR
void vTaskNotifyGiveFromISR( TaskHandle_t xTaskToNotify,
BaseType_t *pxHigherPriorityTaskWoken );
void vTaskNotifyGiveIndexedFromISR( TaskHandle_t xTaskHandle,
UBaseType_t uxIndexToNotify,
BaseType_t *pxHigherPriorityTaskWoken );
xTaskNotifyGive() 和 xTaskNotifyGiveIndexed() 的版本,可从中断服务例程 (ISR) 中使用。
参数:
xTaskToNotify | 正在通知的 RTOS 任务的句柄,其通知值递增。 若要获取任务的句柄,请使用 xTaskCreate() 创建任务并使用pxCreatedTask 参数,或使用 xTaskCreateStatic() 创建任务并存储返回值,或者在调用 xTaskGetHandle() 时使用任务的名称。 当前正在执行的 RTOS 任务的句柄由 xTaskGetCurrentTaskHandle() API 函数返回。 |
uxIndexToNotify | 要向其发送通知的目标任务的通知值数组中的索引。 uxIndexToNotify 必须小于 configTASK_NOTIFICATION_ARRAY_ENTRIES。 xTaskNotifyGiveFromISR() 没有此参数,并且始终将通知发送到索引 0。 |
pxHigherPriorityTaskWoken | *pxHigherPriorityTaskWoken 必须初始化为 0。 vTaskNotifyGiveFromISR() 会将 *pxHigherPriorityTaskWoken 设置为 pdTRUE 如果发送通知导致任务解除阻止,并且未阻止的任务的优先级高于当前正在运行的任务。 如果 vTaskNotifyGiveFromISR() 将此值设置为 pdTRUE,则应在退出中断之前请求上下文切换。请参阅下面的示例。 pxHigherPriorityTaskWoken 是一个可选参数,可以设置为 NULL。 |
使用示例:
/* 这是一个通用外围设备驱动程序中的传输函数的示例。一个RTOS任务调用传输函数,
然后等待在阻塞状态(所以不使用CPU时间),直到它被通知传输完成。传输由DMA执行,
DMA端中断用于通知任务。 */
static TaskHandle_t xTaskToNotify = NULL;
/* 外围驱动器的传输功能。 */
void StartTransmission( uint8_t *pcData, size_t xDataLength )
{
/* 此时xTaskToNotify应该为NULL,因为没有正在进行的传输。如果有必要,
互斥锁可以用来保护对外围设备的访问。 */
configASSERT( xTaskToNotify == NULL );
/* 存储调用任务的句柄。 */
xTaskToNotify = xTaskGetCurrentTaskHandle();
/* 启动传输——传输完成时产生中断。 */
vStartTransmit( pcData, xDatalength );
}
/*-----------------------------------------------------------*/
/* 发送端中断。 */
void vTransmitEndISR( void )
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
/* 此时xTaskToNotify不应该为NULL,因为传输正在进行中。 */
configASSERT( xTaskToNotify != NULL );
/* 通知任务传输完成。 */
vTaskNotifyGiveIndexedFromISR( xTaskToNotify, 0, &xHigherPriorityTaskWoken );
/* 没有正在进行的传输,所以没有需要通知的任务。 */
xTaskToNotify = NULL;
/* 如果xHigherPriorityTaskWoken现在设置为pdTRUE,那么应该执行一个上下
文切换,以确保中断直接返回到最高优先级的任务。用于此目的的宏依赖于使用
的端口,可以称为portEND_SWITCHING_ISR()。 */
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
/*-----------------------------------------------------------*/
/* 启动传输的任务,然后进入阻塞状态(因此不消耗任何CPU时间),等待它完成。 */
void vAFunctionCalledFromATask( uint8_t ucDataToTransmit, size_t xDataLength )
{
uint32_t ulNotificationValue;
const TickType_t xMaxBlockTime = pdMS_TO_TICKS( 200 );
/* 通过调用上面所示的函数来开始传输。 */
StartTransmission( ucDataToTransmit, xDataLength );
/* 等待传输完成。 */
ulNotificationValue = ulTaskNotifyTakeIndexed( 0, pdFALSE, xMaxBlockTime );
if( ulNotificationValue == 1 )
{
/* 传播如预期般结束。 */
}
else
{
/* 调用ulTaskNotifyTake()超时。 */
}
}
3.ulTaskNotifyTake / ulTaskNotifyTakeIndexed
获取任务通知,可以设置在退出此函数的时候将任务通知值清零或者减一。当任务通知用作二值信号量或者计数信号量的时候使用此函数来获取信号量。
uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit,
TickType_t xTicksToWait );
uint32_t ulTaskNotifyTakeIndexed( UBaseType_t uxIndexToWaitOn,
BaseType_t xClearCountOnExit,
TickType_t xTicksToWait );
每个任务都有一个“任务通知”数组(或只是“通知”),每个通知都有一个状态和一个 32 位值。直接到任务通知是直接发送到任务的事件,该事件可以取消阻止接收任务,并可以选择以多种不同的方式更新接收任务的通知值之一。例如,通知可能会覆盖接收任务的通知值之一,或者只是在接收任务的通知值之一中设置一个或多个位。
ulTaskNotifyTake() 是一个宏,旨在将任务通知用作更快、更轻量级的二进制或计数信号量替代项时使用。FreeRTOS 信号量是使用 xSemaphoreTake() API 函数获取的,ulTaskNotifyTake() 是使用通知值代替信号量的等效项。
ulTaskNotifyTake() 和 ulTaskNotifyTakeIndexed() 是等效的宏 - 唯一的区别是 ulTaskNotifyTakeIndexed() 可以对数组中的任何任务通知进行操作,而 ulTaskNotifyTake() 始终对数组索引 0 处的任务通知进行操作。
当任务使用通知值作为二进制文件或计数信号量时,其他任务和中断应使用 xTaskNotifyGive() 宏或 xTaskNotify() 函数(如果函数的 eAction 参数设置为 eIncrement)向其发送通知(两者等效)。
ulTaskNotifyTake() 可以在退出时将任务的通知值清除为零,在这种情况下,通知值的作用类似于二进制信号量,或者在退出时递减任务的通知值,在这种情况下,通知值的作用更像是计数信号量。
RTOS 任务可以使用 ulTaskNotifyTake() 来 [可选] 阻止等待任务的通知值。任务处于“已阻止”状态时不会消耗任何 CPU 时间。
注意:数组中的每个通知都独立运行 – 一个任务一次只能阻止数组中的一个通知,并且不会被发送到任何其他数组索引的通知取消阻止。
其中 xTaskNotifyWait() 将在通知挂起时返回,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,则在 ulTaskNotifyTake() 退出之前,RTOS 任务的通知值将递减。这等效于成功调用 xSemaphoreTake() 时递减的计数信号量的值。 如果收到 RTOS 任务通知,并且 xClearCountOnExit 设置为 pdTRUE,则在 ulTaskNotifyTake() 退出之前,RTOS 任务的通知值将重置为 0。这等效于在成功调用 xSemaphoreTake() 后二进制信号量保持在零(或空,或“不可用”)的值。 |
xTicksToWait | 在调用 ulTaskNotifyTake() 时,如果在通知尚未挂起,则在“已阻止”状态下等待接收通知的最长时间。 RTOS 任务处于“已阻止”状态时不会消耗任何 CPU 时间。 时间以 RTOS 刻度周期指定。pdMS_TO_TICKS() 宏可用于将以毫秒为单位指定的时间转换为以刻度为单位指定的时间。 |
返回值:
任务的通知值在递减或清除之前的值(请参阅 xClearCountOnExit 的说明)。
使用示例:
/* 一个中断处理程序。中断处理程序不执行任何处理,而是解除一个高优先级任务的阻塞,
在该任务中,产生中断的事件被处理。如果该任务的优先级足够高,那么中断将直接返回到
该任务(因此它将中断一个任务,但返回到另一个任务),因此处理将在时间上连续发生——就
像所有的处理都已经在中断处理器本身完成了一样。 */
void vANInterruptHandler( void )
{
BaseType_t xHigherPriorityTaskWoken;
/* 清除中断。 */
prvClearInterruptSource();
/* xHigherPriorityTaskWoken必须初始化为pdFALSE。
如果调用vTaskNotifyGiveFromISR()解除了处理任务的阻塞,并且处理任务的优先级高于
当前正在运行的任务的优先级,那么xHigherPriorityTaskWoken将自动被设置为pdTRUE。 */
xHigherPriorityTaskWoken = pdFALSE;
/* 解除对处理任务的阻塞,使该任务可以执行中断所需要的任何处理。
xHandlingTask是任务的句柄,它是在创建任务时获得的。 */
vTaskNotifyGiveIndexedFromISR( xHandlingTask, 0, &xHigherPriorityTaskWoken );
/* 如果xHigherPriorityTaskWoken现在设置为pdTRUE,强制一个上下文切换。用于完成此
操作的宏依赖于端口,可以称为portEND_SWITCHING_ISR。 */
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
/*-----------------------------------------------------------*/
/* 一种阻塞等待外设需要维修的通知的任务,每次外设收到维修通知时,该任务处理外设中等待处理
的所有事件。 */
void vHandlingTask( void *pvParameters )
{
BaseType_t xEvent;
for( ;; )
{
/* 不确定地阻塞(没有超时,因此不需要检查函数的返回值)以等待通知。这里RTOS任务通知
被用作二进制信号量,因此在退出时通知值被清除为零。注意!真正的应用程序不应该无限
阻塞,而应该偶尔超时,以处理可能阻止中断发送更多通知的错误条件。 */
ulTaskNotifyTakeIndexed( 0, /* 使用第0个通知 */
pdTRUE, /* 退出前清除通知值。 */
portMAX_DELAY ); /* 无期限。 */
/* RTOS任务通知被用作二进制信号量(而不是计数信号量),所以只有当外围设备中挂起的
所有事件都被处理后,才会返回等待进一步的通知。 */
do
{
xEvent = xQueryPeripheral();
if( xEvent != NO_MORE_EVENTS )
{
vProcessPeripheralEvent( xEvent );
}
} while( xEvent != NO_MORE_EVENTS );
}
}
4.xTaskNotify / xTaskNotifyIndexed
发送通知,带有通知值并且不保留接收任务原通知值,用在任务中。
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 任务并可能取消阻止 RTOS 任务,并可选择通过以下方式之一更新接收任务的通知值之一:
- 将 32 位数字写入通知值
- 添加一个(递增)通知值
- 在通知值中设置一个或多个位
- 保持通知值不变
xTaskNotify() 和 xTaskNotifyIndexed() 是等效的函数 - 唯一的区别是 xTaskNotifyIndexed() 可以对数组中的任何任务通知进行操作,而 xTaskNotify() 始终对数组索引 0 处的任务通知进行操作。
不得从中断服务例程 (ISR) 调用此函数。请改用 xTaskNotifyFromISR()。
configUSE_TASK_NOTIFICATIONS必须在 FreeRTOSConfig.h 中设置为 1(或保留未定义),这些功能才可用。常量configTASK_NOTIFICATION_ARRAY_ENTRIES设置每个任务的任务通知数组中的索引数。
参数:
xTaskToNotify | 被通知的RTOS任务句柄。这是目标任务。 要获得一个任务的句柄,可以使用xTaskCreate()创建任务并使用pxCreatedTask参数,或者使用xTaskCreateStatic()创建任务并存储返回值,或者在调用xTaskGetHandle()时使用任务的名称。 当前正在执行的RTOS任务的句柄由xtaskgetcurrentttaskhandle () API函数返回。 |
uxIndexToNotify | 通知将发送到的目标任务通知值数组中的索引。 uxIndexToNotify必须小于configTASK_NOTIFICATION_ARRAY_ENTRIES。 xTaskNotify()没有这个参数,并且总是向索引0发送通知。 |
ulValue | 用于更新目标任务的通知值。请参阅下面对eAction参数的描述。 |
eAction | 一种枚举类型,可以采用下表中记录的值之一,以便执行相关操作。 |
typedef enum
{
eNoAction = 0,
eSetBits, //更新指定的 bit
eIncrement, //通知值加一
eSetValueWithOverwrite, //覆写的方式更新通知值
eSetValueWithoutOverwrite //不覆写通知值
} eNotifyAction;
eAction 设置(eAction Setting) | 执行操作(Action Performed) |
eNoAction | 目标任务接收到事件,但是它的通知值没有更新。在这种情况下,不使用ulValue。 |
eSetBits | 目标任务的通知值将使用 ulValue 按位排序。例如,如果 ulValue 设置为 0x01,则将在目标任务的通知值内设置位 0。同样,如果 ulValue 0x04则将在目标任务的通知值中设置位 2。通过这种方式,RTOS任务通知机制可以用作事件组的轻量级替代方案。 |
eIncrement | 目标任务的通知值将增加1,使得对xTaskNotify()的调用相当于对xTaskNotifyGive()的调用。在这种情况下,不使用ulValue。 |
eSetValueWithOverwrite | 目标任务的通知值无条件设置为ulValue。通过这种方式,RTOS任务通知机制被用作xQueueOverwrite()的轻量级替代。 |
eSetValueWithoutOverwrite | 如果目标任务没有等待通知,那么它的通知值将被设置为ulValue。 如果目标任务已经有一个通知挂起,那么它的通知值不会更新,因为这样做会覆盖之前的值。在这种情况下,调用xTaskNotify()失败并返回pdFALSE。 通过这种方式,RTOS任务通知机制被用作长度为1的队列的xQueueSend()的轻量级替代。 |
返回值:
当eAction设置为eSetValueWithoutOverwrite,目标任务的通知值不能更新,因为目标任务已经有一个通知挂起时,所有情况下都会返回pdPASS。
使用示例:
/* 在xTask1Handle引用的任务的第0个通知值中设置第8位。 */
xTaskNotifyIndexed( xTask1Handle, 0, ( 1UL << 8UL ), eSetBits );
/* 向xTask2Handle引用的任务发送通知,可能会将该任务从Blocked状态中移除,
但不会更新该任务的通知值。 */
xTaskNotify( xTask2Handle, 0, eNoAction );
/* 将xTask3Handle引用的任务的通知值设置为0x50,即使该任务没有读取它之前的通知值。 */
xTaskNotify( xTask3Handle, 0x50, eSetValueWithOverwrite );
/* 将xTask4Handle引用的任务的通知值设置为0xfff,但只有在这样做不会覆盖该任务已经
获得的通知值之前(通过调用xTaskNotifyWait()或ulTaskNotifyTake())的情况下才会
这样做。 */
if( xTaskNotify( xTask4Handle, 0xfff, eSetValueWithoutOverwrite ) == pdPASS )
{
/* 更新任务的通知值。 */
}
else
{
/* 未更新任务的通知值。 */
}
5.xTaskNotifyFromISR / xTaskNotifyIndexedFromISR
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 );
xTaskNotify()和xTaskNotifyIndexed()的版本,可以从中断服务例程(ISR)中使用。请参阅xTaskNotify() API函数的文档页,以获得其操作的描述和必要的配置参数,以及向后兼容性信息。
参数:
xTaskToNotify | 被通知的RTOS任务句柄。这是目标任务。 要获得一个任务的句柄,可以使用xTaskCreate()创建任务并使用pxCreatedTask参数,或者使用xTaskCreateStatic()创建任务并存储返回值,或者在调用xTaskGetHandle()时使用任务的名称。 当前正在执行的RTOS任务的句柄由xtaskgetcurrentttaskhandle () API函数返回。 |
uxIndexToNotify | 通知将发送到的目标任务通知值数组中的索引。 uxIndexToNotify必须小于configTASK_NOTIFICATION_ARRAY_ENTRIES。 xTaskNotify()没有这个参数,并且总是向索引0发送通知。 |
ulValue | 用于更新目标任务的通知值。请参阅下面对eAction参数的描述。 |
eAction | 一种枚举类型,可以采用下表中记录的值之一,以便执行相关操作。 |
pxHigherPriorityTaskWoken | *pxHigherPriorityTaskWoken必须初始化为0 xTaskNotifyFromISR()将设置*pxHigherPriorityTaskWoken为pdTRUE,如果发送通知导致一个任务解除阻塞,且解除阻塞的任务的优先级高于当前正在运行的任务。 如果xTaskNotifyFromISR()将该值设置为pdTRUE,那么应该在中断退出之前请求上下文切换。请参阅下面的示例。 pxHigherPriorityTaskWoken是一个可选参数,可以设置为NULL。 |
typedef enum
{
eNoAction = 0,
eSetBits, //更新指定的 bit
eIncrement, //通知值加一
eSetValueWithOverwrite, //覆写的方式更新通知值
eSetValueWithoutOverwrite //不覆写通知值
} eNotifyAction;
eAction 设置(eAction Setting) | 执行操作(Action Performed) |
eNoAction | 目标任务接收到事件,但是它的通知值没有更新。在这种情况下,不使用ulValue。 |
eSetBits | 目标任务的通知值将使用 ulValue 按位排序。例如,如果 ulValue 设置为 0x01,则将在目标任务的通知值内设置位 0。同样,如果 ulValue 0x04则将在目标任务的通知值中设置位 2。通过这种方式,RTOS任务通知机制可以用作事件组的轻量级替代方案。 |
eIncrement | 目标任务的通知值将增加1,使得对xTaskNotify()的调用相当于对xTaskNotifyGive()的调用。在这种情况下,不使用ulValue。 |
eSetValueWithOverwrite | 目标任务的通知值无条件设置为ulValue。通过这种方式,RTOS任务通知机制被用作xQueueOverwrite()的轻量级替代。 |
eSetValueWithoutOverwrite | 如果目标任务没有等待通知,那么它的通知值将被设置为ulValue。 如果目标任务已经有一个通知挂起,那么它的通知值不会更新,因为这样做会覆盖之前的值。在这种情况下,调用xTaskNotify()失败并返回pdFALSE。 通过这种方式,RTOS任务通知机制被用作长度为1的队列的xQueueSend()的轻量级替代。 |
返回值:
当eAction设置为eSetValueWithoutOverwrite,目标任务的通知值不能更新,因为目标任务已经有一个通知挂起时,所有情况下都会返回pdPASS。
使用示例:
这个例子演示了如何在eSetBits操作中使用xTaskNotifyFromISR()。请参阅xTaskNotify() API文档页面,以获得如何使用eNoAction, eSetValueWithOverwrite和eSetValueWithoutOverwrite动作的示例。
/* 中断处理程序本身不执行任何处理。相反,它解除了一个高优先级任务的阻塞,
在该任务中,产生中断的事件被处理。如果该任务的优先级足够高,那么中断将直
接返回到该任务(因此它将中断一个任务,但返回到另一个任务),因此处理将在时
间上连续发生——就像所有的处理都已经在中断处理器本身完成了一样。中断外设的
状态通过RTOS任务通知发送给任务。 */
void vANInterruptHandler( void )
{
BaseType_t xHigherPriorityTaskWoken;
uint32_t ulStatusRegister;
/* 读取每个中断源都有一个位的中断状态寄存器(例如,可能是一个Rx位、一个Tx位、
一个缓冲区溢出位等)。 */
ulStatusRegister = ulReadPeripheralInterruptStatus();
/* 清除中断。 */
vClearPeripheralInterruptStatus( ulStatusRegister );
/* xHigherPriorityTaskWoken必须初始化为pdFALSE。如果调用xTaskNotifyFromISR()
解除了处理任务的阻塞,并且处理任务的优先级高于当前正在运行的任务的优先级,那么
xHigherPriorityTaskWoken将自动被设置为pdTRUE。 */
xHigherPriorityTaskWoken = pdFALSE;
/* 解除对处理任务的阻塞,使该任务可以执行中断所需要的任何处理。xHandlingTask
是任务的句柄,它是在创建任务时获得的。处理任务的第0个通知值与中断状态
按位或-确保已经设置的位不会被覆盖。 */
xTaskNotifyIndexedFromISR( xHandlingTask,
0,
ulStatusRegister,
eSetBits,
&xHigherPriorityTaskWoken );
/* 如果xHigherPriorityTaskWoken现在设置为pdTRUE,强制一个上下文切换。
用于完成此操作的宏依赖于端口,可以称为portEND_SWITCHING_ISR。 */
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
/* ----------------------------------------------------------- */
/* 一种阻塞等待外设需要维修的通知的任务,每次外设收到维修通知时,该任务处理外设中
等待处理的所有事件。 */
void vHandlingTask( void *pvParameters )
{
uint32_t ulInterruptStatus;
for( ;; )
{
/* 不确定地阻塞(没有超时,因此不需要检查函数的返回值)以等待通知。
注意!真正的应用程序不应该无限阻塞,而应该偶尔超时,以处理可能
阻止中断发送更多通知的错误条件。 */
xTaskNotifyWaitIndexed( 0, /* 等待第0个通知 */
0x00, /* 不要在输入时清除任何位 */
ULONG_MAX, /* 退出时清除所有位*/
&ulInterruptStatus, /* 接收通知值 */
portMAX_DELAY ); /* 无限期阻塞 */
/* 处理在收到的通知值中设置的任何位。 这假设外设为Rx中断设置位1,
为Tx中断设置位2,为缓冲区溢出中断设置位3。 */
if( ( ulInterruptStatus & 0x01 ) != 0x00 )
{
prvProcessRxInterrupt();
}
if( ( ulInterruptStatus & 0x02 ) != 0x00 )
{
prvProcessTxInterrupt();
}
if( ( ulInterruptStatus & 0x04 ) != 0x00 )
{
prvClearBufferOverrun();
}
}
}
6.xTaskNotifyAndQuery / xTaskNotifyAndQueryIndexed
发送通知,带有通知值并且保留接收任务的原通知值,用在任务中。
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 );
xTaskNotifyAndQueryIndexed() 执行与 xTaskNotifyIndexed() 相同的操作,并补充说,它还在附加的 pulPreviousNotifyValue 参数中返回目标任务的先前通知值(调用函数时的通知值,而不是函数返回时的通知值)。
xTaskNotifyAndQuery() 执行与 xTaskNotify() 相同的操作,并补充说,它还在附加的 pulPreviousNotifyValue 参数中返回目标任务的先前通知值(调用函数时的通知值,而不是函数返回时的通知值)。
不得从中断服务例程 (ISR) 调用此函数。请改用 xTaskNotifyAndQueryFromISR()。
参数:
xTaskToNotify | 被通知的RTOS任务句柄。这是目标任务。 要获得一个任务的句柄,可以使用xTaskCreate()创建任务并使用pxCreatedTask参数,或者使用xTaskCreateStatic()创建任务并存储返回值,或者在调用xTaskGetHandle()时使用任务的名称。 当前正在执行的RTOS任务的句柄由xtaskgetcurrentttaskhandle () API函数返回。 |
uxIndexToNotify | 通知将发送到的目标任务通知值数组中的索引。 uxIndexToNotify必须小于configTASK_NOTIFICATION_ARRAY_ENTRIES。 |
ulValue | 用于更新目标任务的通知值。请参阅下面对eAction参数的描述。 |
eAction | 一种枚举类型,可以采用下表中记录的值之一,以便执行相关操作。 |
pulPreviousNotifyValue | 可用于在xTaskNotifyAndQuery()操作修改任何位之前传递目标任务的通知值。 pulPreviousNotifyValue是一个可选参数,如果不是必需的,可以设置为NULL。如果pulPreviousNotifyValue没有被使用,那么考虑使用xTaskNotify()来代替xTaskNotifyAndQuery()。 |
typedef enum
{
eNoAction = 0,
eSetBits, //更新指定的 bit
eIncrement, //通知值加一
eSetValueWithOverwrite, //覆写的方式更新通知值
eSetValueWithoutOverwrite //不覆写通知值
} eNotifyAction;
eAction 设置(eAction Setting) | 执行操作(Action Performed) |
eNoAction | 目标任务接收到事件,但是它的通知值没有更新。在这种情况下,不使用ulValue。 |
eSetBits | 目标任务的通知值将使用 ulValue 按位排序。例如,如果 ulValue 设置为 0x01,则将在目标任务的通知值内设置位 0。同样,如果 ulValue 0x04则将在目标任务的通知值中设置位 2。通过这种方式,RTOS任务通知机制可以用作事件组的轻量级替代方案。 |
eIncrement | 目标任务的通知值将增加1,使得对xTaskNotify()的调用相当于对xTaskNotifyGive()的调用。在这种情况下,不使用ulValue。 |
eSetValueWithOverwrite | 目标任务的通知值无条件设置为ulValue。通过这种方式,RTOS任务通知机制被用作xQueueOverwrite()的轻量级替代。 |
eSetValueWithoutOverwrite | 如果目标任务没有等待通知,那么它的通知值将被设置为ulValue。 如果目标任务已经有一个通知挂起,那么它的通知值不会更新,因为这样做会覆盖之前的值。在这种情况下,调用xTaskNotify()失败并返回pdFALSE。 通过这种方式,RTOS任务通知机制被用作长度为1的队列的xQueueSend()的轻量级替代。 |
返回值:
当eAction设置为eSetValueWithoutOverwrite,目标任务的通知值不能更新,因为目标任务已经有一个通知挂起时,所有情况下都会返回pdPASS。
使用示例:
uint32_t ulPreviousValue;
/* 在xTask1Handle引用的任务的第0个通知值中设置第8位。
在ulPreviousValue中存储任务之前的第0个通知值(在第8位设置之前)。*/
xTaskNotifyAndQueryIndexed( xTask1Handle,
0,
( 1UL << 8UL ),
eSetBits,
&ulPreviousValue );
/* 向xTask2Handle引用的任务发送通知,可能会将该任务从Blocked状态中移除,
但不会更新该任务的通知值。将任务通知值存储在ulPreviousValue中。 */
xTaskNotifyAndQuery( xTask2Handle, 0, eNoAction, &ulPreviousValue );
/* 将xTask3Handle引用的任务的通知值设置为0x50,即使该任务没有读取它之前的通知值。
任务之前的通知值没有意义,因此最后一个参数被设置为NULL。 */
xTaskNotifyAndQuery( xTask3Handle, 0x50, eSetValueWithOverwrite, NULL );
/* 将xTask4Handle引用的任务的通知值设置为0xfff,但只有在这样做不会覆盖该任务已经
获得的通知值之前(通过调用xTaskNotifyWait()或ulTaskNotifyTake())的情况下才会
这样做。任务之前的通知值保存在ulPreviousValue中。 */
if( xTaskNotifyAndQuery( xTask4Handle,
0xfff,
eSetValueWithoutOverwrite,
&ulPreviousValue ) == pdPASS )
{
/* 更新任务的通知值。 */
}
else
{
/* 未更新任务的通知值。 */
}
7.xTaskNotifyAndQueryFromISR / xTaskNotifyAndQueryIndexedFromISR
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 );
xTaskNotifyAndQueryIndexedFromISR() 执行与 xTaskNotifyIndexedFromISR() 相同的操作,并补充说,它还在附加的 pulPreviousNotifyValue 参数中返回目标任务的先前通知值(调用函数时的通知值,而不是函数返回时的通知值)。
xTaskNotifyAndQueryFromISR() 执行与 xTaskNotifyFromISR() 相同的操作,并补充说,它还在附加的 pulPreviousNotifyValue 参数中返回目标任务的先前通知值(调用函数时的通知值,而不是函数返回时的通知值)。
参数:
xTaskToNotify | 被通知的RTOS任务句柄。这是目标任务。 要获得一个任务的句柄,可以使用xTaskCreate()创建任务并使用pxCreatedTask参数,或者使用xTaskCreateStatic()创建任务并存储返回值,或者在调用xTaskGetHandle()时使用任务的名称。 当前正在执行的RTOS任务的句柄由xtaskgetcurrentttaskhandle () API函数返回。 |
uxIndexToNotify | 通知将发送到的目标任务通知值数组中的索引。 uxIndexToNotify必须小于configTASK_NOTIFICATION_ARRAY_ENTRIES。 |
ulValue | 用于更新目标任务的通知值。请参阅下面对eAction参数的描述。 |
eAction | 一种枚举类型,可以采用下表中记录的值之一,以便执行相关操作。 |
pulPreviousNotifyValue | 可以用于在xTaskNotifyAndQueryFromISR()操作修改任何位之前传递目标任务的通知值。 pulPreviousNotifyValue是一个可选参数,如果不是必需的,可以设置为NULL。如果pulPreviousNotifyValue没有被使用,那么考虑使用xTaskNotify()来代替xTaskNotifyAndQueryFromISR()。 |
pxHigherPriorityTaskWoken | *pxHigherPriorityTaskWoken必须初始化为pdFALSE(0)。 xTaskNotifyAndQueryFromISR()将设置*pxHigherPriorityTaskWoken为pdTRUE,如果发送通知导致任务解除阻塞,且解除阻塞的任务的优先级高于当前正在运行的任务。 如果xTaskNotifyAndQueryFromISR()将该值设置为pdTRUE,那么应该在中断退出之前请求上下文切换。请参阅下面的示例。 pxHigherPriorityTaskWoken是一个可选参数,可以设置为NULL。 |
typedef enum
{
eNoAction = 0,
eSetBits, //更新指定的 bit
eIncrement, //通知值加一
eSetValueWithOverwrite, //覆写的方式更新通知值
eSetValueWithoutOverwrite //不覆写通知值
} eNotifyAction;
eAction 设置(eAction Setting) | 执行操作(Action Performed) |
eNoAction | 目标任务接收到事件,但是它的通知值没有更新。在这种情况下,不使用ulValue。 |
eSetBits | 目标任务的通知值将使用 ulValue 按位排序。例如,如果 ulValue 设置为 0x01,则将在目标任务的通知值内设置位 0。同样,如果 ulValue 0x04则将在目标任务的通知值中设置位 2。通过这种方式,RTOS任务通知机制可以用作事件组的轻量级替代方案。 |
eIncrement | 目标任务的通知值将增加1,使得对xTaskNotify()的调用相当于对xTaskNotifyGive()的调用。在这种情况下,不使用ulValue。 |
eSetValueWithOverwrite | 目标任务的通知值无条件设置为ulValue。通过这种方式,RTOS任务通知机制被用作xQueueOverwrite()的轻量级替代。 |
eSetValueWithoutOverwrite | 如果目标任务没有等待通知,那么它的通知值将被设置为ulValue。 如果目标任务已经有一个通知挂起,那么它的通知值不会更新,因为这样做会覆盖之前的值。在这种情况下,调用xTaskNotify()失败并返回pdFALSE。 通过这种方式,RTOS任务通知机制被用作长度为1的队列的xQueueSend()的轻量级替代。 |
返回值:
当eAction设置为eSetValueWithoutOverwrite,目标任务的通知值不能更新,因为目标任务已经有一个通知挂起时,所有情况下都会返回pdPASS。
使用示例:
void vAnISR( void )
{
/* 必须初始化为pdFALSE! */
BaseType_t xHigherPriorityTaskWoken = pdFALSE.
uint32_t ulPreviousValue;
/* 在xTask1Handle引用的任务的第0个通知值中设置第8位。
在ulPreviousValue中存储任务之前的第0个通知值(在第8位设置之前)。 */
xTaskNotifyAndQueryIndexedFromISR( xTask1Handle,
0,
( 1UL << 8UL ),
eSetBits,
&ulPreviousValue,
&xHigherPriorityTaskWoken );
/* 任务之前的通知值保存在ulPreviousValue中。 */
/* 如果xTask1Handle引用的任务处于阻塞状态,正在等待通知,那么它现在将从
阻塞状态移动到就绪状态。如果它的优先级高于当前正在执行的任务(被中断的
任务)的优先级,那么xHigherPriorityTaskWoken将被设置为pdTRUE,并将该
变量传递给portYIELD_FROM_ISR()调用将导致中断直接返回到未阻塞的任务。
如果xHigherPriorityTaskWoken仍然是pdFALSE,
那么传入portYIELD_FROM_ISR()将没有效果。 */
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
8.xTaskNotifyWait / xTaskNotifyWaitIndexed
等待任务通知,比 ulTaskNotifyTak()更为强大,全功能版任务通知获取函数。
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() 等待调用任务接收通知,并带有可选的超时。如果接收实时操作系统任务在等待通知到达时已被阻止等待通知,则接收实时操作系统任务将从“已阻止”状态中删除,并清除通知。
注意:数组中的每个通知都独立运行 – 一个任务一次只能阻止数组中的一个通知,并且不会被发送到任何其他数组索引的通知取消阻止。
xTaskNotifyWait() 和 xTaskNotifyWaitIndexed() 是等效的宏 - 唯一的区别是 xTaskNotifyWaitIndexed() 可以对数组中的任何任务通知进行操作,而 xTaskNotifyWait() 始终对数组索引 0 处的任务通知进行操作。
xTaskNotifyGive() 不得从中断服务例程调用。请改用 vTaskNotifyGiveFromISR()。
configUSE_TASK_NOTIFICATIONS必须在 FreeRTOSConfig.h 中设置为 1(或保持未定义状态),这些宏才可用。常量configTASK_NOTIFICATION_ARRAY_ENTRIES设置每个任务的任务通知数组中的索引数。
参数:
uxIndexToWaitOn | 调用任务的通知值数组中的索引,调用任务将基于该索引等待收到通知。 uxIndexToWaitOn 必须小于 configTASK_NOTIFICATION_ARRAY_ENTRIES。 xTaskNotifyWait() 没有此参数,并且始终等待索引 0 上的通知。 |
ulBitsToClearOnEntry | 在ulBitsToClearOnEntry中设置的任何位将在进入xTaskNotifyWait()函数时(在任务等待新通知之前)在调用RTOS任务的通知值中被清除,前提是在调用xTaskNotifyWait()时通知尚未挂起。 例如,如果 ulBitsToClearOnEntry 0x01,则在进入函数时将清除任务通知值的位 0。 将 ulBitsToClearOnEntry 设置为 0xffffffff (ULONG_MAX) 将清除任务通知值中的所有位,从而有效地将值清除为 0。 |
ulBitsToClearOnExit | 在 ulBitsToClearOnExit 中设置的任何位都将在调用 RTOS 任务的通知值中被清除,如果收到通知,则在 xTaskNotifyWait() 函数退出之前。 在 RTOS 任务的通知值保存在 *pulNotificationValue 中后,这些位将被清除(请参阅下面的 pulNotificationValue 说明)。 例如,如果 ulBitsToClearOnExit 0x03,则在函数退出之前,将清除任务通知值的位 0 和位 1。 将 ulBitsToClearOnExit 设置为 0xffffffff (ULONG_MAX) 将清除任务通知值中的所有位,从而有效地将值清除为 0。 |
pulNotificationValue | 用于传递 RTOS 任务的通知值。复制到 *pulNotificationValue 的值是 RTOS 任务的通知值,因为它是在由于 ulBitsToClearOnExit 设置而清除任何位之前的值。 如果通知值不是必需的,则将 pulNotificationValue 设置为 NULL。 |
xTicksToWait | 在 xTaskNotifyWait() 调用时,如果通知尚未挂起,则在“已阻止”状态下等待接收通知的最长时间。 RTOS 任务处于“已阻止”状态时不会消耗任何 CPU 时间。 时间以 RTOS 刻度周期指定。pdMS_TO_TICKS() 宏可用于将以毫秒为单位指定的时间转换为以刻度为单位指定的时间。 |
返回值:
pdTRUE 如果收到通知,或者在调用 xTaskNotifyWait() 时通知已挂起。
pdFALSE 如果对 xTaskNotifyWait() 的调用在收到通知之前超时。
使用示例:
/* 这个任务显示了RTOS任务通知值中用于向任务传递不同事件的位,就像事件组中的
标志可能用于相同的目的一样。 */
void vAnEventProcessingTask( void *pvParameters )
{
uint32_t ulNotifiedValue;
for( ;; )
{
/* 不确定地阻塞(没有超时,因此不需要检查函数的返回值)以等待通知。
这个RTOS任务的通知值中的位是由通知任务和中断设置的,
用来指示发生了哪些事件。 */
xTaskNotifyWaitIndexed( 0, /* 等待第 0 个通知 */
0x00, /* 不要在输入时清除任何通知位 */
ULONG_MAX, /* 退出时将通知值重置为 0 */
&ulNotifiedValue, /* 通知值在 ulNotifiedValue 中传递 */
portMAX_DELAY ); /* 无限期阻塞 */
/* 处理已锁定在通知值中的任何事件。 */
if( ( ulNotifiedValue & 0x01 ) != 0 )
{
/* 设置了位 0 - 处理由位 0 表示的任何事件。 */
prvProcessBit0Event();
}
if( ( ulNotifiedValue & 0x02 ) != 0 )
{
/* 设置了位 1 - 处理由位 1 表示的任何事件。 */
prvProcessBit1Event();
}
if( ( ulNotifiedValue & 0x04 ) != 0 )
{
/* 设置了位 2 - 处理由位 2 表示的任何事件。 */
prvProcessBit2Event();
}
/* Etc. */
}
}
9.xTaskNotifyStateClear / xTaskNotifyStateClearIndexed将通知状态清除为“未挂起”
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 必须小于 configTASK_NOTIFICATION_ARRAY_ENTRIES。 ulTaskNotifyStateClear() 没有此参数,并且始终作用于索引 0 处的通知。 |
返回值:
如果 xTask 引用的任务有一个挂起的通知,并且通知已被清除,则返回 pdTRUE。如果 xTask 引用的任务没有挂起的通知,则返回 pdFALSE。
使用示例:
/* 一个示例UART发送函数。该函数启动UART传输,然后等待传输完成的通知。
传输完成通知从UART中断发送。调用任务的通知状态在传输启动之前被清除,
以确保在任务试图阻塞其通知状态之前,它不会碰巧已经挂起。 */
void vSerialPutString( const signed char * const pcStringToSend,
unsigned short usStringLength )
{
const TickType_t xMaxBlockTime = pdMS_TO_TICKS( 5000 );
/* xSendingTask持有等待传输完成的任务的句柄。如果xSendingTask为NULL,
则表示传输没有进行中。除非之前的字符串传输完成,否则不要开始发送新的字符串。 */
if( ( xSendingTask == NULL ) && ( usStringLength > 0 ) )
{
/* 确保调用任务的第0个通知状态没有挂起。 */
xTaskNotifyStateClearIndexed( NULL, 0 );
/* 存储传输任务的句柄。这用于在传输完成后解除对任务的阻塞。 */
xSendingTask = xTaskGetCurrentTaskHandle();
/* 开始发送字符串-传输然后由中断控制。 */
UARTSendString( pcStringToSend, usStringLength );
/* 在阻塞状态下等待(所以不使用任何CPU时间),直到UART ISR向xSendingTask
发送第0个通知,在传输完成时通知(并解除阻塞)任务。 */
ulTaskNotifyTake( 0, pdTRUE, xMaxBlockTime );
}
}
9.ulTaskNotifyValueClear / ulTaskNotifyValueClearIndexed清除由 xTask 引用的任务的数组索引 uxIndexToClear 的通知值中的 ulBitsToClear 位掩码指定的位
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 以查询任务的通知值,而不清除任何位。 |
返回值:
清除ulBitsToClear指定位之前的目标任务通知值。
使用示例:
#define MESSAGE_RECEIVED_BIT 8
#define TICKS_UNTIL_TIMEOUT 100
unsigned long ulNotification, ulMessageReceivedMask;
/* 清除所有接收到的消息事件 */
ulMessageReceivedMask = 1u << MESSAGE_RECEIVED_BIT;
ulTaskNotifyValueClear( ulMessageReceivedMask );
/* 发送需要响应的消息。 */
send_message();
/* 阻塞此任务,直到它有另一个待处理的通知。在本例中,任务只使用其通知值的
MESSAGE_RECEIVED_BIT,因此下一个事件只能在接收到的消息上。 */
xTaskNotifyWait( 0u, /* 不要在输入时清除任何通知位。 */
0u, /* 退出时不要清除任何通知位。 */
&ulNotification,
TICKS_UNTIL_TIMEOUT );
/* 如果没有超时,则会收到唯一可能的事件。
在此示例中,这是MESSAGE_RECEIVED_EVENT。 */
if( ulNotification == 0u )
{
/* 处理响应超时 */
process_response_timeout();
}
else if( ulNotification == ulMessageReceivedMask )
{
/* 处理响应事件 */
process_response();
ulTaskNotifyValueClear( ulMessageReceivedMask );
}
else
{
/* 示例任务应该只收到MESSAGE_RECEIVED_EVENTS。 */
process_error();
}