当前位置: 首页 > news >正文

FreeRTOS(7)队列集

队列集

在使用队列进行任务之间的“沟通交流”时,一个队列只允许任务间传递的消息为同一种数据类型,如果需要在任务间传递不同数据类型的消息时,那么就可以使用队列集。 FreeRTOS提供的队列集功能可以对多个队列进行“监听”,只要被监听的队列中有一个队列有有效的消息,那么队列集的读取任务都可以读取到消息,如果读取任务因读取队列集而被阻塞,那么队列集将解除读取任务的阻塞。使用队列集的好处在于,队列集可以读取多个队列中的消息,而无需遍历所有待读取的队列,以确定具体读取哪一个队列。使用队列集功能,需要在 FreeRTOSConfig.h 文件中将配置项 configUSE_QUEUE_SETS 配置为 1,来启用队列集功能。

队列集相关 API 函数

函数描述
xQueueCreateSet()创建队列集
xQueueAddToSet()队列添加到队列集中
xQueueRemoveFromSet()从队列集中移除队列
xQueueSelectFromSet()获取队列集中有有效消息的队列
xQueueSelectFromSetFromISR()在中断中获取队列集中有有效消息的队列

函数 xQueueCreateSet()

此函数用于创建队列集,该函数在 queue.c 文件中有定义, 函数的原型如下所示:

    QueueSetHandle_t xQueueCreateSet( const UBaseType_t uxEventQueueLength )
    {
        QueueSetHandle_t pxQueue;

        traceENTER_xQueueCreateSet( uxEventQueueLength );

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

        traceRETURN_xQueueCreateSet( pxQueue );

        return pxQueue;
    }
形参描述
uxEventQueueLength队列集可容纳的队列数量
返回值描述
NULL队列集创建失败
其他值队列集创建成功,返回队列集

函数 xQueueAddToSet()

此函数用于往队列集中添加队列,要注意的时,队列在被添加到队列集之前,队列中不能有有效的消息,该函数在 queue.c 文件中有定义,函数的原型如下所示:

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

        traceENTER_xQueueAddToSet( xQueueOrSemaphore, xQueueSet );

        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();

        traceRETURN_xQueueAddToSet( xReturn );

        return xReturn;
    }
形参描述
xQueueOrSemaphore待添加的队列
xQueueSet队列集
返回值描述
pdPASS队列集添加队列成功
pdFAIL队列集添加队列失败

函数 xQueueRemoveFromSet()

此函数用于从队列集中移除队列, 要注意的时,队列在从队列集移除之前,必须没有有效的消息, 该函数在 queue.c 文件中有定义,函数的原型如下所示:

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

        traceENTER_xQueueRemoveFromSet( xQueueOrSemaphore, xQueueSet );

        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;
        }

        traceRETURN_xQueueRemoveFromSet( xReturn );

        return xReturn;
    }
形参描述
xQueueOrSemaphore待移除的队列
xQueueSet队列集
返回值描述
pdPASS队列集移除队列成功
pdFAIL队列集移除队列失败

函数 xQueueSelectFromSet()

此函数用于在任务中获取队列集中有有效消息的队列,该函数在 queue.c 文件中有定义,函数的原型如下所示:

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

        traceENTER_xQueueSelectFromSet( xQueueSet, xTicksToWait );

        ( void ) xQueueReceive( ( QueueHandle_t ) xQueueSet, &xReturn, xTicksToWait );

        traceRETURN_xQueueSelectFromSet( xReturn );

        return xReturn;
    }
形参描述
xQueueSet队列集
xTicksToWait阻塞超时时间
返回值描述
NULL获取消息失败
其他值获取到消息的队列

函数 xQueueSelectFromSetFromISR()

此函数用于在中断中获取队列集中有有效消息的队列,该函数在 queue.c 文件中有定义,函数的原型如下所示:

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

        traceENTER_xQueueSelectFromSetFromISR( xQueueSet );

        ( void ) xQueueReceiveFromISR( ( QueueHandle_t ) xQueueSet, &xReturn, NULL );

        traceRETURN_xQueueSelectFromSetFromISR( xReturn );

        return xReturn;
    }
形参描述
xQueueSet队列集
返回值描述
NULL获取消息失败
其他值获取到消息的队列

队列集操作实验

TaskHandle_t xTaskHandle_1;
TaskHandle_t xTaskHandle_2;

void vTaskFunction_1(void *pvParameters);
void vTaskFunction_2(void *pvParameters);

