RTOS中Queue的工作原理

电子说

1.2w人已加入

描述

Queue概述

Queue即消息队列是通过RTOS内核提供的一种服务。它是一种线程间同步数据的安全方法。

队列(Queue)是与栈对应的概念;栈是FILO结构,而队列是FIFO结构。FreeRTOS原生的队列支持从高位添加新数据,但CMSIS简化删去了这一功能,即只能从队列底部推入数据并且对数据类型有限制,这一简化一般不影响使用。

  • RTOS中Queue的工作原理:

FreeRTOS

  • API Description:
    1.使用**osMessageQueueNew() 创建队列
    该函数会涉及
    osMessageQueueAttr_t **配置结构体;主要用于配置Control Block和名称;一旦使用该结构体将导致只能使用静态方式创建队列;一般传入NULL即可
osMessageQueueId_t osMessageQueueNew (uint32_t msg_count, uint32_t msg_size, const osMessageQueueAttr_t *attr);/*
创建新的Queue队列
@retval    -队列地址(Queue Identifier)
@param     msg_count -队列可容纳的消息(变量)数量
@param     msg_size  -消息(变量)占用的空间[通常用sizeof()填入]
@param     *attr     -配置结构体对象,一般为NULL。 当传入NULL时,仅使用xQueueCreate()动态创建对应大小、数量的队列;
*/

2.使用**osMessageQueueDelete() **删除队列

该函数能释放队列占用的空间并清除其中内容和任务规划。队列删除后可通过**osMessageQueueNew() **重新创建。

osStatus_t osMessageQueueDelete (osMessageQueueId_t mq_id);/*删除队列
@retval     -osOK: the message queue object has been deleted.
            -osErrorParameter: parameter mq_id is NULL or invalid.
            -osErrorResource: the message queue is in an invalid state.
            -osErrorISR: osMessageQueueDelete cannot be called from interrupt service routines.
*/

3.获取队列配置信息

uint32_t osMessageQueueGetCapacity (osMessageQueueId_t  mq_id );
/*获取队列可容纳的消息(变量)数量; []
*/
uint32_t osMessageQueueGetMsgSize (osMessageQueueId_t  mq_id );
/* 获取消息(变量)占用的空间 [单位byte]
*/
uint32_t osMessageQueueGetSpace (osMessageQueueId_t  mq_id );/*
  查询队列中空位(未填入变量)的数量
*/
uint32_t osMessageQueueGetCount (osMessageQueueId_t  mq_id );/*
  查询队列中已写入的消息(变量)数量
*/

4.※ 读取(取出)/写入队列

关于阻塞超时时间:

①读取(取出)阻塞超时:当任务读一个消息队列时,可通过osMessageQueueGet()设置阻塞超时时间。在这段时间中,如果队列为空(无变量),该任务将保持BLOCK状态以等待队列数据有效。在此期间当任务检测到其等待的队列中写入了数据时,将自动由BLOCK态转移为READY态。当等待的时间超过了指定的阻塞时间,即使队列中尚无数据,任务也会自动从阻塞态转移为READY态。此时程序会返回osErrorTimeout错误。若没有设置阻塞超时且参数正确,返回osErrorResource错误**。**

由于队列可以被多个任务读取,所以对单个队列而言,也可能有多个任务处于BLOCK
状态以等待队列数据有效。这种情况下,一旦队列数据有效,所有等待任务中优先级最高的任务被执行。而如果所有等待任务的优先级相同,那么被解除阻塞的任务将是等待最久的任务。

②写入阻塞超时: 同读队列一样,任务也可以在写队列时指定一个阻塞超时时间。这个时间是当被写队列已满时,任务进入BLOCK态以等待队列空间有效的最长时间。当等待的时间超过了指定的阻塞时间,即使队列中尚无数据,任务也会自动从BLOCK态转移为READY态。此时程序会返回osErrorTimeout错误。若没有设置阻塞超时且参数正确,返回osErrorResource错误。由于队列可以被多个任务写入,所以对单个队列而言,也可能有多个任务处于BLOCK
状态以等待队列空间有效。这种情况下,一旦队列空间有效,所有等待任务中优先级最高的任务被执行。而如果所有等待任务的优先级相同,那么被解除阻塞的任务将是等待最久的任务。

阻塞超时时间(timeout 变量)有三种配置:

==  0U     //不设置阻塞超时时间,若出现上述队列异常函数将直接报错返回
 ==  osWaitForever  //任务将一直阻塞直到空队列被写入/满队列被取出数据
 ==  Ticks   //设置具体等待时间,单位为RTOS心跳数(Ticks)

①用 osMessageQueueGet() 取出数据**【※可在中断中使用】**

osStatus_t osMessageQueueGet ( osMessageQueueId_t  mq_id,
void *  msg_ptr,       //储存读取结果的变量地址
uint8_t *  msg_prio,  // ==NULL
uint32_t  timeout    //阻塞超时时间
);

①用 osMessageQueuePut() 写入**【※可在中断中使用】**

osStatus_t osMessageQueuePut ( osMessageQueueId_t  mq_id,
const void *  msg_ptr,     //储存写入内容的变量地址
uint8_t  msg_prio,        //==0U
uint32_t  timeout         //阻塞超时时间
);

读出/写入的返回状态值:

-osOK: 取出/写入成功
-osErrorTimeout: the message could not be retrieved from/put into the queue in the given time (timed-wait semantics).
-osErrorResource: nothing to get from the queue or no space to push.
-osErrorParameter: parameter mq_id is NULL or invalid, non-zero timeout specified in an ISR.

5.清空队列

osStatus_t osMessageQueueReset (osMessageQueueId_t mq_id);/*
@retval:      -osOK: the message queue has been rest.
              -osErrorParameter: parameter mq_id is NULL or invalid.
              -osErrorResource: the message queue is in an invalid state.
              -osErrorISR: osMessageQueueReset cannot be called from interrupt service routines.
*/
打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分