14.1.2 队列的函数解析

更新于 2026年10月10日 版权声明
14.1.2 队列的函数解析

1.队列结构体

队列采用队列结构体来进行管理,包括消息的存储位置、头指针pcHead、尾指针pcTail、消息大小uxItemSize,以及队列长度uxLength等。每个队列都与消息空间在同一段连续的内存空间中,在创建成功的时候,这些内存就被占用了,只有删除队列,这段内存才会被释放掉。每个消息空间可以存放不大于消息大小uxItemSize的任意类型的数据,所有队列中的消息空间总数即队列的长度,这个长度可在队列创建时指定。

FreeRTOS队列的控制块为Queue_t,该结构体在文件“queue.c”中定义,原型如下。

图示

图示

2.队列创建

在应用队列之前,要先创建一个队列。创建队列有动态创建和静态创建两种方法,其对应的函数为xQueueCreate()和xQueueCreateStatic()。这两个函数本质上都是宏,真正完成队列创建的函数是xQueueGenericCreate()和xQueueGenericCreateStatic(),这两个函数在文件“queue.c”中定义。下面以xQueueGenericCreate()函数为例进行分析。

函数xQueueGenericCreate()在文件“queue.c”中定义,函数原型如下。

图示

图示

函数的输入参数如下。

①uxQueueLength:要创建的队列长度。

②uxItemSize:单个队列项的大小,单位为字节。

③ucQueueType:类型,可以为以下值。

•queueQUEUE_TYPE_BASE:表示队列。

•queueQUEUE_TYPE_SET:表示队列集合。

•queueQUEUE_TYPE_MUTEX:表示互斥信号量。

•queueQUEUE_TYPE_COUNTING_SEMAPHORE:表示计数信号量。

•queueQUEUE_TYPE_BINARY_SEMAPHORE:表示二值信号量。

•queueQUEUE_TYPE_RECURSIVE_MUTEX:表示递归互斥信号量。

函数的返回值如下。

pxNewQueue:消息队列控制块,一个结构体指针(QueueHandle_t句柄,实际是void*),即队列在内存中的地址。

图示

函数xQueueGenericCreate()最主要的作用就是给队列分配内存,当内存分配成功以后,调用函数prvInitialiseNewQueue()来初始化队列。

队列初始化函数prvInitialiseNewQueue()在文件“queue.c”中定义,函数原型如下。

图示

队列初始化完成后,还要调用队列复位函数xQueueGenericReset()来完成最终的初始化工作,该函数会调用vListInitialise()函数构建列表结构。函数原型如下。

图示

图示

以创建一个有4个队列项、每个队列项长度为32个字节的队列TestQueue为例,创建成功的初始队列结构如图14.4所示。

图示

图14.4 初始队列结构

3.队列发送消息

创建好队列以后,就可以向队列发送消息了,这一过程被称为入队。FreeRTOS提供了8个向队列发送消息的API函数(队列入队函数),分为任务级队列的发送函数和中断级队列的发送函数,相关函数请读者参见第12章的表12.4。(https://www.daowen.com)

任务级队列的发送函数有前向入队、后向入队、覆写入队等函数,可以适应不同的应用需求,它们均是使用xQueueGenericSend()函数来实现的。

中断级队列的发送函数有前向入队、后向入队、覆写入队等函数,可以适应不同的应用需求,它们均是使用xQueueGenericSendFromISR()函数来实现的。

下面以任务级队列的发送函数xQueueSend()和中断级队列的发送函数xQueueSendFromISR()为例进行分析,均是发到队列尾部,其他函数请读者自行分析。

(1)任务级队列发送函数xQueueSend()。

任务级队列发送函数xQueueSend()的原型如下。

图示

图示

该函数返回pdPASS表示向队列发送消息成功,否则表示不成功。

xQueueSend()函数实际是通过xQueueGenericSend()函数完成发送的,该函数的原型如下。

图示

(2)中断级队列发送函数xQueueSendFromISR()。

中断级队列发送函数xQueueSendFromISR()的原型如下。

图示

①输入参数如下。

•xQueue:队列句柄,表明要向哪个队列发送数据。

•pvItemToQueue:指向要发送的消息,发送的过程中会将这个消息复制到队列中。

•pxHigherPriorityTaskWoken:标记退出此函数后是否进行任务切换,为pdTRUE表示切换。

②返回参数。该函数无返回参数。

该函数宏定义如下。

图示

4.队列接收消息

队列接收消息即从消息队列中接收一组数据,这一过程被称为出队。FreeRTOS有4个队列接收函数(队列出队函数),参见第12章的表12.4,分为任务级队列接收函数和中断级队列接收函数。

任务级队列接收函数有读取完后删除函数xQueueReceive(),读取完后不删除函数xQueuePeek()两种。

中断级队列接收函数有读取完后删除函数xQueueReceiveFromISR(),读取完后不删除函数xQueuePeekFromISR()两种。

下面主要分析函数xQueueReceive()和xQueueReceiveFromISR(),其他函数请读者自行分析。

(1)任务级队列接收函数。

xQueueReceive()函数用于从队列中读取一条(请求)消息,读取成功以后就会将队列中的这条数据删除,此函数的本质是一个宏,真正执行的函数是xQueueGenericReceive()。此函数在读取消息的时候是采用复制方式的,所以用户需要提供一个数组或缓冲区来保存读取到的数据,所读取的数据长度是创建队列的时候所设定的每个队列项长度,函数原型如下。

图示

图示

该函数返回pdTRUE表示从队列中读取数据成功,返回pdFALSE表示从队列中读取数据失败。

(2)中断级队列接收函数。

xQueueReceiveFromISR()函数原型如下。

图示

综上所述,任务获取队列中的消息采用xQueueReceive()函数,在中断服程序中获取队列中的消息采用xQueueReceiveFromISR()函数。这两个函数不能混合使用,注意应用场合。

↑上一章 ↓下一章
关注公众号获取验证码
复制内容需要验证码(7.99元/天)