8、FreeRTOS - 队列简单的使用介绍

目录

FreeRTOS 队列

FreeRTOS 队列大小

FreeRTOS 队列特点

FreeRTOS 队列的使用流程

FreeRTOS 队列的 API 函数

1、队列创建函数

2、入队函数

3、出队函数

4、队列删除函数


FreeRTOS 队列

队列是任务跟任务之间、任务跟中断之间进行数据交流的一种机制。

队列图示如下:

3b9ac0d4c58143a3b1d092b80f188846.png

任务往队列写入数据,称为入队。从队列中读取数据,称为出队。入队和出队函数的内部都调用了临界段保护函数,禁止了任务的调度,保护了任务在读写时的数据,防止多个任务同时访问队列数据造成冲突。


FreeRTOS 队列大小

队列的存放数据的空间是有限的,空间大小可以在创建队列时指定。队列空间可以看成由多个存放数据的小盒子组成,这些小盒子称为“队列项目”,队列项目的大小单位为字节,小盒子的总数就是队列长度(如下图)。在创建队列时,就要指定队列项目的大小和队列长度。

37da9c79e2314f118edbca640a3067e0.png


FreeRTOS 队列特点

1)队列通常采用数据存取机制是:先入队的数据先出队,也就是“先进先出”(FIFO,First in First out)。当然也可以配置成“后进先出”(LIFO,Last in First out)的方式,慢入队的数据先出队。

2)任务在入队时,是把要发送的数据/地址进行拷贝,拷贝到队列中进行存放。出队时,任务每读取一次数据/地址(即其中一个队列项目的内容被读取),则被读取的队列项目会被清空。

3)队列,是独立于任务外的一个数据结构,不属于任意一个任务,一旦被创建就独立于任务外,任何任务都可以向队列发送消息或读取消息。

4)

入队阻塞:

任务往一个已存满消息的队列发送消息时,任务会阻塞,等队列出现空位后立马退出阻塞,并写入数据。

 

阻塞时间由入队函数的参数 xTicksToWait 决定:

1. 为 0 时,代表直接返回不等到;

2. 为 port_MAX_DELAY 时,代表死等,一直等到可以队列有空闲位置为止;

 

出队阻塞:

任务从一个空的队列读取消息时,任务会阻塞,等队列中出现有可读取的消息后立马退出阻塞,并进行读取。

 

阻塞时间由入队函数的参数 xTicksToWait 决定:

1. 为 0 时,代表直接返回不等到;

2. 为 port_MAX_DELAY 时,代表死等,一直等到可以队列有空闲位置为止;

补充:

Q:当多个任务都往一个“满队列”写入消息时,这些任务都会进入阻塞态,多个任务在等待同一个队列的空间,队列出现空闲空间时,哪个任务优先退出阻塞进入就绪态?

A:优先级最高的任务。如果大家的优先级相同,那等待时间最久的任务会进入就绪态。


FreeRTOS 队列的使用流程

创建队列:创建队列需要调用队列创建的 API 函数,有两种创建方式,分别是动态创建和静态创建。注意,创建队列前先定义一个全局变量,用来接收队列句柄。

        ↓

入队:任务调用入队的 API 函数往队列中填充消息。

        ↓

出队:任务调用出队的 API 函数从队列中读取消息。


FreeRTOS 队列的 API 函数

1、队列创建函数

(1)动态创建

xQueueCreate (  uxQueueLength,   /* 队列长度 */   
                uxItemSize       /* 队列项目大小,单位:字节 */     )

/* 返回值:
   成功返回队列句柄。
   失败返回 NULL。       */

(2)静态创建

QueueHandle_t xQueueCreateStatic(    UBaseType_t      uxQueueLength,         
                                     UBaseType_t      uxItemSize,
                                     uint9_t *        pucQueueStorageBuffer,
                                     StaticQueue_t *  pxQueueBuffer          );

/* 形参:
uxQueueLength:队列长度。     
uxItemSize:队列项目大小,单位为字节。
pucQueueStorageBuffer:是一个指向 uint_t 类型数组的指针。数组大小至少有 uxItiemSize 个字节。当 uxItiemSize 为0时,该参数可以为 NULL。
pxQueueBuffer:是一个指向 StaticQueue_t 类型变量的指针。变量是用来存放队列这个数据结构的。    */


/* 返回值:
成功返回 pdTRUE。
失败返回 errQUEUE_FULL。    */

动态和静态的区别:

队列所需的内存空间由 FreeRTOS 从 FreeRTOS 管理的堆中分配,而静态创建需要用户自行分配内存

2、入队函数

(1)任务级:在任务函数中调用

往队列的尾部写入消息:

BaseType_t xQueueSend( QueueHandle_t   xQueue,          
                       const void *    pvItemToQueue,    
                       TickType_t      xTicksToWait    );

/* 形参:
xQueue:队列句柄。
pvItemToQueue:指针,指向要发送到队列尾部的队列消息。
xTicksToWait:队列满时,等待队列空闲的最大超时时间。如果 xTicksToWait 设置为 0,则队列满时函数立即返回。如果宏 INCLUDE_vTaskSuspend 置 1,且 xTicksToWait 设置为 portMAX_DELAY,则队列满时任务进入阻塞状态,会一直死等,直到队列有空闲位置。    */

/* 返回值:
成功返回 pdTRUE。
失败返回 errQUEUE_FULL。    */

往队列的头部写入消息:

xQueueSendToBack ( xQueue,   
                   pvItemToQueue,   
                   xTicksToWait    );

覆盖队列里的消息:

xQueueOverwrite ( xQueue,   
                  pvItemToQueue );

(2)中断级:在中断服务函数中调用

在中断中往队列的尾部写入消息:xQueueSendFromISR( )

在中断中往队列的头部写入消息:xQueueSendToFrontFromISR( )

在中断中覆写队列消息(只用于队列长度为 1 的情况):xQueueOverwriteFromISR( )

3、出队函数

(1)任务级:在任务函数中调用

从队列头部读取一个队列项目的消息,读取完后移除消息,腾出空闲位置

BaseType_t  xQueueReceive ( QueueHandle_t   xQueue,  
                            void * const    pvBuffer,  
                            TickType_t      xTicksToWait )

/* 形参:
xQueue :待读取的队列。
pvBuffer :信息读取缓冲区。
xTicksToWait :阻塞超时时间。    */

/* 返回值:
读取成功返回 pdTRUE。
读取失败返回 pdFALSE。    */

从队列头部读取一个队列项目的消息,但读取成功后不移除消息

BaseType_t  xQueuePeek ( QueueHandle_t   xQueue,  
                         void * const    pvBuffer,  
                         TickType_t      xTicksToWait )

/* 形参:
xQueue :待读取的队列。
pvBuffer :信息读取缓冲区。
xTicksToWait :阻塞超时时间。    */

/* 返回值:
读取成功返回 pdTRUE。
读取失败返回 pdFALSE。    */

(2)中断级:在中断服务函数中调用

在中断中从队列头部读取消息,并删除消息:xQueueReceiveFromISR( )

在中断中从队列头部读取消息:xQueuePeekFromISR( )

4、队列删除函数

函数:vQueueDelete ( xQueue );

参数:xQueue 是待删除队列的句柄。

队列被删除后,这个队列的所有信息都会被系统回收清空,而且不能再次使用这个消息队列了。vQueueDelete()也可用于删除信号量。如果删除消息队列时,有任务正在等待消息,则不应 该进行删除操作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值