FreeRTOS Queue

变量定义

typedef void *QueueHandle_t;  // Type by which queues are referenced. 
typedef void *QueueSetHandle_t; // Type by which queue sets are referenced.
typedef void *QueueSetMemberHandle_t; 
/* For internal use only. */
#define queueSEND_TO_BACK 	((BaseType_t)0)
#define queueSEND_TO_FRONT 	((BaseType_t)1)
#define queueOVERWRITE 		((BaseType_t)2)
/* For internal use only.  These definitions *must* match those in queue.c. */
#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)
/*
 * Definition of the queue used by the scheduler.
 * Items are queued by copy, not reference.  
 */
typedef struct QueueDefinition
{
	/*< Points to the beginning of the queue storage area. */
	int8_t *pcHead;	 
	 /*< Points to the byte at the end of the queue storage area. */  
	int8_t *pcTail;	 
	/*< Points to the free next place in the storage area. */ 
	int8_t *pcWriteTo; 
	
	/* Use of a union is an exception to the coding standard to ensure two mutually exclusive structure members don't appear simultaneously (wasting RAM). */
	union 
	{
		 /*< Points to the last place that a queued item was read from when the structure is used as a queue. */
		int8_t *pcReadFrom;	
		/*< Maintains a count of the number of times a recursive mutex has been recursively 'taken' when the structure is used as a mutex. */			 
		UBaseType_t uxRecursiveCallCount; 
	} u;
	
	/*< List of tasks that are blocked waiting to post onto this queue.  Stored in priority order. */
	List_t xTasksWaitingToSend;	 
	/*< List of tasks that are blocked waiting to read from this queue.  Stored in priority order. */  
	List_t xTasksWaitingToReceive; 

	/*< The number of items currently in the queue. */
	volatile UBaseType_t uxMessagesWaiting; 
	/*< The length of the queue defined as the number of items it will hold, not the number of bytes. */
	UBaseType_t uxLength;
	/*< The size of each items that the queue will hold. */
	UBaseType_t uxItemSize;					
	
	/*< Stores the number of items received from the queue (removed from the queue) while the queue was locked.  
		Set to queueUNLOCKED when the queue is not locked. */
	volatile int8_t cRxLock; 
	/*< Stores the number of items transmitted to the queue (added to the queue) while the queue was locked.  
		Set to queueUNLOCKED when the queue is not locked. */
	volatile int8_t cTxLock; 

} xQUEUE;

typedef xQUEUE Queue_t;

创建队列

Internally, within the FreeRTOS implementation, queues use two blocks of memory. The first block is used to hold the queue’s data structures. The second block is used to hold items placed into the queue. If a queue is created using xQueueCreate() then both blocks of memory are automatically dynamically allocated inside the xQueueCreate() function. If a queue is created using xQueueCreateStatic() then the application writer must provide the memory that will get used by the queue. xQueueCreateStatic() therefore allows a queue to be created without using any dynamic memory allocation.

#define xQueueCreate(uxQueueLength, uxItemSize)  \
	    xQueueGenericCreate((uxQueueLength), (uxItemSize), (queueQUEUE_TYPE_BASE))
	    
QueueHandle_t xQueueGenericCreate(const UBaseType_t uxQueueLength, 
								  const UBaseType_t uxItemSize, 
								  const uint8_t ucQueueType) PRIVILEGED_FUNCTION;
								  
#define xQueueCreateStatic(uxQueueLength, uxItemSize, pucQueueStorage, pxQueueBuffer) \
xQueueGenericCreateStatic((uxQueueLength), (uxItemSize), (pucQueueStorage), (pxQueueBuffer), (queueQUEUE_TYPE_BASE))

QueueHandle_t xQueueGenericCreateStatic(const UBaseType_t uxQueueLength, 
										const UBaseType_t uxItemSize, 
										uint8_t *pucQueueStorage, 
										StaticQueue_t *pxStaticQueue, 
										const uint8_t ucQueueType) PRIVILEGED_FUNCTION;
