队列集
[API]
FreeRTOS 队列集 API 函数
xQueueCreateSet()
[队列集 API]
queue.h
QueueSetHandle_t xQueueCreateSet ( const UBaseType_t uxEventQueueLength );
必须在 FreeRTOSConfig.h 中将 configUSE_QUEUE_SETS 设置为 1,xQueueCreateSet() API 函数才可用。
队列集提供了一种机制,允许 RTOS 任务从多个 RTOS 队列或信号量同时进行读取操作后阻塞(挂起)。 请注意, 除了使用队列集之外,还有更简单的替代方法。 有关详细信息,请参阅 阻塞多个对象页面 。
必须使用调用 xQueueCreateSet() 显式创建队列集, 然后才能使用它。 创建后,可以将标准 FreeRTOS 队列和信号量添加到集合中 (通过调用 xQueueAddToSet())。 然后,使用 xQueueSelectFromSet() 确定集合中包含的队列或信号量中的哪些(如果有) 处于队列读取或信号量获取操作将成功的状态。
注意:
- 队列和信号量在添加到队列集时必须为空 。 在添加对象时要特别小心, 比如使用已经可用的信号量创建的二进制信号量 [如果使用 vSemaphoreCreateBinary() 宏创建信号量,则属于这种情况, 但如果信号量是使用首选的 xSemaphoreCreateBinary() 函数创建的,则不是这种情况]。
- 阻塞包含互斥锁的队列集不会导致 互斥锁持有者继承已阻塞任务的优先级。
- 添加到队列集的每个队列中的每个空格都需要额外的 4 个字节 RAM 。 因此,不应将具有较高最大计数值的计数信号量 添加到队列集中。
- 不得对队列集的成员执行接收(若为队列)或获取(若为 信号量)操作,除非 调用 xQueueSelectFromSet() 先返回了队列集成员的句柄。
参数:
uxEventQueueLength | 队列集存储集合中包含的队列和 信号量上发生的事件。 uxEventQueueLength 指定一次可以排队的最大事件数 。 要绝对确定事件不会丢失, 必须将 uxEventQueueLength 设置为 添加到集合中的队列长度之和,其中二进制信号量和 互斥体长度为 1,计数信号量的 长度由其最大计数值设置。 例如:
|
Returns:
如果成功创建队列集,则返回所创建队列集的句柄 。 否则返回 NULL。
用法示例:
/* Define the lengths of the queues that will be added to the queue set. */ #define QUEUE_LENGTH_1 10 #define QUEUE_LENGTH_2 10 /* Binary semaphores have an effective length of 1. */ #define BINARY_SEMAPHORE_LENGTH 1 /* Define the size of the item to be held by queue 1 and queue 2 respectively. The values used here are just for demonstration purposes. */ #define ITEM_SIZE_QUEUE_1 sizeof( uint32_t ) #define ITEM_SIZE_QUEUE_2 sizeof( something_else_t ) /* The combined length of the two queues and binary semaphore that will be added to the queue set. */ #define COMBINED_LENGTH ( QUEUE_LENGTH_1 + QUEUE_LENGTH_2 + BINARY_SEMAPHORE_LENGTH ) void vAFunction( void ) { static QueueSetHandle_t xQueueSet; QueueHandle_t xQueue1, xQueue2, xSemaphore; QueueSetMemberHandle_t xActivatedMember; uint32_t xReceivedFromQueue1; something_else_t xReceivedFromQueue2; /* Create the queue set large enough to hold an event for every space in every queue and semaphore that is to be added to the set. */ xQueueSet = xQueueCreateSet( COMBINED_LENGTH ); /* Create the queues and semaphores that will be contained in the set. */ xQueue1 = xQueueCreate( QUEUE_LENGTH_1, ITEM_SIZE_QUEUE_1 ); xQueue2 = xQueueCreate( QUEUE_LENGTH_2, ITEM_SIZE_QUEUE_2 ); /* Create the semaphore that is being added to the set. */ xSemaphore = xSemaphoreCreateBinary(); /* Check everything was created. */ configASSERT( xQueueSet ); configASSERT( xQueue1 ); configASSERT( xQueue2 ); configASSERT( xSemaphore ); /* Add the queues and semaphores to the set. Reading from these queues and semaphore can only be performed after a call to xQueueSelectFromSet() has returned the queue or semaphore handle from this point on. */ xQueueAddToSet( xQueue1, xQueueSet ); xQueueAddToSet( xQueue2, xQueueSet ); xQueueAddToSet( xSemaphore, xQueueSet ); for( ;; ) { /* Block to wait for something to be available from the queues or semaphore that have been added to the set. Don't block longer than 200ms. */ xActivatedMember = xQueueSelectFromSet( xQueueSet, 200 / portTICK_PERIOD_MS ); /* Which set member was selected? Receives/takes can use a block time of zero as they are guaranteed to pass because xQueueSelectFromSet() would not have returned the handle unless something was available. */ if( xActivatedMember == xQueue1 ) { xQueueReceive( xActivatedMember, &xReceivedFromQueue1, 0 ); vProcessValueFromQueue1( xReceivedFromQueue1 ); } else if( xActivatedMember == xQueue2 ) { xQueueReceive( xActivatedMember, &xReceivedFromQueue2, 0 ); vProcessValueFromQueue2( &xReceivedFromQueue2 ); } else if( xActivatedMember == xSemaphore ) { /* Take the semaphore to make sure it can be "given" again. */ xSemaphoreTake( xActivatedMember, 0 ); vProcessEventNotifiedBySemaphore(); break; } else { /* The 200ms block time expired without an RTOS queue or semaphore being ready to process. */ } } }
xQueueAddToSet()
[队列集 API]
queue.h
BaseType_t xQueueAddToSet ( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet );
必须在 FreeRTOSConfig.h 中将 configUSE_QUEUE_SETS 设置为 1,这样 xQueueAddToSet () API 函数才可用。
将 RTOS 队列或信号量添加至先前由 xQueueCreateSet() 调用创建的队列集。
接收(如果是队列)或获取(如果是 信号量)操作,除非 调用 xQueueSelectFromSet() 先返回了队列集成员的句柄。
参数:
xQueueOrSemaphore | 正在添加到队列集的队列或信号量的句柄 (转换为 QueueSetMemberHandle_t 类型)。 |
xQueueSet | 正在添加队列或信号量的队列集句柄 。 |
Returns:
如果队列或信号量成功添加到队列集 那么返回 pdPASS。 如果队列无法成功添加到 队列集,因为它已经是其他队列集的成员,那么返回 pdFAIL 。
用法示例:
请参阅 xQueueCreateSet() 文档页面上的示例。
xQueueRemoveFromSet()
[队列集 API]
queue.h
BaseType_t xQueueRemoveFromSet ( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet );
必须在 FreeRTOSConfig.h 中将 configUSE_QUEUE_SETS 设置为 1,xQueueRemoveFromSet() API 函数才可用。
从队列集中删除 RTOS 队列或信号量。
仅当队列或信号量为空时,才能从队列集中删除 RTOS 队列或信号量 。
参数:
xQueueOrSemaphore | 从队列集中删除的队列或信号量的句柄 (转换为 QueueSetMemberHandle_t 类型)。 |
xQueueSet | 包含队列或信号量的队列集的句柄 。 |
Returns:
如果队列或信号量已成功从队列集中删除, 则返回 pdPASS。 如果队列不在队列集中,或者 队列(或信号量)不为空,则返回 pdFAIL。
用法示例:
此示例假定 xQueueSet 是已创建的队列集, 而 xQueue 是已创建并添加到 xQueueSet 中的队列。
if( xQueueRemoveFromSet( xQueue, xQueueSet ) != pdPASS )
{
/* Either xQueue was not a member of the xQueueSet set, or xQueue is
not empty and therefore cannot be removed from the set. */
}
else
{
/* The queue was successfully removed from the set. */
}
xQueueSelectFromSet()
[队列集 API]
queue.h
QueueSetMemberHandle_t xQueueSelectFromSet ( QueueSetHandle_t xQueueSet, const TickType_t xTicksToWait );
必须在 FreeRTOSConfig.h 中将 configUSE_QUEUE_SETS 设置为 1,才能使用 xQueueSelectFromSet() API 函数。
xQueueSelectFromSet() 从队列集成员中选择队列或信号量, 它们要么包含数据(若选择队列),要么可供获取 (若选择信号量)。 xQueueSelectFromSet() 能有效 允许任务同时读取一个队列集中的所有 队列和信号量后阻塞(挂起)。
注意:
- 您也可以不使用队列集,而是采用更简单的替代方案。 请参阅 阻塞多个对象页面 了解详情。
- 阻塞包含互斥锁的队列不会导致 互斥锁持有者继承被阻塞任务的优先级。
- 除非 xQueueSelectFromSet() 信号量)操作,除非 调用 xQueueSelectFromSet() 先返回了队列集成员的句柄。
参数:
xQueueSet | 任务(可能)阻塞的队列集。 |
xTicksToWait | 调用任务保持阻塞状态(其他任务正在执行), 等待队列集成员做好准备 以便成功读取队列或获取信号量所需的最长时间, 以滴答为单位。 |
Returns:
xQueueSelectFromSet() 将返回 队列集中包含数据的队列的句柄(转换为 QueueSetMemberHandle_t 类型) 或队列集中可用信号量的句柄(转换为 QueueSetMemberHandle_t 类型), 如果在指定的阻塞时间到期之前不存在这样的队列或信号量, 则返回 NULL。
用法示例:
请参阅 xQueueCreateSet() 文档页面上的示例。
xQueueSelectFromSetFromISR()
[队列集 API]
queue.h
QueueSetMemberHandle_t xQueueSelectFromSetFromISR ( QueueSetHandle_t xQueueSet );
必须在 FreeRTOSConfig.h 中将 configUSE_QUEUE_SETS 设置为 1,xQueueSelectFromSetFromISR() API 函数才可用。
xQueueSelectFromSet() 的一个版本, 可以从中断服务程序 (ISR) 中使用。
参数:
xQueueSet | 正在查询的队列集。 因为此函数设计为从中断中使用, 所以无法在读取时阻塞 。 |
Returns:
xQueueSelectFromSetFromISR() 将返回一个队列的句柄(被转换为 QueueSetMemberHandle_t 类型), 该队列包含在包含数据的队列集中, 或队列集中可用信号量的句柄(转换为 QueueSetMemberHandle_t 类型), 该信号量包含在可用的队列集中;如果不存在这样的队列或信号量,则返回 NULL 。