freeRTOS中文实用教程2--队列

时间:2021-05-13 14:32:49

1.前言

freeRTOS中所有任务的通信和同步机制都是基于队列来实现。

2.队列的特点

freeRTOS中文实用教程2--队列

图 队列的读写操作

  • 队列的数据存储

(1)队列可以保存有限个具有确定长度的数据单元,队列可以保存的最大单元数目称为队列的深度;

(2)队列创建时需要设定队列深度和每个单元的大小;

(3)队列先进先出

  • 多任务存取

队列是内核中具有独立权限的对象,不属于任何任务,可以有多个任务进行读写

  • 读队列阻塞

(1)任务读取队列数据时可以指定一个阻塞超时时间;

(2)未超过阻塞超时时间,队列为空,任务将保持阻塞状态;

(3)队列中写入数据,任务将由阻塞态转为就绪态;或者阻塞时间超过了阻塞超时时间,任务也将由阻塞态转为就绪态;

(4)可能会有多个任务处于阻塞态等待读取队列中的数据;

(5)队列数据有效,优先级最高的任务会解除阻塞,相同优先级则等待时间最长的任务会解除阻塞

  • 写队列阻塞

(1)任务写入队列数据时可以指定一个阻塞超时时间;

(2)未超过阻塞超时时间,队列满,任务将保持阻塞状态;

(3)队列有空闲,任务将由阻塞态转为就绪态;或者阻塞时间超过了阻塞超时时间,任务也将由阻塞态转为就绪态;

(4)可能会有多个任务处于阻塞态等待向队列中的写入数据;

(5)队列有空闲,优先级最高的任务会解除阻塞,相同优先级则等待时间最长的任务会解除阻塞

3. 使用队列传递复合数据类型

freeRTOS中文实用教程2--队列

图 结构体用于队列传递举例

一般是通过传递复合数据类型的指针来实现

4.使用队列传递指针

  • 如果队列存储的数据单元尺寸较大,那最好是利用队列来传递数据的指针
  • 利用队列传递指针时,一定要十分小心地做到以下两点

(1)指针指向的内存空间的所有权必须明确

不会有任意两个任务同时修改共享内存中的数据 .原则上,共享内存在其指针发送到队列之前,其内容只允许被发送任务访问;

共享内存指针从队列中被读出之后,其内容亦只允许被接收任务访问

(2)指针指向的内存空间必须有效

如果指针指向的内存空间是动态分配的,只应该有一个任务负责对其进行内存释放。当这段内存空间被释放之后,就不应该有任何一个任务再访问这段空间

注:切忌用指针访问任务栈上分配的空间。因为当栈帧发生改变后,栈上的数据将不再有效

5.队列操作API

API原型 函数说明 参数说明 返回值
xQueueCreate( uxQueueLength, uxItemSize ) 用于创建一个队列,并返回一个 xQueueHandle 句柄以便于对其创建的队列进行引用 。当创建队列时, FreeRTOS 从堆空间中分配内存空间。分配的空间用于存储队列数据结构本身以及队列中包含的数据单元。如果内存堆中没有足够的空间来创建队列,xQueueCreate()将返回 NULL
  • uxQueueLength

队列能够存储的最大单元数目,即队列深度。

  • uxItemSize

队列中数据单元的长度,以字节为单位

NULL 表示没有足够的堆空间分配给队列而导致创建失败。
非 NULL 值表示队列创建成功。此返回值应当保存下来,以作为
操作此队列的句柄
xQueueSendToBack( xQueue, pvItemToQueue, xTicksToWait ) xQueueSendToBack()用于将数据发送到队列尾
  • xQueue

目标队列的句柄

  • pvItemToQueue

发送数据的指针

  • xTicksToWait

阻塞超时时间。如果在发送时队列已满,这个时间即是任务处于阻塞态等待队列空间有效的最长等待时间

 
xQueueSendToFront( xQueue, pvItemToQueue, xTicksToWait ) 用于将数据发送到队列首  

pdPASS
返回 pdPASS 只会有一种情况,那就是数据被成功发送到队列

errQUEUE_FULL
如 果 由 于 队 列 已 满 而 无 法 将 数 据 写 入 , 则 将 返 回
errQUEUE_FULL

xQueueSendToFrontFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) 用于在中断服务中实现相同的功能    
xQueueSendToBackFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) 用于在中断服务中实现相同的功能     

xQueueReceive

xQueuePeek

用于从队列中接收(读取)数据单元。接收到的单元同时会从队列中删除

也是从从队列中接收数据单元,不同的是并不从队列中删出接收到的单元

注:切记不要在中断服务例程中调用 xQueueRceive()和 xQueuePeek()

   
xQueueReceiveFromISR      
 uxQueueMessagesWaiting

用于查询队列中当前有效数据单元个数

切记不要在中断服务例程中调用 uxQueueMessagesWaiting()

   
 uxQueueMessagesWaitingFromISR      

6. 执行流程举例

send1和sender2负责写队列,receiver负责读队列:

freeRTOS中文实用教程2--队列