QueueHandle_t xQueueGenericCreate(const UBaseType_t uxQueueLength, 
								  const UBaseType_t uxItemSize, 
								  const uint8_t ucQueueType)
{
	Queue_t *pxNewQueue;
	size_t xQueueSizeInBytes;
	uint8_t *pucQueueStorage;

	configASSERT(uxQueueLength > (UBaseType_t)0);

	if (uxItemSize == (UBaseType_t)0)
	{
		/* There is not going to be a queue storage area. */
		xQueueSizeInBytes = (size_t)0;
	}
	else
	{
		/* Allocate enough space to hold the maximum number of items that
		can be in the queue at any time. */
		xQueueSizeInBytes = (size_t)(uxQueueLength * uxItemSize); 
	}

	pxNewQueue = (Queue_t *)pvPortMalloc(sizeof(Queue_t) + xQueueSizeInBytes);

	if (pxNewQueue != NULL)
	{
		/* Jump past the queue structure to find the location of the queue storage area. */
		pucQueueStorage = ((uint8_t *)pxNewQueue) + sizeof(Queue_t);
		prvInitialiseNewQueue(uxQueueLength, uxItemSize, pucQueueStorage, ucQueueType, pxNewQueue);
	}

	return pxNewQueue;
}
static void prvInitialiseNewQueue(const UBaseType_t uxQueueLength, 
								  const UBaseType_t uxItemSize, 
								  uint8_t *pucQueueStorage, 
								  const uint8_t ucQueueType, 
								  Queue_t *pxNewQueue)
{
	/* Remove compiler warnings about unused parameters should
	configUSE_TRACE_FACILITY not be set to 1. */
	(void)ucQueueType;

	if (uxItemSize == (UBaseType_t)0)
	{
		pxNewQueue->pcHead = (int8_t *)pxNewQueue;
	}
	else
	{
		/* Set the head to the start of the queue storage area. */
		pxNewQueue->pcHead = (int8_t *)pucQueueStorage;
	}

	/* Initialise the queue members as described where the queue type is defined. */
	pxNewQueue->uxLength = uxQueueLength;
	pxNewQueue->uxItemSize = uxItemSize;
	(void)xQueueGenericReset(pxNewQueue, pdTRUE);
	
	traceQUEUE_CREATE(pxNewQueue);
}
BaseType_t xQueueGenericReset(QueueHandle_t xQueue, BaseType_t xNewQueue)
{
	Queue_t *const pxQueue = (Queue_t *)xQueue;

	configASSERT(pxQueue);

	taskENTER_CRITICAL();
	{
		pxQueue->pcTail = pxQueue->pcHead + (pxQueue->uxLength * pxQueue->uxItemSize);
		pxQueue->uxMessagesWaiting = (UBaseType_t)0U;
		pxQueue->pcWriteTo = pxQueue->pcHead;
		pxQueue->u.pcReadFrom = pxQueue->pcHead + ((pxQueue->uxLength - (UBaseType_t)1U) * pxQueue->uxItemSize);
		pxQueue->cRxLock = queueUNLOCKED;
		pxQueue->cTxLock = queueUNLOCKED;

		if (xNewQueue == pdFALSE)
		{
			/* If there are tasks blocked waiting to read from the queue, then
			the tasks will remain blocked as after this function exits the queue
			will still be empty.  If there are tasks blocked waiting to write to
			the queue, then one should be unblocked as after this function exits
			it will be possible to write to it. */
			if (listLIST_IS_EMPTY(&(pxQueue->xTasksWaitingToSend)) == pdFALSE)
			{
				if (xTaskRemoveFromEventList(&(pxQueue->xTasksWaitingToSend)) != pdFALSE)
				{
					queueYIELD_IF_USING_PREEMPTION();
				}
				else
				{
					mtCOVERAGE_TEST_MARKER();
				}
			}
			else
			{
				mtCOVERAGE_TEST_MARKER();
			}
		}
		else
		{
			/* Ensure the event queues start in the correct state. */
			vListInitialise(&(pxQueue->xTasksWaitingToSend));
			vListInitialise(&(pxQueue->xTasksWaitingToReceive));
		}
	}
	taskEXIT_CRITICAL();

	/* A value is returned for calling semantic consistency with previous versions. */
	return pdPASS;
}

范例

 struct AMessage
 {
	char ucMessageID;
	char ucData[ 20 ];
 };

 void vATask( void *pvParameters )
 {
 QueueHandle_t xQueue1, xQueue2;

	// Create a queue capable of containing 10 uint32_t values.
	xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );
	if( xQueue1 == 0 )
	{
		// Queue was not created and must not be used.
	}

	// Create a queue capable of containing 10 pointers to AMessage structures.
	// These should be passed by pointer as they contain a lot of data.
	xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
	if( xQueue2 == 0 )
	{
		// Queue was not created and must not be used.
	}

	// ... Rest of task code.
 }
