⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 queue.c

📁 关于 modbus tcp 的一些源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*

	FreeRTOS.org V4.1.1 - Copyright (C) 2003-2006 Richard Barry.



	This file is part of the FreeRTOS.org distribution.



	FreeRTOS.org is free software; you can redistribute it and/or modify

	it under the terms of the GNU General Public License as published by

	the Free Software Foundation; either version 2 of the License, or

	(at your option) any later version.



	FreeRTOS.org is distributed in the hope that it will be useful,

	but WITHOUT ANY WARRANTY; without even the implied warranty of

	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the

	GNU General Public License for more details.



	You should have received a copy of the GNU General Public License

	along with FreeRTOS.org; if not, write to the Free Software

	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA



	A special exception to the GPL can be applied should you wish to distribute

	a combined work that includes FreeRTOS.org, without being obliged to provide

	the source code for any proprietary components.  See the licensing section

	of http://www.FreeRTOS.org for full details of how and when the exception

	can be applied.



	***************************************************************************

	See http://www.FreeRTOS.org for documentation, latest information, license

	and contact details.  Please ensure to read the configuration and relevant

	port sections of the online documentation.

	***************************************************************************

*/



/*

Changes from V1.01



	+ More use of 8bit data types.

	+ Function name prefixes changed where the data type returned has changed.



Changed from V2.0.0



	+ Added the queue locking mechanism and make more use of the scheduler

	  suspension feature to minimise the time interrupts have to be disabled

	  when accessing a queue.



Changed from V2.2.0



	+ Explicit use of 'signed' qualifier on portCHAR types added.



Changes from V3.0.0



	+ API changes as described on the FreeRTOS.org WEB site.



Changes from V3.2.3



	+ Added the queue functions that can be used from co-routines.



Changes from V4.0.5



	+ Added a loop within xQueueSend() and xQueueReceive() to prevent the

	  functions exiting when a block time remains and the function has

	  not completed.



*/



#include <stdlib.h>

#include <string.h>

#include "FreeRTOS.h"

#include "task.h"

#include "croutine.h"



/*-----------------------------------------------------------

 * PUBLIC LIST API documented in list.h

 *----------------------------------------------------------*/



/* Constants used with the cRxLock and cTxLock structure members. */

#define queueUNLOCKED	( ( signed portBASE_TYPE ) -1 )

#define queueERRONEOUS_UNBLOCK					( -1 )



/*

 * Definition of the queue used by the scheduler.

 * Items are queued by copy, not reference.

 */

typedef struct QueueDefinition

{

	signed portCHAR *pcHead;				/*< Points to the beginning of the queue storage area. */

	signed portCHAR *pcTail;				/*< Points to the byte at the end of the queue storage area.  Once more byte is allocated than necessary to store the queue items, this is used as a marker. */



	signed portCHAR *pcWriteTo;				/*< Points to the free next place in the storage area. */

	signed portCHAR *pcReadFrom;			/*< Points to the last place that a queued item was read from. */



	xList xTasksWaitingToSend;				/*< List of tasks that are blocked waiting to post onto this queue.  Stored in priority order. */

	xList xTasksWaitingToReceive;			/*< List of tasks that are blocked waiting to read from this queue.  Stored in priority order. */



	unsigned portBASE_TYPE uxMessagesWaiting;/*< The number of items currently in the queue. */

	unsigned portBASE_TYPE uxLength;		/*< The length of the queue defined as the number of items it will hold, not the number of bytes. */

	unsigned portBASE_TYPE uxItemSize;		/*< The size of each items that the queue will hold. */



	signed portBASE_TYPE xRxLock;				/*< 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. */

	signed portBASE_TYPE xTxLock;				/*< 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. */

} xQUEUE;

/*-----------------------------------------------------------*/



/*

 * Inside this file xQueueHandle is a pointer to a xQUEUE structure.

 * To keep the definition private the API header file defines it as a

 * pointer to void.

 */

typedef xQUEUE * xQueueHandle;



/*

 * Prototypes for public functions are included here so we don't have to

 * include the API header file (as it defines xQueueHandle differently).  These

 * functions are documented in the API header file.

 */

xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize );

signed portBASE_TYPE xQueueSend( xQueueHandle xQueue, const void * pvItemToQueue, portTickType xTicksToWait );

unsigned portBASE_TYPE uxQueueMessagesWaiting( xQueueHandle pxQueue );

void vQueueDelete( xQueueHandle xQueue );

signed portBASE_TYPE xQueueSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xTaskPreviouslyWoken );

signed portBASE_TYPE xQueueReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait );

signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxTaskWoken );



#if configUSE_CO_ROUTINES == 1

	signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken );

	signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxTaskWoken );

	signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait );

	signed portBASE_TYPE xQueueCRReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait );

#endif



/*

 * Unlocks a queue locked by a call to prvLockQueue.  Locking a queue does not

 * prevent an ISR from adding or removing items to the queue, but does prevent

 * an ISR from removing tasks from the queue event lists.  If an ISR finds a

 * queue is locked it will instead increment the appropriate queue lock count

 * to indicate that a task may require unblocking.  When the queue in unlocked

 * these lock counts are inspected, and the appropriate action taken.

 */

static void prvUnlockQueue( xQueueHandle pxQueue );



/*

 * Uses a critical section to determine if there is any data in a queue.

 *

 * @return pdTRUE if the queue contains no items, otherwise pdFALSE.

 */

static signed portBASE_TYPE prvIsQueueEmpty( const xQueueHandle pxQueue );



