队列集相关的 API 函数详解

FreeRTOS 中的 队列集(Queue Set) 是一种高级同步机制,允许任务同时监听多个队列或信号量的事件,并在任意一个成员有数据到达时唤醒任务。它适用于需要多路复用事件的场景,例如任务需要同时等待消息队列、信号量或其他队列集成员的事件。以下是队列集相关的 API 函数详解及使用指南。


队列集的核心特性

  1. 多事件监听:任务可以阻塞等待队列集中的多个队列或信号量,任一成员有事件即可唤醒任务(这个任务指的是监听任务它本身,不是其他的任务)。
  2. 统一管理:简化多事件监听逻辑,避免任务频繁轮询多个队列。
  3. 成员类型:支持队列(QueueHandle_t)和信号量(SemaphoreHandle_t)。
  4. 限制
    • 每个队列或信号量只能加入一个队列集。
    • 队列集本身不存储数据,仅标记成员是否有事件发生。

1. 创建队列集

函数原型
QueueSetHandle_t xQueueCreateSet(const UBaseType_t uxEventQueueLength);
  • 功能:动态分配内存并初始化一个队列集。
  • 参数
    • uxEventQueueLength:队列集能同时记录的最大事件数(通常等于队列集中所有成员的队列长度总和)。
  • 返回值
    • 成功:返回队列集句柄(QueueSetHandle_t)。
    • 失败:返回 NULL(内存不足或参数无效)。
  • 示例
    QueueSetHandle_t xQueueSet = xQueueCreateSet(5); // 最多记录5个事件
    

2. 向队列集中添加成员

函数原型
BaseType_t xQueueAddToSet(
    QueueSetMemberHandle_t xQueueOrSemaphore, // 队列或信号量句柄
    QueueSetHandle_t xQueueSet               // 队列集句柄
);
  • 功能:将队列或信号量添加到队列集中。
  • 参数
    • xQueueOrSemaphore:要添加的队列或信号量句柄。
    • xQueueSet:目标队列集句柄。
  • 返回值
    • pdPASS:添加成功。
    • pdFAIL:添加失败(成员已属于其他队列集,或队列集已满)。
  • 示例
    QueueHandle_t xQueue1 = xQueueCreate(5, sizeof(int));
    QueueHandle_t xQueue2 = xQueueCreate(5, sizeof(int));
    QueueSetHandle_t xQueueSet = xQueueCreateSet(10);
    
    // 将队列加入队列集
    xQueueAddToSet(xQueue1, xQueueSet);
    xQueueAddToSet(xQueue2, xQueueSet);
    

3. 从队列集中移除成员

函数原型
BaseType_t xQueueRemoveFromSet(
    QueueSetMemberHandle_t xQueueOrSemaphore, // 队列或信号量句柄
    QueueSetHandle_t xQueueSet               // 队列集句柄
);
  • 功能:从队列集中移除队列或信号量。
  • 参数:同上。
  • 返回值
    • pdPASS:移除成功。
    • pdFAIL:移除失败(成员不属于该队列集)。

4. 等待队列集中的事件

函数原型
QueueSetMemberHandle_t xQueueSelectFromSet(
    QueueSetHandle_t xQueueSet,
    TickType_t xTicksToWait // 阻塞时间
);
  • 功能:阻塞任务,直到队列集中任意成员有事件(数据到达或信号量释放)。
  • 参数
    • xQueueSet:队列集句柄。
    • xTicksToWait:阻塞时间(单位:系统节拍),portMAX_DELAY 表示无限等待。
  • 返回值
    • NULL:触发事件的成员句柄(QueueHandle_tSemaphoreHandle_t)。
    • NULL:超时或队列集无效。
  • 注意:返回的句柄需通过 xQueueReceive()xSemaphoreTake() 处理数据。
中断安全版本
QueueSetMemberHandle_t xQueueSelectFromSetFromISR(
    QueueSetHandle_t xQueueSet
);
  • 用于中断服务程序(ISR)中非阻塞查询队列集事件。

5. 使用流程示例

场景:任务需同时监听两个队列和一个信号量。
QueueHandle_t xQueueA, xQueueB;
SemaphoreHandle_t xSemaphore;
QueueSetHandle_t xQueueSet;

void vTaskEventMonitor(void *pvParameters) {
    xQueueSet = xQueueCreateSet(10); // 总事件容量为10

    // 创建队列和信号量,并加入队列集
    xQueueA = xQueueCreate(5, sizeof(int));
    xQueueB = xQueueCreate(5, sizeof(int));
    xSemaphore = xSemaphoreCreateBinary();
    xQueueAddToSet(xQueueA, xQueueSet);
    xQueueAddToSet(xQueueB, xQueueSet);
    xQueueAddToSet(xSemaphore, xQueueSet);

    while (1) {
        // 等待队列集中任意成员有事件
        QueueSetMemberHandle_t xActivatedMember = xQueueSelectFromSet(xQueueSet, portMAX_DELAY);
        
        if (xActivatedMember == xQueueA) {
            int data;
            xQueueReceive(xQueueA, &data, 0); // 读取队列A数据
            // 处理队列A事件...
        } else if (xActivatedMember == xQueueB) {
            int data;
            xQueueReceive(xQueueB, &data, 0); // 读取队列B数据
            // 处理队列B事件...
        } else if (xActivatedMember == xSemaphore) {
            xSemaphoreTake(xSemaphore, 0); // 获取信号量
            // 处理信号量事件...
        }
    }
}

注意事项

  1. 事件容量限制
    创建队列集时指定的 uxEventQueueLength 必须 ≥ 所有成员队列的长度之和。例如:

    • 若队列1长度为3,队列2长度为2,信号量最大计数值为1,则 uxEventQueueLength 至少为 3+2+1=6。
  2. 数据读取时机
    xQueueSelectFromSet() 返回触发事件的成员句柄后,必须立即调用 xQueueReceive()xSemaphoreTake() 处理数据,否则该事件会被队列集标记为已处理,可能导致数据丢失。

  3. 性能影响
    队列集的实现基于内部事件队列,频繁操作可能增加系统开销。在实时性要求高的场景中,需评估是否适合使用。

  4. 中断中使用
    在 ISR 中只能使用 xQueueSelectFromSetFromISR(),且需确保不会阻塞。


适用场景

  • 多事件监听:如网络任务需同时等待命令队列和数据队列。
  • 统一事件分发:多个任务的事件通过队列集集中管理。
  • 资源受限系统:避免为每个队列单独创建任务。

总结

队列集是 FreeRTOS 中管理多事件的高效工具,通过集中监听多个队列或信号量,简化了复杂事件处理逻辑。合理使用队列集可以提升代码可维护性,但需注意事件容量和性能开销。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

九层指针

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值