define xQueueCreateStatic(uxQueueLength, uxItemSize, pucQueueStorage, pxQueueBuffer)	\
xQueueGenericCreateStatic((uxQueueLength), (uxItemSize), (pucQueueStorage), (pxQueueBuffer), (queueQUEUE_TYPE_BASE))
 struct AMessage
 {
	char ucMessageID;
	char ucData[ 20 ];
 };

 #define QUEUE_LENGTH 10
 #define ITEM_SIZE sizeof( uint32_t )

 // xQueueBuffer will hold the queue structure.
 StaticQueue_t xQueueBuffer;

 // ucQueueStorage will hold the items posted to the queue.  Must be at least
 // [(queue length) * ( queue item size)] bytes long.
 uint8_t ucQueueStorage[ QUEUE_LENGTH * ITEM_SIZE ];

 void vATask( void *pvParameters )
 {
 QueueHandle_t xQueue1;

	// Create a queue capable of containing 10 uint32_t values.
	xQueue1 = xQueueCreate( QUEUE_LENGTH, // The number of items the queue can hold.
							ITEM_SIZE	  // The size of each item in the queue
							&( ucQueueStorage[ 0 ] ), // The buffer that will hold the items in the queue.
							&xQueueBuffer ); // The buffer that will hold the queue structure.

	// The queue is guaranteed to be created successfully as no dynamic memory
	// allocation is used.  Therefore xQueue1 is now a handle to a valid queue.

	// ... Rest of task code.
 }
#define xQueueSendToFront(xQueue, pvItemToQueue, xTicksToWait) \
		xQueueGenericSend((xQueue), (pvItemToQueue), (xTicksToWait), queueSEND_TO_FRONT)
 struct AMessage
 {
	char ucMessageID;
	char ucData[ 20 ];
 } xMessage;

 uint32_t ulVar = 10UL;

 void vATask( void *pvParameters )
 {
 QueueHandle_t xQueue1, xQueue2;
 struct AMessage *pxMessage;

	// Create a queue capable of containing 10 uint32_t values.
	xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );

	// Create a queue capable of containing 10 pointers to AMessage structures.
	// These should be passed by pointer as they contain a lot of data.
	xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );

	// ...

	if( xQueue1 != 0 )
	{
		// Send an uint32_t.  Wait for 10 ticks for space to become
		// available if necessary.
		if( xQueueSendToFront( xQueue1, ( void * ) &ulVar, ( TickType_t ) 10 ) != pdPASS )
		{
			// Failed to post the message, even after 10 ticks.
		}
	}

	if( xQueue2 != 0 )
	{
		// Send a pointer to a struct AMessage object.  Don't block if the
		// queue is already full.
		pxMessage = & xMessage;
		xQueueSendToFront( xQueue2, ( void * ) &pxMessage, ( TickType_t ) 0 );
	}

	// ... Rest of task code.
 }
#define xQueueSendToBack(xQueue, pvItemToQueue, xTicksToWait) \
		xQueueGenericSend((xQueue), (pvItemToQueue), (xTicksToWait), queueSEND_TO_BACK)
 struct AMessage
 {
	char ucMessageID;
	char ucData[ 20 ];
 } xMessage;

 uint32_t ulVar = 10UL;

 void vATask( void *pvParameters )
 {
 QueueHandle_t xQueue1, xQueue2;
 struct AMessage *pxMessage;

	// Create a queue capable of containing 10 uint32_t values.
	xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );

	// Create a queue capable of containing 10 pointers to AMessage structures.
	// These should be passed by pointer as they contain a lot of data.
	xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );

	// ...

	if( xQueue1 != 0 )
	{
		// Send an uint32_t.  Wait for 10 ticks for space to become
		// available if necessary.
		if( xQueueSendToBack( xQueue1, ( void * ) &ulVar, ( TickType_t ) 10 ) != pdPASS )
		{
			// Failed to post the message, even after 10 ticks.
		}
	}

	if( xQueue2 != 0 )
	{
		// Send a pointer to a struct AMessage object.  Don't block if the
		// queue is already full.
		pxMessage = & xMessage;
		xQueueSendToBack( xQueue2, ( void * ) &pxMessage, ( TickType_t ) 0 );
	}

	// ... Rest of task code.
 }