/*

 * Uses a critical section to determine if there is any space in a queue.

 *

 * @return pdTRUE if there is no space, otherwise pdFALSE;

 */

static signed portBASE_TYPE prvIsQueueFull( const xQueueHandle pxQueue );



/*

 * Macro that copies an item into the queue.  This is done by copying the item

 * byte for byte, not by reference.  Updates the queue state to ensure it's

 * integrity after the copy.

 */

#define prvCopyQueueData( pxQueue, pvItemToQueue )												\

{																								\

	memcpy( ( void * ) pxQueue->pcWriteTo, pvItemToQueue, ( unsigned ) pxQueue->uxItemSize );	\

	++( pxQueue->uxMessagesWaiting );															\

	pxQueue->pcWriteTo += pxQueue->uxItemSize;													\

	if( pxQueue->pcWriteTo >= pxQueue->pcTail )													\

	{																							\

		pxQueue->pcWriteTo = pxQueue->pcHead;													\

	}																							\

}

/*-----------------------------------------------------------*/



/*

 * Macro to mark a queue as locked.  Locking a queue prevents an ISR from

 * accessing the queue event lists.

 */

#define prvLockQueue( pxQueue )			\

{										\

	taskENTER_CRITICAL();				\

		++( pxQueue->xRxLock );			\

		++( pxQueue->xTxLock );			\

	taskEXIT_CRITICAL();				\

}

/*-----------------------------------------------------------*/





/*-----------------------------------------------------------

 * PUBLIC QUEUE MANAGEMENT API documented in queue.h

 *----------------------------------------------------------*/



xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize )

{

xQUEUE *pxNewQueue;

size_t xQueueSizeInBytes;



	/* Allocate the new queue structure. */

	if( uxQueueLength > ( unsigned portBASE_TYPE ) 0 )

	{

		pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) );

		if( pxNewQueue != NULL )

		{

			/* Create the list of pointers to queue items.  The queue is one byte

			longer than asked for to make wrap checking easier/faster. */

			xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ) + ( size_t ) 1;



			pxNewQueue->pcHead = ( signed portCHAR * ) pvPortMalloc( xQueueSizeInBytes );

			if( pxNewQueue->pcHead != NULL )

			{

				/* Initialise the queue members as described above where the

				queue type is defined. */

				pxNewQueue->pcTail = pxNewQueue->pcHead + ( uxQueueLength * uxItemSize );

				pxNewQueue->uxMessagesWaiting = 0;

				pxNewQueue->pcWriteTo = pxNewQueue->pcHead;

				pxNewQueue->pcReadFrom = pxNewQueue->pcHead + ( ( uxQueueLength - 1 ) * uxItemSize );

				pxNewQueue->uxLength = uxQueueLength;

				pxNewQueue->uxItemSize = uxItemSize;

				pxNewQueue->xRxLock = queueUNLOCKED;

				pxNewQueue->xTxLock = queueUNLOCKED;



				/* Likewise ensure the event queues start with the correct state. */

				vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) );

				vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) );



				return  pxNewQueue;

			}

			else

			{

				vPortFree( pxNewQueue );

			}

		}

	}



	/* Will only reach here if we could not allocate enough memory or no memory

	was required. */

	return NULL;

}

/*-----------------------------------------------------------*/



signed portBASE_TYPE xQueueSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait )

{

signed portBASE_TYPE xReturn;

xTimeOutType xTimeOut;



	/* Make sure other tasks do not access the queue. */

	vTaskSuspendAll();



	/* Capture the current time status for future reference. */

	vTaskSetTimeOutState( &xTimeOut );



	/* It is important that this is the only thread/ISR that modifies the

	ready or delayed lists until xTaskResumeAll() is called.  Places where

	the ready/delayed lists are modified include:



		+ vTaskDelay() -  Nothing can call vTaskDelay as the scheduler is

		  suspended, vTaskDelay() cannot be called from an ISR.

		+ vTaskPrioritySet() - Has a critical section around the access.

		+ vTaskSwitchContext() - This will not get executed while the scheduler

		  is suspended.

		+ prvCheckDelayedTasks() - This will not get executed while the

		  scheduler is suspended.

		+ xTaskCreate() - Has a critical section around the access.

		+ vTaskResume() - Has a critical section around the access.

		+ xTaskResumeAll() - Has a critical section around the access.

		+ xTaskRemoveFromEventList - Checks to see if the scheduler is

		  suspended.  If so then the TCB being removed from the event is

		  removed from the event and added to the xPendingReadyList.

	*/



	/* Make sure interrupts do not access the queue event list. */

	prvLockQueue( pxQueue );



	/* It is important that interrupts to not access the event list of the

	queue being modified here.  Places where the event list is modified

	include:



		+ xQueueSendFromISR().  This checks the lock on the queue to see if

		  it has access.  If the queue is locked then the Tx lock count is

		  incremented to signify that a task waiting for data can be made ready

		  once the queue lock is removed.  If the queue is not locked then

		  a task can be moved from the event list, but will not be removed

		  from the delayed list or placed in the ready list until the scheduler

		  is unlocked.



		+ xQueueReceiveFromISR().  As per xQueueSendFromISR().

	*/

		

	/* If the queue is already full we may have to block. */

	do

	{

		if( prvIsQueueFull( pxQueue ) )

		{

			/* The queue is full - do we want to block or just leave without

			posting? */

			if( xTicksToWait > ( portTickType ) 0 )

			{

				/* We are going to place ourselves on the xTasksWaitingToSend event

				list, and will get woken should the delay expire, or space become

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -