news 2026/2/11 0:25:42

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/2/3 14:44:22

编写API文档:即使未开放接口也为未来预留扩展空间

编写API文档&#xff1a;即使未开放接口也为未来预留扩展空间 在AI模型部署越来越追求“即插即用”的今天&#xff0c;一个有趣的现象正在浮现&#xff1a;许多高性能小模型虽然功能强大&#xff0c;却以非服务化的方式交付——没有API&#xff0c;只有镜像和脚本。VibeThinker…

作者头像 李华
网站建设 2026/2/8 1:29:46

百考通源码图纸库,你的项目开发加速器!

在软件工程、嵌入式开发、自动化控制乃至人工智能等领域&#xff0c;一个成功的项目往往始于一个扎实的起点。然而&#xff0c;对于广大的开发者、学生和工程师而言&#xff0c;“从零开始”构建一个复杂系统&#xff0c;不仅意味着漫长的学习曲线和巨大的工作量&#xff0c;更…

作者头像 李华
网站建设 2026/2/10 12:54:11

降重后参考文献格式乱、引用标红?百考通AI“全链路降重”服务,3分钟同步优化正文+参考文献,彻底清零格式与重复风险

你是否遇到过这种“降重后遗症”&#xff1f; ——正文重复率降下来了&#xff0c;但参考文献列表被查重系统标红&#xff1b; ——引用的句子改写后&#xff0c;文中标注和文末参考文献对不上&#xff1b; ——手动调整GB/T 7714格式时&#xff0c;卷号、页码、DOI漏填&#x…

作者头像 李华
网站建设 2026/2/2 23:29:05

未来版本路线图:VibeThinker-2.0可能带来的重大升级

VibeThinker-2.0 的演进之路&#xff1a;从“小而精”到“专而强” 在当前大模型军备竞赛愈演愈烈的背景下&#xff0c;千亿参数、万亿token训练已成常态。然而&#xff0c;越来越多的实践表明&#xff1a;并非所有智能任务都需要“巨无霸”模型来解决。尤其是在数学推导、算法…

作者头像 李华
网站建设 2026/2/10 5:31:46

典型案例库建设:积累高质量输入输出对供研究参考

典型案例库建设&#xff1a;积累高质量输入输出对供研究参考 在AI模型参数规模不断膨胀的今天&#xff0c;一个反直觉的现象正在引起越来越多研究者的注意&#xff1a;某些仅含十几亿参数的小模型&#xff0c;在特定高难度任务上的表现&#xff0c;竟能超越数百倍参数的大模型。…

作者头像 李华
网站建设 2026/1/30 8:57:34

基于FPGA的时序逻辑电路设计完整指南

掌握硬件节奏&#xff1a;FPGA时序逻辑设计的实战精要你有没有遇到过这样的情况&#xff1f;代码仿真一切正常&#xff0c;下载到FPGA后系统却莫名其妙“抽风”——状态跳变错乱、输出信号毛刺频发&#xff0c;甚至偶尔死机。排查数日&#xff0c;最终发现罪魁祸首竟是一个未处…

作者头像 李华