#define xQueueSend(xQueue, pvItemToQueue, xTicksToWait) \
		xQueueGenericSend((xQueue), (pvItemToQueue), (xTicksToWait), queueSEND_TO_BACK)

 struct AMessage
 {
	char ucMessageID;
	char ucData[ 20 ];
 } xMessage;

 uint32_t ulVar = 10UL;

 void vATask( void *pvParameters )
 {
 QueueHandle_t xQueue1, xQueue2;
 struct AMessage *pxMessage;

	// Create a queue capable of containing 10 uint32_t values.
	xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );

	// Create a queue capable of containing 10 pointers to AMessage structures.
	// These should be passed by pointer as they contain a lot of data.
	xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );

	// ...

	if( xQueue1 != 0 )
	{
		// Send an uint32_t.  Wait for 10 ticks for space to become
		// available if necessary.
		if( xQueueSend( xQueue1, ( void * ) &ulVar, ( TickType_t ) 10 ) != pdPASS )
		{
			// Failed to post the message, even after 10 ticks.
		}
	}

	if( xQueue2 != 0 )
	{
		// Send a pointer to a struct AMessage object.  Don't block if the
		// queue is already full.
		pxMessage = & xMessage;
		xQueueSend( xQueue2, ( void * ) &pxMessage, ( TickType_t ) 0 );
	}

	// ... Rest of task code.
 }
#define xQueueOverwrite(xQueue, pvItemToQueue) xQueueGenericSend((xQueue), (pvItemToQueue), 0, queueOVERWRITE)
 void vFunction( void *pvParameters )
 {
 QueueHandle_t xQueue;
 uint32_t ulVarToSend, ulValReceived;

	// Create a queue to hold one uint32_t value.  It is strongly
	// recommended *not* to use xQueueOverwrite() on queues that can
	// contain more than one value, and doing so will trigger an assertion
	// if configASSERT() is defined.
	xQueue = xQueueCreate( 1, sizeof( uint32_t ) );

	// Write the value 10 to the queue using xQueueOverwrite().
	ulVarToSend = 10;
	xQueueOverwrite( xQueue, &ulVarToSend );

	// Peeking the queue should now return 10, but leave the value 10 in
	// the queue.  A block time of zero is used as it is known that the
	// queue holds a value.
	ulValReceived = 0;
	xQueuePeek( xQueue, &ulValReceived, 0 );

	if( ulValReceived != 10 )
	{
		// Error unless the item was removed by a different task.
	}

	// The queue is still full.  Use xQueueOverwrite() to overwrite the
	// value held in the queue with 100.
	ulVarToSend = 100;
	xQueueOverwrite( xQueue, &ulVarToSend );

	// This time read from the queue, leaving the queue empty once more.
	// A block time of 0 is used again.
	xQueueReceive( xQueue, &ulValReceived, 0 );

	// The value read should be the last value written, even though the
	// queue was already full when the value was written.
	if( ulValReceived != 100 )
	{
		// Error!
	}

	// ...
}
BaseType_t xQueueGenericSend(QueueHandle_t xQueue, const void *const pvItemToQueue, TickType_t xTicksToWait, const BaseType_t xCopyPosition) PRIVILEGED_FUNCTION;
	 struct AMessage
	 {
		char ucMessageID;
		char ucData[ 20 ];
	 } xMessage;

	 uint32_t ulVar = 10UL;

	 void vATask( void *pvParameters )
	 {
	 QueueHandle_t xQueue1, xQueue2;
	 struct AMessage *pxMessage;

		// Create a queue capable of containing 10 uint32_t values.
		xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );

		// Create a queue capable of containing 10 pointers to AMessage structures.
		// These should be passed by pointer as they contain a lot of data.
		xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );

		// ...

		if( xQueue1 != 0 )
		{
			// Send an uint32_t.  Wait for 10 ticks for space to become
			// available if necessary.
			if( xQueueGenericSend( xQueue1, ( void * ) &ulVar, ( TickType_t ) 10, queueSEND_TO_BACK ) != pdPASS )
			{
				// Failed to post the message, even after 10 ticks.
			}
		}

		if( xQueue2 != 0 )
		{
			// Send a pointer to a struct AMessage object.  Don't block if the
			// queue is already full.
			pxMessage = & xMessage;
			xQueueGenericSend( xQueue2, ( void * ) &pxMessage, ( TickType_t ) 0, queueSEND_TO_BACK );
		}

		// ... Rest of task code.
	 }
