uC/OS-III 队列相关接口

在 uC/OS(Micro-Controller Operating System)中,队列(Queue)是任务间通信的核心机制之一,用于实现数据缓冲和异步消息传递。uC/OS 的队列设计兼顾了实时性和内存效率,以下从代码结构、核心接口和实现特点进行分析:

一、uC/OS 队列的核心数据结构

uC/OS 中队列的控制块(OS_Q)定义了队列的全部状态信息,关键成员如下(以 uC/OS-III 为例):

复制代码
typedef struct os_q {
    CPU_CHAR          Name[OS_OBJ_NAME_LEN];  // 队列名称(调试用)
    OS_MSG_Q          MsgQ;                   // 消息队列容器
    OS_OBJ_QTY        MaxMsg;                 // 最大消息数
    OS_MSG_SIZE       MaxMsgSize;             // 单条消息最大字节数
    OS_OBJ_TYPE       Type;                   // 对象类型(标识为队列)
    // 等待队列(任务阻塞时的等待链表)
    OS_PEND_LIST      PendList;
    // 其他状态变量(如是否使用动态内存、计数器等)
    OS_FLAGS          Flags;
    CPU_INT32U        MsgQty;                 // 当前消息数量
    // ...
} OS_Q;
  • OS_MSG_Q:实际存储消息的缓冲区,通常为环形队列结构
  • PendList:记录等待该队列的任务(用于阻塞机制)

二、核心接口及实现分析

uC/OS 的队列操作接口封装在os_q.c文件中,核心功能如下:

1. 队列创建(OSQCreate()

功能 :初始化队列控制块,分配消息缓冲区。
关键代码逻辑

复制代码
OS_Q *OSQCreate(OS_Q        *p_q,
                CPU_CHAR    *p_name,
                OS_OBJ_QTY   max_msg,
                OS_MSG_SIZE  max_msg_size,
                OS_ERR      *p_err)
{
    // 参数校验(空指针、长度合法性)
    if (p_q == (OS_Q *)0) {
        *p_err = OS_ERR_OBJ_PTR_NULL;
        return ((OS_Q *)0);
    }
    // 初始化队列控制块成员
    p_q->MaxMsg      = max_msg;
    p_q->MaxMsgSize  = max_msg_size;
    p_q->MsgQty      = 0u;
    // 初始化等待链表(无任务等待)
    OS_PendListInit(&p_q->PendList);
    // 初始化消息缓冲区(环形队列)
    OS_MsgQInit(&p_q->MsgQ, max_msg, max_msg_size, p_err);
    // ...
    return (p_q);
}

特点

  • 支持静态创建(用户提供OS_Q结构体)和动态创建(内部调用malloc
  • 需指定最大消息数和单条消息长度,避免内存溢出
2. 发送消息(OSQPost()

功能 :向队列尾部发送消息,支持阻塞 / 非阻塞模式。
核心逻辑

复制代码
OS_OBJ_QTY OSQPost(OS_Q        *p_q,
                   void        *p_msg,
                   OS_MSG_SIZE  msg_size,
                   OS_FLAGS     opt,
                   OS_ERR      *p_err)
{
    CPU_SR_ALLOC();  // 用于临界区保护
    
    CPU_CRITICAL_ENTER();  // 关中断(确保操作原子性)
    // 检查队列是否已满
    if (p_q->MsgQty >= p_q->MaxMsg) {
        CPU_CRITICAL_EXIT();
        *p_err = OS_ERR_Q_FULL;
        return (0u);
    }
    // 复制消息到队列缓冲区(支持指针传递或数据拷贝)
    OS_MsgQPut(&p_q->MsgQ, p_msg, msg_size, opt, p_err);
    p_q->MsgQty++;
    // 唤醒等待该队列的任务(如有)
    if (OS_PendListIsEmpty(&p_q->PendList) == DEF_NO) {
        OS_PendListPost(&p_q->PendList, p_msg, msg_size, opt, p_err);
    }
    CPU_CRITICAL_EXIT();  // 开中断
    // ...
    return (1u);
}

关键特性

  • 支持OS_OPT_POST_FIFO(先进先出)和OS_OPT_POST_LIFO(后进先出)模式
  • 消息可通过指针传递(零拷贝,适合大数据)或拷贝(内存独立,安全但耗时)
3. 接收消息(OSQPend()

功能 :从队列头部获取消息,队列为空时可阻塞等待。
核心逻辑

复制代码
void *OSQPend(OS_Q         *p_q,
              OS_TICK       timeout,
              OS_OPT        opt,
              OS_MSG_SIZE  *p_msg_size,
              CPU_TS       *p_ts,
              OS_ERR       *p_err)
{
    void        *p_msg;
    CPU_SR_ALLOC();
    
    CPU_CRITICAL_ENTER();
    // 队列有消息:直接取消息
    if (p_q->MsgQty > 0u) {
        p_msg = OS_MsgQGet(&p_q->MsgQ, p_msg_size, p_err);
        p_q->MsgQty--;
        CPU_CRITICAL_EXIT();
        return (p_msg);
    }
    // 队列空:任务进入阻塞状态
    else {
        // 将当前任务加入等待链表
        OS_PendListWait(&p_q->PendList, 
                       (OS_PEND_OBJ *)p_q, 
                       OS_TASK_PEND_ON_Q,
                       timeout,
                       opt,
                       p_err);
        CPU_CRITICAL_EXIT();
        // 任务调度(切换到其他就绪任务)
        OSSched();
        // 被唤醒后获取消息
        p_msg = OSTCBCur->MsgPtr;
        *p_msg_size = OSTCBCur->MsgSize;
        // ...
        return (p_msg);
    }
}

阻塞机制

  • 任务调用OSQPend()时若队列空,会被加入PendList并进入阻塞态
  • 超时时间timeout为 0 表示非阻塞(立即返回错误),OS_OPT_PEND_BLOCKING表示无限等待
  • 当消息到来时,OSQPost()会唤醒等待队列中优先级最高的任务
4. 其他关键接口
  • OSQFlush():清空队列所有消息(重置缓冲区指针)
  • OSQDel():删除队列(需确保无任务等待)
  • OSQQuery():查询队列状态(当前消息数、最大容量等)
相关推荐
沐欣工作室_lvyiyi13 小时前
一种简易高灵活性机械四足机器人的设计与实现(论文+源码)
单片机·机器人·毕业设计·四足机器人
d111111111d14 小时前
STM32-外设学习-读写备份寄存器(代码)--学习笔记
笔记·stm32·单片机·嵌入式硬件·学习
国科安芯14 小时前
AS32系列MCU芯片TIM模块的捕获和比较
单片机·嵌入式硬件·fpga开发·架构·risc-v
stars-he15 小时前
单片机转换电路学习笔记
笔记·单片机·学习
DIY机器人工房15 小时前
(十二)嵌入式面试题收集:15道
单片机·嵌入式硬件·diy机器人工房
仰望星空的凡人15 小时前
基于RH850-F1x系列的瑞萨MCU选型指南
单片机·嵌入式硬件·rh850·renesas
卡提西亚15 小时前
(10)普中A2 51单片机DS1302实时时钟
单片机·嵌入式硬件·51单片机
@good_good_study15 小时前
STM32 TIM通道捕获配置函数及实验
stm32·单片机
硅农深芯1 天前
是时候跟GitBucket说再见了
git·单片机
未来之窗软件服务1 天前
幽冥大陆(三十八)P50酒店门锁SDK C#仙盟插件——东方仙盟筑基期
开发语言·单片机·c#·东方仙盟·东方仙盟sdk·东方仙盟vos智能浏览器