21-FreeRTOS队列集API函数

1-xQueueCreateSet()

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() 先返回了队列集成员的句柄。

1.1 参数:

uxEventQueueLength 队列集存储集合中包含的队列和 信号量上发生的事件。 uxEventQueueLength 指定一次可以排队的最大事件数 。
要绝对确定事件不会丢失, 必须将 uxEventQueueLength 设置为 添加到集合中的队列长度之和,其中二进制信号量和 互斥体长度为 1,计数信号量的 长度由其最大计数值设置。 例如:

如果队列集要保存一个长度为 5 的队列, 另一个长度为 12 的队列和一个二进制信号量, 则 uxEventQueueLength 应设置为 (5 + 12 + 1) 或 18。
如果队列集要容纳三个二进制信号量, 则 uxEventQueueLength 应设置为 (1 + 1 + 1) 或 3。
如果队列集要保持最大计数为 5 的计数信号量 和最大计数为 3 的计数信号量, 则 uxEventQueueLength 应设置为 (5 + 3) 或 8。

1.2 Returns:

如果成功创建队列集,则返回所创建队列集的句柄 。 否则返回 NULL。

1.3用法示例:

/* 定义添加到队列集中的队列的长度。 */
#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. */
        }
    }
}

2-xQueueAddToSet()

queue.h
 BaseType_t xQueueAddToSet
                      (
                          QueueSetMemberHandle_t xQueueOrSemaphore,
                          QueueSetHandle_t xQueueSet
                      );

必须在 FreeRTOSConfig.h 中将 configUSE_QUEUE_SETS 设置为 1,这样 xQueueAddToSet
() API 函数才可用。

将 RTOS 队列或信号量添加至先前由 xQueueCreateSet() 调用创建的队列集。

接收(如果是队列)或获取(如果是 信号量)操作,除非 调用 xQueueSelectFromSet() 先返回了队列集成员的句柄。

2.1参数:

xQueueOrSemaphore 正在添加到队列集的队列或信号量的句柄 (转换为 QueueSetMemberHandle_t 类型)。
xQueueSet 正在添加队列或信号量的队列集句柄 。

2.2Returns:

如果队列或信号量成功添加到队列集 那么返回 pdPASS。 如果队列无法成功添加到 队列集,因为它已经是其他队列集的成员,那么返回 pdFAIL 。

3 - xQueueRemoveFromSet()

queue.h
 BaseType_t xQueueRemoveFromSet
                      (
                          QueueSetMemberHandle_t xQueueOrSemaphore,
                          QueueSetHandle_t xQueueSet
                      );

必须在 FreeRTOSConfig.h 中将 configUSE_QUEUE_SETS 设置为 1,xQueueRemoveFromSet() API 函数才可用。

从队列集中删除 RTOS 队列或信号量。

仅当队列或信号量为空时,才能从队列集中删除 RTOS 队列或信号量 。

3.1参数:

xQueueOrSemaphore 从队列集中删除的队列或信号量的句柄 (转换为 QueueSetMemberHandle_t 类型)。
xQueueSet 包含队列或信号量的队列集的句柄 。

3.2 Returns:

如果队列或信号量已成功从队列集中删除, 则返回 pdPASS。 如果队列不在队列集中,或者 队列(或信号量)不为空,则返回 pdFAIL。

3.3 用法示例:

此示例假定 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. */
}

4- xQueueSelectFromSet()

queue.h
 QueueSetMemberHandle_t xQueueSelectFromSet
                       (
                             QueueSetHandle_t xQueueSet,
                             const TickType_t xTicksToWait
                        );

必须在 FreeRTOSConfig.h 中将 configUSE_QUEUE_SETS 设置为 1,才能使用 xQueueSelectFromSet() API 函数。

xQueueSelectFromSet() 从队列集成员中选择队列或信号量, 它们要么包含数据(若选择队列),要么可供获取 (若选择信号量)。 xQueueSelectFromSet() 能有效 允许任务同时读取一个队列集中的所有 队列和信号量后阻塞(挂起)。

注意:

阻塞包含互斥锁的队列不会导致 互斥锁持有者继承被阻塞任务的优先级。
除非 xQueueSelectFromSet() 信号量)操作,除非 调用 xQueueSelectFromSet() 先返回了队列集成员的句柄。

4.1参数:

xQueueSet 任务(可能)阻塞的队列集。
xTicksToWait 调用任务保持阻塞状态(其他任务正在执行), 等待队列集成员做好准备 以便成功读取队列或获取信号量所需的最长时间, 以滴答为单位。

4.2Returns:

xQueueSelectFromSet() 将返回 队列集中包含数据的队列的句柄(转换为 QueueSetMemberHandle_t 类型) 或队列集中可用信号量的句柄(转换为 QueueSetMemberHandle_t 类型), 如果在指定的阻塞时间到期之前不存在这样的队列或信号量, 则返回 NULL。

5 xQueueSelectFromSetFromISR()

queue.h
 QueueSetMemberHandle_t xQueueSelectFromSetFromISR
                       (
                             QueueSetHandle_t xQueueSet
                        );

必须在 FreeRTOSConfig.h 中将 configUSE_QUEUE_SETS 设置为 1,xQueueSelectFromSetFromISR() API 函数才可用。

xQueueSelectFromSet() 的一个版本, 可以从中断服务程序 (ISR) 中使用。

5.1参数:

xQueueSet 正在查询的队列集。 因为此函数设计为从中断中使用, 所以无法在读取时阻塞 。
Returns:
xQueueSelectFromSetFromISR() 将返回一个队列的句柄(被转换为 QueueSetMemberHandle_t 类型), 该队列包含在包含数据的队列集中, 或队列集中可用信号量的句柄(转换为 QueueSetMemberHandle_t 类型), 该信号量包含在可用的队列集中;如果不存在这样的队列或信号量,则返回 NULL 。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
FreeRTOS提供了一些与消息队列相关的API。引用中提到了一些关键的API函数和机制,如任务从阻塞态转为就绪态的机制以及先进先出原则和后进先出原则。引用中介绍了消息队列的创建及初始化过程,并提到了消息队列控制块的结构和成员。引用中展示了消息队列删除函数vQueueDelete()的源码。 因此,FreeRTOS的消息队列API包括但不限于以下几个函数: 1. xQueueCreate():用于创建一个消息队列,并返回一个消息队列句柄。 2. xQueueSend():用于向消息队列发送一条消息。 3. xQueueReceive():用于从消息队列接收一条消息。 4. xQueuePeek():用于查看消息队列中的下一条消息,但不会将其从队列中移除。 5. xQueueReset():用于重置消息队列,清空其中的所有消息。 6. xQueueDelete():用于删除消息队列,释放相应的内存空间。 这些API函数可以在FreeRTOSAPI文档中找到详细的说明和使用示例。它们提供了一种方便和灵活的方式来实现任务之间的异步通信和数据传递。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [【FreeRTOSFreeRTOS学习笔记(14)— FreeRTOS的消息队列(原生API)](https://blog.csdn.net/qq_39400113/article/details/120381691)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南山府嵌入式

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值