QueueSetHandle_t xQueueSet;
QueueHandle_t	xQueue1;
QueueHandle_t	xQueue2;

//init
//队列集长度 ≥ 绑定的队列数量 × 每个队列可能产生的事件数
xQueueSet = xQueueCreateSet(4);

xQueue1 = xQueueCreate(2, sizeof(int));
xQueue2 = xQueueCreate(2, sizeof(int));

xQueueAddToSet(xQueue1, xQueueSet);
xQueueAddToSet(xQueue2, xQueueSet);

xTaskCreate(vTaskFunction_1, "Task1", 8192, NULL, 1, &xTaskHandle_1 );
xTaskCreate(vTaskFunction_2, "Task2", 8192, NULL, 1, &xTaskHandle_2 );

void vTaskFunction_1(void *pvParameters)
{
	int i=0;
    while(1) {
		if(i%2 == 0) {
			xQueueSend(xQueue1, &i, portMAX_DELAY);
		} else {
			xQueueSend(xQueue2, &i, portMAX_DELAY);
		}
		i++;
		
        vTaskDelay(200);
    }
}

void vTaskFunction_2(void *pvParameters)
{   
	int queue_recv = 0;
	QueueSetMemberHandle_t activate_member;
    while(1) {
		activate_member = xQueueSelectFromSet(xQueueSet, portMAX_DELAY);
		if (activate_member == xQueue1) {
			xQueueReceive(activate_member, &queue_recv, portMAX_DELAY);
			printf("接收到来自 xQueue1 的消息: %d\r\n", queue_recv);
		}
		else if (activate_member == xQueue2) {
			xQueueReceive(activate_member, &queue_recv, portMAX_DELAY);
			printf("接收到来自 xQueue2 的消息: %d\r\n", queue_recv);
		}

		vTaskDelay(200);
    }
}

测试结果:

接收到来自 xQueue1 的消息: 0
接收到来自 xQueue2 的消息: 1
接收到来自 xQueue1 的消息: 2
接收到来自 xQueue2 的消息: 3
接收到来自 xQueue1 的消息: 4
接收到来自 xQueue2 的消息: 5
接收到来自 xQueue1 的消息: 6
接收到来自 xQueue2 的消息: 7
接收到来自 xQueue1 的消息: 8
接收到来自 xQueue2 的消息: 9
接收到来自 xQueue1 的消息: 10

相关文章:

  • Redis 主从复制详解:实现高可用与数据备份
  • 【MySQL - 表的内外连接】
  • 【13】单片机编程核心技巧:乘法运算
  • 《Python全栈开发》第2课:HTML骨架搭建 - 从零编写个人简历页面
  • 数字IC后端设计实现教程 |Innovus ICC2 Routing Pin Access Setting设置方法
  • 第十五届蓝桥杯大学B组(握手问题、小球反弹、好数)
  • ChatGPT课件分享(37页PPT)
  • 【亲测有效】Mac系统升级或降级Node.js版本,Mac系统调整node.js版本
  • 【3D视觉学习笔记1】针孔相机模型与坐标系变换
  • 【Azure 架构师学习笔记】- Azure Databricks (17) --Delta Live Table和Delta Table
  • 面试之《webpack从输入到输出经历了什么》
  • 基础网络安全-K8S 配置Ingress-controller 通过HTTPS处理服务请求
  • GB8599-2023标准测试包/小规格测试包/标准生物测试包1.5kg/满负载织物7.5kg/不锈钢金属测试包/空腔负载试验的过程挑战装置(PCD)
  • Linux网络编程之——网络初认识
  • 启智畅想的集装箱号码识别技术,效率与技术的完美结合
  • [杂学笔记] TCP和UDP的区别,对http接口解释 , Cookie和Session的区别 ,http和https的区别 , 智能指针 ,断点续传
  • AF3 shaped_categorical函数解读
  • 大数据hadoop课程笔记
  • HTTPS协议原理:在Linux世界里的加密冒险
  • Jupyter Notebook 全平台安装与配置教程(附Python/Anaconda双方案)
  • 阿森纳被打得毫无脾气,回天无力的阿尔特塔只剩嘴硬
  • 司法部谈民营经济促进法:对违规异地执法问题作出禁止性规定
  • 暴雨蓝色预警:南方开启较强降雨过程
  • 五一期间7名游客接连被困青海荒漠,警方提醒严禁非法穿越
  • 机器人助力、入境游、演出引流:假期纳客千万人次城市有高招
  • 安顺市原副市长、市公安局原局长顾长华任贵州省民委副主任