news 2026/9/5 23:49:21

FreeRTOS队列:入队与出队详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
FreeRTOS队列:入队与出队详解

一、基本概念

入队(Enqueue):向队列中添加数据(发送消息)出队(Dequeue):从队列中获取数据(接收消息)

FreeRTOS队列采用FIFO(先进先出)机制,是任务间通信的核心方式。队列存储的是数据的拷贝,而非指针,确保了数据安全。

二、队列数据结构

队列的核心结构体Queue_t包含以下关键成员:

typedef struct QueueDefinition { int8_t *pcHead; // 指向队列存储区开始地址 int8_t *pcWriteTo; // 指向存储区中下一个空闲位置 union { QueuePointers_t xQueue; // 队列相关数据 SemaphoreData_t xSemaphore; // 信号量相关数据 } u; List_t xTasksWaitingToSend; // 等待发送任务列表(按优先级排序) List_t xTasksWaitingToReceive; // 等待接收任务列表(按优先级排序) volatile UBaseType_t uxMessagesWaiting; // 当前队列中消息数量 UBaseType_t uxLength; // 队列长度(最大可存储消息数) UBaseType_t uxItemSize; // 每个消息的大小 volatile int8_t cRxLock; // 接收锁 } Queue_t;

队列空/满判断

  • 队列为空pcWriteTo == pcReadFrom
  • 队列已满pcWriteTo + itemSize == pcReadFrom(考虑回绕)

三、入队操作

1. 入队函数

// 向队列尾部入队(默认方式) BaseType_t xQueueSendToBack(QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait); // 向队列头部入队 BaseType_t xQueueSendToFront(QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait); // 覆写入队(仅当队列长度为1时有效) BaseType_t xQueueOverwrite(QueueHandle_t xQueue, const void *pvItemToQueue);

2. 入队操作原理

  1. 检查队列状态

    • 如果队列未满,继续入队
    • 如果队列已满,根据等待时间决定处理方式
  2. 数据拷贝

    • 调用prvCopyDataToQueue将数据从源地址拷贝到队列存储区
    • uxMessagesWaiting(消息数量)+1
  3. 任务唤醒

    • 如果有任务在等待接收(xTasksWaitingToReceive非空)
    • 将等待接收任务从阻塞态唤醒,加入就绪队列
    • 调用vTaskMissedYield()进行任务切换
  4. 队列满处理

    • 如果等待时间不为0,将当前任务加入等待发送列表
    • 如果等待时间=0,直接返回errQUEUE_FULL

3. 入队阻塞机制

阻塞时间行为
0立即返回,不等待
0 ~ portMAX_DELAY等待指定时间,超时后返回
portMAX_DELAY无限等待,直到队列有空闲位置

四、出队操作

1. 出队函数

// 从队列接收数据(出队并删除数据) BaseType_t xQueueReceive(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait); // 从队列读取数据(出队但不删除数据) BaseType_t xQueuePeek(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait);

2. 出队操作原理

  1. 检查队列状态

    • 如果队列非空,继续出队
    • 如果队列为空,根据等待时间决定处理方式
  2. 数据拷贝

    • 将队列中的数据拷贝到接收缓冲区
    • uxMessagesWaiting(消息数量)-1
  3. 任务唤醒

    • 如果有任务在等待发送(xTasksWaitingToSend非空)
    • 将等待发送任务从阻塞态唤醒,加入就绪队列
    • 调用vTaskMissedYield()进行任务切换
  4. 队列空处理

    • 如果等待时间不为0,将当前任务加入等待接收列表
    • 如果等待时间=0,直接返回errQUEUE_EMPTY

3. 出队阻塞机制

阻塞时间行为
0立即返回,不等待
0 ~ portMAX_DELAY等待指定时间,超时后返回
portMAX_DELAY无限等待,直到队列有消息

五、入队与出队的对比

特性入队出队
数据传递方式值传递(拷贝数据)值传递(拷贝数据)
队列满处理阻塞等待或返回错误队列满不影响入队
队列空处理队列空不影响出队阻塞等待或返回错误
阻塞优先级优先级最高的任务先被唤醒优先级最高的任务先被唤醒
消息顺序FIFO(先进先出)FIFO(先进先出)

六、实际使用示例

入队示例(发送消息)

// 创建队列 QueueHandle_t xQueue = xQueueCreate(5, sizeof(uint32_t)); // 任务中发送消息 void SenderTask(void *pvParameters) { uint32_t data = 0; while(1) { data++; // 向队列尾部发送数据,阻塞等待10个tick if(xQueueSendToBack(xQueue, &data, 10) != pdPASS) { // 队列满,处理错误 } } }

出队示例(接收消息)

// 任务中接收消息 void ReceiverTask(void *pvParameters) { uint32_t data; while(1) { // 从队列头部接收数据,永久阻塞 if(xQueueReceive(xQueue, &data, portMAX_DELAY) == pdPASS) { // 处理接收到的数据 } } }

七、关键注意事项

  1. 数据拷贝:队列存储的是数据的拷贝,不是指针。传递大结构体时,建议使用指针传递(传递结构体地址),但需确保指针指向的数据在队列处理期间有效。

  2. 队列长度:合理设置队列长度,过小会导致频繁阻塞,过大则浪费内存。

  3. 阻塞时间:根据应用需求设置合适的阻塞时间,避免任务长时间阻塞。

  4. 中断安全:在中断中操作队列,必须使用xQueueSendFromISRxQueueReceiveFromISR

  5. 队列空/满检测:使用uxQueueMessagesWaiting()uxQueueSpacesAvailable()查询队列状态,避免数据丢失。

八、队列工作流程图

任务A(发送) 队列 任务B(接收) | | | | 入队操作 | | |----------------->| | | | | | | | | | 入队成功 | | |--------------->| | | | | | | | | | | | 出队操作 | | |<---------------| | | | | | |

入队和出队操作确保了任务间的解耦,使系统设计更加清晰、灵活,是FreeRTOS中实现任务间通信的关键机制。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/4 19:03:08

FreeRTOS二值信号量详解

一、基本概念**二值信号量(Binary Semaphore)**是FreeRTOS提供的一种简单而强大的同步工具&#xff0c;它只有两个可能值&#xff1a;0或1。形象理解&#xff1a;二值信号量就像公共卫生间的占用指示灯&#xff1a;绿灯(值为1)&#xff1a;资源可用&#xff0c;任务可以获取红灯…

作者头像 李华
网站建设 2026/9/2 23:26:13

还在用“片段式”降重?百考通AI“全链路降重” vs 普通优化,三大核心差异决定你的论文能否一次过关

面对毕业论文查重&#xff0c;很多同学选择“哪里红改哪里”——复制一段高重复文字&#xff0c;粘贴到某个工具里替换同义词&#xff0c;再手动贴回文档。这种局部、割裂、反应式的“片段式降重”&#xff0c;看似省事&#xff0c;实则埋下多重隐患&#xff1a;逻辑断裂、风格…

作者头像 李华
网站建设 2026/9/5 22:05:41

低成本物联网平台

物联网平台 - Thinglinks-iot ## &#x1f31f; 项目简介 一个功能完备、高可扩展的物联网平台&#xff0c;提供完整的设备接入、管理和数据处理解决方案。支持多种网络协议&#xff0c;具备强大的消息解析和实时告警能力&#xff0c;帮助企业快速构建物联网应用。 该项目现已…

作者头像 李华
网站建设 2026/9/3 6:34:03

设计Logo与Slogan:强化品牌形象便于传播记忆

VibeThinker-1.5B-APP&#xff1a;轻量模型如何以“精准推理”重构AI价值认知 在算力军备竞赛愈演愈烈的今天&#xff0c;一个仅1.5B参数的模型竟能在数学与编程任务中击败数十倍规模的大模型——这听起来像是一场对“越大越好”信条的公然挑战。但VibeThinker-1.5B-APP正是这样…

作者头像 李华
网站建设 2026/9/2 1:21:37

(Dify凭证加密存储技术大揭秘):掌握AES+HSM双重保护的核心原理

第一章&#xff1a;Dify凭证管理安全概述在现代AI应用开发中&#xff0c;凭证&#xff08;Credentials&#xff09;作为连接外部服务、数据库和模型API的关键凭据&#xff0c;其安全管理直接影响系统的整体安全性。Dify作为一个低代码AI应用开发平台&#xff0c;提供了统一的凭…

作者头像 李华
网站建设 2026/9/3 0:44:35

【AI内容生成进阶之道】:Dify描述优化必须掌握的8种高级策略

第一章&#xff1a;Dify描述生成优化的核心价值Dify作为新一代低代码AI应用开发平台&#xff0c;其描述生成优化能力在提升开发效率与模型可维护性方面展现出显著优势。通过自然语言驱动的自动化描述生成机制&#xff0c;开发者能够快速定义、调试并迭代AI工作流&#xff0c;大…

作者头像 李华