首页 > 其他分享 >FreeRTOS--队列集

FreeRTOS--队列集

时间:2023-12-02 18:44:21浏览次数:32  
标签:pxQueueSetContainer FreeRTOS -- configUSE xReturn QUEUE 队列 SETS

示例源码基于FreeRTOS V9.0.0

队列集

1. 概述

队列集的本质也是队列,只不过里面存放的是“队列句柄”。

当任务需要及时读取多个队列时,可以使用队列集。它类似于posix的多路复用思想。可以将想要监听消息的队列放入队列集中,当其中有队列有数据达到时,队列集的接口会返回可读的队列句柄,用户获得句柄后,就可以从队列中读取数据。

2. 接口API

2.1 创建队列集

#if( ( configUSE_QUEUE_SETS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )

    QueueSetHandle_t xQueueCreateSet( const UBaseType_t uxEventQueueLength )
    {
    QueueSetHandle_t pxQueue;

        pxQueue = xQueueGenericCreate( uxEventQueueLength, sizeof( Queue_t * ), queueQUEUE_TYPE_SET );

        return pxQueue;
    }

#endif /* configUSE_QUEUE_SETS */

创建队列集使用xQueueCreateSet接口,仅需传入队列深度参数。使用队列集,需要开启宏configUSE_QUEUE_SETS和configSUPPORT_DYNAMIC_ALLOCATION;

队列集创建实际调用的是xQueueGenericCreate接口,它本质也是个队列,其数据项是队列句柄。

2.2 添加队列到队列集

#if ( configUSE_QUEUE_SETS == 1 )

    BaseType_t xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet )
    {
    BaseType_t xReturn;

        taskENTER_CRITICAL();
        {
            if( ( ( Queue_t * ) xQueueOrSemaphore )->pxQueueSetContainer != NULL )
            {
                /* Cannot add a queue/semaphore to more than one queue set. */
                xReturn = pdFAIL;
            }
            else if( ( ( Queue_t * ) xQueueOrSemaphore )->uxMessagesWaiting != ( UBaseType_t ) 0 )
            {
                /* Cannot add a queue/semaphore to a queue set if there are already
                items in the queue/semaphore. */
                xReturn = pdFAIL;
            }
            else
            {
                ( ( Queue_t * ) xQueueOrSemaphore )->pxQueueSetContainer = xQueueSet;
                xReturn = pdPASS;
            }
        }
        taskEXIT_CRITICAL();

        return xReturn;
    }

#endif /* configUSE_QUEUE_SETS */

添加队列到队列集,需要在临界区内操作。同时,待添加的队列,其原先必须不属于任何队列集(pxQueueSetContainer需指向空),且队列需为空。

添加队列到队列集,本质操作是把队列的pxQueueSetContainer指针指向队列集即可。

2.3 删除队列集的队列

#if ( configUSE_QUEUE_SETS == 1 )

    BaseType_t xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet )
    {
    BaseType_t xReturn;
    Queue_t * const pxQueueOrSemaphore = ( Queue_t * ) xQueueOrSemaphore;

        if( pxQueueOrSemaphore->pxQueueSetContainer != xQueueSet )
        {
            /* The queue was not a member of the set. */
            xReturn = pdFAIL;
        }
        else if( pxQueueOrSemaphore->uxMessagesWaiting != ( UBaseType_t ) 0 )
        {
            /* It is dangerous to remove a queue from a set when the queue is
            not empty because the queue set will still hold pending events for
            the queue. */
            xReturn = pdFAIL;
        }
        else
        {
            taskENTER_CRITICAL();
            {
                /* The queue is no longer contained in the set. */
                pxQueueOrSemaphore->pxQueueSetContainer = NULL;
            }
            taskEXIT_CRITICAL();
            xReturn = pdPASS;
        }

        return xReturn;
    } /*lint !e818 xQueueSet could not be declared as pointing to const as it is a typedef. */

#endif /* configUSE_QUEUE_SETS */

待删除的队列,其队列集需存在,且只有空队列才允许从队列集中删除。

删除队列集的队列,需要在临界区内操作。删除的本质操作是把队列的pxQueueSetContainer指针置空。

2.4 等待队列可读

