简介
队列是任务到任务、任务到中断、中断到任务数据交流的一种机制(消息传递)。
特点
- 队列采用先进先出(FIFO)的数据存储缓冲机制,也支持后进先出(LIFO)原则
- 队列才有实际值传递,将数据拷贝到队列中进行传递,采用拷贝数据传递,也可以传递指针,所以在传递较大的数据的时候采用指针传递。
- 队列不属于某个任务,任何任务和中断都可以向队列发送/读取消息。
- 当任务项一个队列发送消息时,可以指定一个阻塞时间。
- 若阻塞时间为0,直接返回不会等待;
- 阻塞时间为0~port_MAX_DELAY,等待设定的阻塞时间,若在该时间内还无法入队,超时后直接返回不再等待;
- 若阻塞时间为port_MAX_DELAY,死等,一直等到可以入队为止,出队阻塞与入队阻塞类似。
当多个任务写入消息给一个满队列时,这些任务都会进入阻塞状态,当队列中有空间时,哪个任务会进入就绪态?
答
1.优先级最高的任务
2.如果任务优先级相同,那等待时间最久的任务会进入就绪态。
创建队列API
动态创建队列
使用时必须在FreeRTOSConfig.h中把configSUPPORT_DYNAMIC_ALLOCATION置为1,这是一个启动动态内存分配的宏。
//动态创建队列
xQueueCreate()
#define xQueueCreate( uxQueueLength, uxItemSize ) xQueueGenericCreate( ( uxQueueLength ), ( uxItemSize ), ( queueQUEUE_TYPE_BASE ) )
//uxQueueLength队列长度
//uxItemSize 队列项大小,以字节为单位
//queueQUEUE_TYPE_BASE 类型 代表队列
//返回值NULL 创建失败,其他值 创建成功,返回队列句柄
#define queueQUEUE_TYPE_BASE ( ( uint8_t ) 0U ) //队列
#define queueQUEUE_TYPE_SET ( ( uint8_t ) 0U ) //队列集
#define queueQUEUE_TYPE_MUTEX ( ( uint8_t ) 1U ) //互斥信号量
#define queueQUEUE_TYPE_COUNTING_SEMAPHORE ( ( uint8_t ) 2U ) //计数型信号量
#define queueQUEUE_TYPE_BINARY_SEMAPHORE ( ( uint8_t ) 3U ) //二值信号量
#define queueQUEUE_TYPE_RECURSIVE_MUTEX ( ( uint8_t ) 4U ) //递归互斥信号量
静态创建队列
//静态创建队列
xQueueCreateStatic()
#define xQueueCreateStatic( uxQueueLength, uxItemSize, pucQueueStorage, pxQueueBuffer ) xQueueGenericCreateStatic( ( uxQueueLength ), ( uxItemSize ), ( pucQueueStorage ), ( pxQueueBuffer ), ( queueQUEUE_TYPE_BASE ) )
写入队列API
函数 | 描述 |
---|---|
xQueueSend() | 往队列的尾部写入消息 |
xQueueSendToBack() | 同xQueueSend() |
xQueueSendToFront | 往队列头部写入消息 |
xQueueOverwrite() | 覆写队列消息,只用于队列长度为1的情况 |
xQueueSendFromISR() | 在中断中往队列的尾部写入消息 |
xQueueSendToBackFromISR() | 同xQueueSendFromISR() |
xQueueSendToFrontFromISR() | 在中断中往队列的头部写入消息 |
xQueueOverwriteFromISR() | 在中断中覆写队列消息,只用于队列长度为1的情况 |
//xQueue队列句柄 pvItemToQueue 发送消息内容 xTicksToWait 超时时间
#define xQueueSend( xQueue, pvItemToQueue, xTicksToWait ) \
xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK )
#define xQueueSendToBack( xQueue, pvItemToQueue, xTicksToWait ) \
xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK )
#define xQueueSendToFront( xQueue, pvItemToQueue, xTicksToWait ) \
xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_FRONT )
#define xQueueOverwrite( xQueue, pvItemToQueue ) \
xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), 0, queueOVERWRITE )
BaseType_t xQueueGenericSend( QueueHandle_t xQueue,
const void * const pvItemToQueue,
TickType_t xTicksToWait,
const BaseType_t xCopyPosition )
{}
//xQueue 待写入队列
//pvItemToQueue 待写入消息
//xTicksToWait 阻塞超时时间
//xCopyPosition 写入位置
//返回值 pdTrue队列写入成功,errQUEUE_FULL 队列写入失败
读取队列API
函数 | 描述 |
---|---|
xQueueReceive() | 从队列头部读取消息,并删除消息 |
xQueuePeek() | 从队列头部读取消息 |
xQueueReceiveFromISR() | 从中断中从队列头部读取消息,并删除消息 |
xQueuePeekFromISR() | 从中断中从队列头部读取消息 |
//xQueue 队列句柄 pvBuffer 缓存 xTicksToWait 超时时间
BaseType_t xQueueReceive( QueueHandle_t xQueue,
void * const pvBuffer,
TickType_t xTicksToWait) PRIVILEGED_FUNCTION;
BaseType_t xQueuePeek( QueueHandle_t xQueue,
void * const pvBuffer,
TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue,
void * const pvBuffer,
BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue,
void * const pvBuffer ) PRIVILEGED_FUNCTION;
//xQueue 读取的队列
//pvBuffer 数据读取缓冲区
//xTicksToWait 阻塞超时时间
//返回值 pdTRUE 读取成功 pdFALSE 读取失败
队列删除API
删除这个消息队列的所有信息都会被系统回收清空,而且不能再次使用这个消息队列。如果消息队列没没有被创建,是无法被删除的
//xQueue 要删除的队列
void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
代码示例
#include "queue.h"
#define QUEUE_LEN 4 //队列长度
#define QUEUE_SIZE 4 //队列中每个消息的大小
QueueHandle_t test_queue = NULL;
void init(){
test_queue = xQueueCreate((UBaseType_t)QUEUE_LEN ,(UBaseType_t)QUEUE_SIZE );
}
void task1(){
uint32_t send_data = 1;
while(1){
xQueueSend(test_queue , &send_data ,0);
}
}
void task2(){
uint32_t r_queue;
BaseType_t xReturn = pdPASS;
while(1){
xReturn = xQueueReceive(test_queue ,&r_queue,portMAX_DELAY);
}
}