如图1所示,相关数据类型
typedef struct xSTATIC_QUEUE
{
void *pvDummy1[ 3 ];
union
{
void *pvDummy2;
UBaseType_t uxDummy2;
} u;
StaticList_t xDummy3[ 2 ];
UBaseType_t uxDummy4[ 3 ];
uint8_t ucDummy5[ 2 ];
} StaticQueue_t;
typedef StaticQueue_t StaticSemaphore_t;
/* 队列句柄 xQueueCreate()*/
typedef void * QueueHandle_t;
/*队列集 句柄,xQueueCreateSet()*/
typedef void * QueueSetHandle_t;
/* ??? */
typedef void * QueueSetMemberHandle_t;
struct AMessage
{
char ucMessageID;
char ucData[ 20 ];
};
/* 队列标志. */
#define queueSEND_TO_BACK ( ( BaseType_t ) 0 ) //队列后
#define queueSEND_TO_FRONT ( ( BaseType_t ) 1 ) //队列前
#define queueOVERWRITE ( ( BaseType_t ) 2 ) // 复写
/* 6种 队列的类型标志. */
#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 )// 递归互斥锁队列
typedef struct QueueDefinition
{
int8_t *pcHead; /*< 指向队列存储区域的开头. */
int8_t *pcTail; /*< 指向队列存储区域末尾的字节。一旦分配了多于存储队列项所需的字节,就将其用作标记. */
int8_t *pcWriteTo; /*< 指向存储区域中空闲的下一个位置. */
union /* 使用union是编码标准的一个例外,以确保两个互斥结构成员不会同时出现(浪费RAM)。 */
{
int8_t *pcReadFrom; /*< 指向结构用作队列时读取队列项的最后一个位置. */
UBaseType_t uxRecursiveCallCount;/*< 在结构用作互斥锁时,维护递归互斥锁被递归地“占用”的次数的计数 */
} u;
List_t xTasksWaitingToSend; /*< 阻塞的任务列表,这些任务等待发送到此队列。按优先顺序存储. */
List_t xTasksWaitingToReceive; /*< 阻塞等待从该队列读取的任务列表。按优先顺序存储. */
volatile UBaseType_t uxMessagesWaiting;/*< 当前队列中的项数. */
UBaseType_t uxLength; /*< 队列的长度定义为它将持有的项的数量,而不是字节的数量. */
UBaseType_t uxItemSize; /*< 队列将持有的每个项目的大小。 */
volatile int8_t cRxLock; /*< 存储在锁定队列时从队列接收(从队列中删除)的项数。当队列未锁定时,设置为queue解锁. */
volatile int8_t cTxLock; /*< 存储在锁定队列时传输到队列(添加到队列)的项数。当队列未锁定时,设置为queue解锁. */
#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
uint8_t ucStaticallyAllocated;
#endif
#if ( configUSE_QUEUE_SETS == 1 )
struct QueueDefinition *pxQueueSetContainer;
#endif
#if ( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxQueueNumber;
uint8_t ucQueueType;
#endif
} xQUEUE;
2,相关全局量
#define QUEUE_LENGTH 10
#define ITEM_SIZE sizeof( uint32_t )
// xQueueBuffer将保存队列结构。
StaticQueue_t xQueueBuffer;
// ucQueueStorage将保存提交到队列的项目。至少 [(queue length) * ( queue item size)] bytes long.
uint8_t ucQueueStorage[ QUEUE_LENGTH * ITEM_SIZE ];
3,API接口
------------------------------------------------------------
//队列注册表是作为内核感知调试器定位队列、信号量和互斥量的一种方法提供的。调用pcQueueGetName()从队列的句柄查找并返回队列注册表中的队列名称。
QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType );
//用于使用动态内存分配创建队列的函数的通用版本。这由其他函数和宏调用,这些函数和宏创建其他使用队列结构作为基的RTOS对象。
QueueHandle_t xQueueGenericCreateStatic( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, StaticQueue_t *pxStaticQueue, const uint8_t ucQueueType );
#define xQueueCreate( uxQueueLength, uxItemSize ) xQueueGenericCreate( ( uxQueueLength ), ( uxItemSize ), ( queueQUEUE_TYPE_BASE ) )
#define xQueueCreateStatic( uxQueueLength, uxItemSize, pucQueueStorage, pxQueueBuffer ) xQueueGenericCreateStatic( ( uxQueueLength ), ( uxItemSize ), ( pucQueueStorage ), ( pxQueueBuffer ), ( queueQUEUE_TYPE_BASE ) )
------------------------------------------------------------
//删除队列——释放为存储放置在队列上的项目而分配的所有内存。
void vQueueDelete( QueueHandle_t xQueue );
//返回存储在队列中的消息数。
UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue );
//返回队列中可用空闲空间的数量。这等于如果没有删除任何项,则在队列满之前可以发送到队列的项数。
UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue );
------------------------------------------------------------
//最好使用宏xQueueSend()、xQueueSendToFront()和xQueueSendToBack()来代替直接调用这个函数。
//将项目发布到队列上。这个项目是通过复制而不是引用来排队的。这个函数不能从中断服务程序中调用。可以在ISR中使用xQueueSendFromISR()作为替代。
BaseType_t xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, const BaseType_t xCopyPosition );
//将项目发布到队列前面。这个项目是通过复制而不是引用来排队的。这个函数不能从中断服务程序中调用。可以在ISR中使用xQueueSendFromISR()作为替代。
#define xQueueSendToFront( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_FRONT )
//将项目发布到队列的后面。这个项目是通过复制而不是引用来排队的。这个函数不能从中断服务程序中调用。可以在ISR中使用xQueueSendFromISR()作为替代。
#define xQueueSendToBack( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK )
//这是一个调用xQueueGenericSend()的宏。它是为了向后兼容FreeRTOS.org的版本而包含的,这些版本不包括xQueueSendToFront()和xQueueSendToBack()宏。它等价于xQueueSendToBack()。
//将项目发布到队列上。这个项目是通过复制而不是引用来排队的。这个函数不能从中断服务程序中调用。可以在ISR中使用xQueueSendFromISR()作为替代。
#define xQueueSend( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK )
//仅用于长度为1的队列——因此队列要么是空的,要么是满的。
//将项目发布到队列上。如果队列已满,则覆盖队列中持有的值。这个项目是通过复制而不是引用来排队的。
//这个函数不能从中断服务程序中调用。请参阅xQueueOverwriteFromISR(),了解可以在ISR中使用的替代方法。
#define xQueueOverwrite( xQueue, pvItemToQueue ) xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), 0, queueOVERWRITE )
------------------------------------------------------------
//最好使用宏xQueueSendFromISR()、xQueueSendToFrontFromISR()和xQueueSendToBackFromISR()来代替直接调用这个函数。xQueueGiveFromISR()对于不复制任何数据的信号量来说是等价的。
//将项目发布到队列上。在中断服务程序中使用这个函数是安全的。
//项目是通过复制而不是引用来排队的,所以这比只对小项目排队更好,特别是在从ISR调用时。在大多数情况下,最好是存储一个指向正在排队的项目的指针。
BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue, const void * const pvItemToQueue, BaseType_t * const pxHigherPriorityTaskWoken, const BaseType_t xCopyPosition );
BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue, BaseType_t * const pxHigherPriorityTaskWoken );
//这是一个调用xQueueGenericSendFromISR()的宏。
//将项目发布到队列前面。在中断服务程序中使用这个宏是安全的。
//项目是通过复制而不是引用来排队的,所以这比只对小项目排队更好,特别是在从ISR调用时。在大多数情况下,最好是存储一个指向正在排队的项目的指针。
#define xQueueSendToFrontFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_FRONT )
//这是一个调用xQueueGenericSendFromISR()的宏。
//将项目发布到队列的后面。在中断服务程序中使用这个宏是安全的。
//项目是通过复制而不是引用来排队的,所以这比只对小项目排队更好,特别是在从ISR调用时。在大多数情况下,最好是存储一个指向正在排队的项目的指针。
#define xQueueSendToBackFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_BACK )
//可以在中断服务例程(ISR)中使用的xQueueOverwrite()的一个版本。
//仅用于可以保存单个项目的队列——因此队列要么是空的,要么是满的。
//将项目发布到队列上。如果队列已满,则覆盖队列中持有的值。这个项目是通过复制而不是引用来排队的。
#define xQueueOverwriteFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueOVERWRITE )
//这是一个调用xQueueGenericSendFromISR()的宏。它是为了向后兼容FreeRTOS.org的版本而包含的,这些版本不包括xQueueSendToBackFromISR()和xQueueSendToFrontFromISR()宏。
//将项目发布到队列的后面。在中断服务程序中使用这个函数是安全的。
//项目是通过复制而不是引用来排队的,所以这比只对小项目排队更好,特别是在从ISR调用时。在大多数情况下,最好是存储一个指向正在排队的项目的指针。
#define xQueueSendFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_BACK )
------------------------------------------------------------
//最好使用宏xQueueReceive(),而不是直接调用这个函数。
//从队列接收项目。项目通过复制接收,因此必须提供足够大小的缓冲区。创建队列时定义了复制到缓冲区中的字节数。
//这个函数不能在中断服务程序中使用。请参阅xQueueReceiveFromISR,以获得一个可行的替代方案。
BaseType_t xQueueGenericReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait, const BaseType_t xJustPeek );
//从队列接收项目。项目通过复制接收,因此必须提供足够大小的缓冲区。创建队列时定义了复制到缓冲区中的字节数。
//成功接收到的项目将从队列中删除。这个函数不能在中断服务程序中