#if ( configUSE_QUEUE_SETS == 1 )

    QueueSetMemberHandle_t xQueueSelectFromSet( QueueSetHandle_t xQueueSet, TickType_t const xTicksToWait )
    {
    QueueSetMemberHandle_t xReturn = NULL;

        ( void ) xQueueGenericReceive( ( QueueHandle_t ) xQueueSet, &xReturn, xTicksToWait, pdFALSE ); /*lint !e961 Casting from one typedef to another is not redundant. */
        return xReturn;
    }

#endif /* configUSE_QUEUE_SETS */
/*-----------------------------------------------------------*/

#if ( configUSE_QUEUE_SETS == 1 )

    QueueSetMemberHandle_t xQueueSelectFromSetFromISR( QueueSetHandle_t xQueueSet )
    {
    QueueSetMemberHandle_t xReturn = NULL;

        ( void ) xQueueReceiveFromISR( ( QueueHandle_t ) xQueueSet, &xReturn, NULL ); /*lint !e961 Casting from one typedef to another is not redundant. */
        return xReturn;
    }

#endif /* configUSE_QUEUE_SETS */

FreeRTOS提供了类似posix select操作的xQueueSelectFromSet接口,它等待队列集可读,并返回从队列集读取的数据(可读队列的句柄)。

队列集内的队列句柄,均是可读的队列。当有任务或中断往队列写数据时,队列非空可读,如果开启了configUSE_QUEUE_SETS,会同时把队列句柄置入队列集中(见xQueueGenericSend)。

xQueueSelectFromSet对应的中断版本是xQueueSelectFromSetFromISR。

关于xQueueGenericReceive和xQueueReceiveFromISR以及xQueueGenericSend、xQueueGenericSendFromISR,见 队列

2.5 通知队列可读

#if ( configUSE_QUEUE_SETS == 1 )

    static BaseType_t prvNotifyQueueSetContainer( const Queue_t * const pxQueue, const BaseType_t xCopyPosition )
    {
    Queue_t *pxQueueSetContainer = pxQueue->pxQueueSetContainer;
    BaseType_t xReturn = pdFALSE;

        /* This function must be called form a critical section. */

        configASSERT( pxQueueSetContainer );
        configASSERT( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength );

        if( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength )
        {
            const int8_t cTxLock = pxQueueSetContainer->cTxLock;

            traceQUEUE_SEND( pxQueueSetContainer );

            /* The data copied is the handle of the queue that contains data. */
            xReturn = prvCopyDataToQueue( pxQueueSetContainer, &pxQueue, xCopyPosition );

            if( cTxLock == queueUNLOCKED )
            {
                if( listLIST_IS_EMPTY( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) == pdFALSE )
                {
                    if( xTaskRemoveFromEventList( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) != pdFALSE )
                    {
                        /* The task waiting has a higher priority. */
                        xReturn = pdTRUE;
                    }
                    else
                    {
                        mtCOVERAGE_TEST_MARKER();
                    }
                }
                else
                {
                    mtCOVERAGE_TEST_MARKER();
                }
            }
            else
            {
                pxQueueSetContainer->cTxLock = ( int8_t ) ( cTxLock + 1 );
            }
        }
        else
        {
            mtCOVERAGE_TEST_MARKER();
        }

        return xReturn;
    }

#endif /* configUSE_QUEUE_SETS */

prvNotifyQueueSetContainer是静态接口,定义在queue.c文件,仅对内使用,不对外开放;

prvNotifyQueueSetContainer在xQueueGenericSend、xQueueGenericSendFromISR、xQueueGiveFromISR、prvUnlockQueue内调用,见 队列

prvNotifyQueueSetContainer支持任务和中断内使用。

通知队列可读的本质操作是将可读队列自身的句柄拷贝入队列集中。

当队列集满则接口返回失败;

当队列cTxLock非锁定时,判断是否有任务阻塞等待从队列集接收数据(等待可读队列),若有则将最高优先级任务从阻塞列表移除,移入就绪等待列表,如果任务的优先级高于当前任务,返回pdTRUE表示需要进行任务切换;

当队列cTxLock锁定时,累加cTxLock计数,待调用prvUnlockQueue时再操作阻塞列表和任务切换;

因为prvNotifyQueueSetContainer可能在中断内使用,所以函数内部不直接唤醒切换任务,而是根据返回值标记,返回pdTRUE表示需要任务切换;

标签:pxQueueSetContainer,FreeRTOS,--,configUSE,xReturn,QUEUE,队列,SETS
From: https://www.cnblogs.com/hjx168/p/17872018.html