#define xQueuePeek(xQueue, pvBuffer, xTicksToWait) xQueueGenericReceive((xQueue), (pvBuffer), (xTicksToWait), pdTRUE)
 struct AMessage
 {
	char ucMessageID;
	char ucData[ 20 ];
 } xMessage;

 QueueHandle_t xQueue;

 // Task to create a queue and post a value.
 void vATask( void *pvParameters )
 {
 struct AMessage *pxMessage;

	// Create a queue capable of containing 10 pointers to AMessage structures.
	// These should be passed by pointer as they contain a lot of data.
	xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
	if( xQueue == 0 )
	{
		// Failed to create the queue.
	}

	// ...

	// Send a pointer to a struct AMessage object.  Don't block if the
	// queue is already full.
	pxMessage = & xMessage;
	xQueueSend( xQueue, ( void * ) &pxMessage, ( TickType_t ) 0 );

	// ... Rest of task code.
 }

 // Task to peek the data from the queue.
 void vADifferentTask( void *pvParameters )
 {
 struct AMessage *pxRxedMessage;

	if( xQueue != 0 )
	{
		// Peek a message on the created queue.  Block for 10 ticks if a
		// message is not immediately available.
		if( xQueuePeek( xQueue, &( pxRxedMessage ), ( TickType_t ) 10 ) )
		{
			// pcRxedMessage now points to the struct AMessage variable posted
			// by vATask, but the item still remains on the queue.
		}
	}

	// ... Rest of task code.
 }
BaseType_t xQueuePeekFromISR(QueueHandle_t xQueue, void *const pvBuffer) PRIVILEGED_FUNCTION;
#define xQueueReceive(xQueue, pvBuffer, xTicksToWait) xQueueGenericReceive((xQueue), (pvBuffer), (xTicksToWait), pdFALSE)
 struct AMessage
 {
	char ucMessageID;
	char ucData[ 20 ];
 } xMessage;

 QueueHandle_t xQueue;

 // Task to create a queue and post a value.
 void vATask( void *pvParameters )
 {
 struct AMessage *pxMessage;

	// Create a queue capable of containing 10 pointers to AMessage structures.
	// These should be passed by pointer as they contain a lot of data.
	xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
	if( xQueue == 0 )
	{
		// Failed to create the queue.
	}

	// ...

	// Send a pointer to a struct AMessage object.  Don't block if the
	// queue is already full.
	pxMessage = & xMessage;
	xQueueSend( xQueue, ( void * ) &pxMessage, ( TickType_t ) 0 );

	// ... Rest of task code.
 }

 // Task to receive from the queue.
 void vADifferentTask( void *pvParameters )
 {
 struct AMessage *pxRxedMessage;

	if( xQueue != 0 )
	{
		// Receive a message on the created queue.  Block for 10 ticks if a
		// message is not immediately available.
		if( xQueueReceive( xQueue, &( pxRxedMessage ), ( TickType_t ) 10 ) )
		{
			// pcRxedMessage now points to the struct AMessage variable posted
			// by vATask.
		}
	}

	// ... Rest of task code.
 }
BaseType_t xQueueGenericReceive(QueueHandle_t xQueue, void *const pvBuffer, TickType_t xTicksToWait, const BaseType_t xJustPeek) PRIVILEGED_FUNCTION;
	 struct AMessage
	 {
		char ucMessageID;
		char ucData[ 20 ];
	 } xMessage;

	 QueueHandle_t xQueue;

	 // Task to create a queue and post a value.
	 void vATask( void *pvParameters )
	 {
	 struct AMessage *pxMessage;

		// Create a queue capable of containing 10 pointers to AMessage structures.
		// These should be passed by pointer as they contain a lot of data.
		xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
		if( xQueue == 0 )
		{
			// Failed to create the queue.
		}

		// ...

		// Send a pointer to a struct AMessage object.  Don't block if the
		// queue is already full.
		pxMessage = & xMessage;
		xQueueSend( xQueue, ( void * ) &pxMessage, ( TickType_t ) 0 );

		// ... Rest of task code.
	 }

	 // Task to receive from the queue.
	 void vADifferentTask( void *pvParameters )
	 {
	 struct AMessage *pxRxedMessage;

		if( xQueue != 0 )
		{
			// Receive a message on the created queue.  Block for 10 ticks if a
			// message is not immediately available.
			if( xQueueGenericReceive( xQueue, &( pxRxedMessage ), ( TickType_t ) 10 ) )
			{
				// pcRxedMessage now points to the struct AMessage variable posted
				// by vATask.
			}
		}

		// ... Rest of task code.
	 }
BaseType_t xQueueGenericReceive(QueueHandle_t xQueue, void *const pvBuffer, TickType_t xTicksToWait, const BaseType_t xJustPeek) PRIVILEGED_FUNCTION;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值