相关文章

  • [Codeforces] CF1675D Vertical Paths
    题目描述给定一棵由\(n\)个顶点组成的有根树。顶点由\(1\)到\(n\)编号。任何顶点都可以是树的根。请在树上找出这样一组路径:每个顶点恰好属于一条路径,每条路径可以包含一个或多个顶点;在每条路径中,每个节点的下一个节点是当前节点的子节点(即路径总是向下——从父节点......
  • 关于 SAP 标准 OData 服务 /sap/bc/adt/ato/settings 的作用
    SAPODataService/sap/bc/adt/ato/settings介绍简介/sap/bc/adt/ato/settings是SAP中一个标准的OData服务,用于处理与ABAPDevelopmentTools(ADT)相关的设置。ADT提供了开发、维护和管理ABAP程序的工具,而这个OData服务允许通过HTTP协议访问ADT设置的相关信......
  • SAP ABAP 里如何高效找到修改某个数据库表字段的 ABAP 程序的三种思路介绍试读版
    我的知识星球里,有朋友提问:公司的SAP中,总部开发了一个功能去更新采购订单行上的收货地址字段EKPO-ADRN2,我尝试着去Debug,但找不到最终是哪段程序更新了这一个字段。SAT也用了,也发现不了。不过我对SAT也不熟。有什么思路可以快速Debug找到那段更新程序不?其实这种需......
  • 关于企业级 Web 应用搜索引擎优化(Search Engine Optimization)的一些工作经验分享
    笔者之前的社区文章,分享了自己在日常工作中从事企业级Web应用开发的一些工作体会:企业级Web应用里使用CSS调整应用外观的一些例子谈谈企业级Angular应用的二次开发-基于AngularComponent替换的Extensibility支持案例介绍所谓企业级前端应用,是指为大型企业或组......
  • 聪明办法学Python_task4_11.28-12.2
    聪明办法学Python_task4_11.28-12.2聪明办法学Python_task4_11.28-12.21.task06循环1.1while循环1.2for循环1.3循环控制语句1.4range()函数2.task07字符串2.1字符串构成2.2字符串操作2.2.1字符串运算2.2.2索引&切片2.2.3相关函数1.task06......
  • 什么是电商领域的 drop sale
    "Dropsale"是电商领域的一种销售策略,通常指的是在特定时间点、短暂时间内发布限量商品,以抢购的形式进行销售。这种销售模式旨在通过短时间内的高度紧张和竞争,刺激消费者的购买欲望,从而达到快速销售产品的目的。在Dropsale中,商品的数量有限,往往比较稀缺,因此消费者需要迅速采取......
  • 事务码 RZ11 对 SAP ABAP 系统管理员( Basis )的作用
    SAPABAP系统中的事务码RZ11是一个非常重要的工具,它主要用于显示和维护SAP系统的参数。这些参数影响了SAP系统的运行,包括内存管理,数据库交互,安全性设置等。RZ11提供了一种方法,允许管理员或开发者查看和修改这些参数,以便调整系统的运行方式,以满足特定的需求或优化性能。例......
  • FreeRTOS--队列
    示例源码基于FreeRTOSV9.0.0队列1.概述FreeRTOS的队列,支持任务与任务间的通信,以及任务与中断间的通信。它是FreeRTOS系统中主要的任务间通信方式。队列内的消息,是通过拷贝方式传递,而非指针。队列除了基本的先进先出特性,也支持往队列首部写入数据。FreeRTOS基于队列进行扩......
  • 华为云IotDA平台与OBS进行数据转发并使用ECS服务器完成数据调用
    华为云IotDA平台与OBS进行数据转发并使用ECS服务器完成数据调用一、通过IotDA平台接入物联网设备参考博客:https://www.cnblogs.com/gitcatone/p/17796975.html二、注册ECS服务器并进行远程控制产品简介ECS弹性服务器,一款运行在云端的弹性虚拟计算机,能够实现弹性储存容量与......
  • linux下使用git上传项目代码到github
    一、创建一个仓库​ 想要上传项目代码到github我们首先需要有一个GitHub账号,具体怎么注册自行搜索,然后我们需要创建一个仓库如图:​ 如图我们创建一个公共仓库,写完名字,描述,和增加一个readme文件二、密钥​ 直接使用命令后面是你的注册邮箱,选项直接回车就好。ssh-keygen-t......