/*\r
- FreeRTOS.org V4.4.0 - Copyright (C) 2003-2007 Richard Barry.\r
-\r
- This file is part of the FreeRTOS.org distribution.\r
-\r
- FreeRTOS.org is free software; you can redistribute it and/or modify\r
- it under the terms of the GNU General Public License as published by\r
- the Free Software Foundation; either version 2 of the License, or\r
- (at your option) any later version.\r
-\r
- FreeRTOS.org is distributed in the hope that it will be useful,\r
- but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- GNU General Public License for more details.\r
-\r
- You should have received a copy of the GNU General Public License\r
- along with FreeRTOS.org; if not, write to the Free Software\r
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
-\r
- A special exception to the GPL can be applied should you wish to distribute\r
- a combined work that includes FreeRTOS.org, without being obliged to provide\r
- the source code for any proprietary components. See the licensing section\r
- of http://www.FreeRTOS.org for full details of how and when the exception\r
- can be applied.\r
-\r
- ***************************************************************************\r
- See http://www.FreeRTOS.org for documentation, latest information, license\r
- and contact details. Please ensure to read the configuration and relevant\r
- port sections of the online documentation.\r
-\r
- Also see http://www.SafeRTOS.com for an IEC 61508 compliant version along\r
- with commercial development and support options.\r
- ***************************************************************************\r
-*/\r
-\r
-/*\r
-Changes from V1.01\r
-\r
- + More use of 8bit data types.\r
- + Function name prefixes changed where the data type returned has changed.\r
-\r
-Changed from V2.0.0\r
-\r
- + Added the queue locking mechanism and make more use of the scheduler\r
- suspension feature to minimise the time interrupts have to be disabled\r
- when accessing a queue.\r
-\r
-Changed from V2.2.0\r
-\r
- + Explicit use of 'signed' qualifier on portCHAR types added.\r
-\r
-Changes from V3.0.0\r
-\r
- + API changes as described on the FreeRTOS.org WEB site.\r
-\r
-Changes from V3.2.3\r
-\r
- + Added the queue functions that can be used from co-routines.\r
-\r
-Changes from V4.0.5\r
-\r
- + Added a loop within xQueueSend() and xQueueReceive() to prevent the\r
- functions exiting when a block time remains and the function has\r
- not completed.\r
-\r
-Changes from V4.1.2:\r
-\r
- + BUG FIX: Removed the call to prvIsQueueEmpty from within xQueueCRReceive\r
- as it exited with interrupts enabled. Thanks Paul Katz.\r
-\r
-Changes from V4.1.3:\r
-\r
- + Modified xQueueSend() and xQueueReceive() to handle the (very unlikely)\r
- case whereby a task unblocking due to a temporal event can remove/send an\r
- item from/to a queue when a higher priority task is still blocked on the\r
- queue. This modification is a result of the SafeRTOS testing.\r
+ FreeRTOS V7.1.0 - Copyright (C) 2011 Real Time Engineers Ltd.\r
+\r
+\r
+ ***************************************************************************\r
+ * *\r
+ * FreeRTOS tutorial books are available in pdf and paperback. *\r
+ * Complete, revised, and edited pdf reference manuals are also *\r
+ * available. *\r
+ * *\r
+ * Purchasing FreeRTOS documentation will not only help you, by *\r
+ * ensuring you get running as quickly as possible and with an *\r
+ * in-depth knowledge of how to use FreeRTOS, it will also help *\r
+ * the FreeRTOS project to continue with its mission of providing *\r
+ * professional grade, cross platform, de facto standard solutions *\r
+ * for microcontrollers - completely free of charge! *\r
+ * *\r
+ * >>> See http://www.FreeRTOS.org/Documentation for details. <<< *\r
+ * *\r
+ * Thank you for using FreeRTOS, and thank you for your support! *\r
+ * *\r
+ ***************************************************************************\r
+\r
+\r
+ This file is part of the FreeRTOS distribution.\r
+\r
+ FreeRTOS is free software; you can redistribute it and/or modify it under\r
+ the terms of the GNU General Public License (version 2) as published by the\r
+ Free Software Foundation AND MODIFIED BY the FreeRTOS exception.\r
+ >>>NOTE<<< The modification to the GPL is included to allow you to\r
+ distribute a combined work that includes FreeRTOS without being obliged to\r
+ provide the source code for proprietary components outside of the FreeRTOS\r
+ kernel. FreeRTOS is distributed in the hope that it will be useful, but\r
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\r
+ more details. You should have received a copy of the GNU General Public\r
+ License and the FreeRTOS license exception along with FreeRTOS; if not it\r
+ can be viewed here: http://www.freertos.org/a00114.html and also obtained\r
+ by writing to Richard Barry, contact details for whom are available on the\r
+ FreeRTOS WEB site.\r
+\r
+ 1 tab == 4 spaces!\r
+\r
+ http://www.FreeRTOS.org - Documentation, latest information, license and\r
+ contact details.\r
+\r
+ http://www.SafeRTOS.com - A version that is certified for use in safety\r
+ critical systems.\r
+\r
+ http://www.OpenRTOS.com - Commercial support, development, porting,\r
+ licensing and training services.\r
*/\r
\r
#include <stdlib.h>\r
#include <string.h>\r
+\r
+/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining\r
+all the API functions to use the MPU wrappers. That should only be done when\r
+task.h is included from an application file. */\r
+#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE\r
+\r
#include "FreeRTOS.h"\r
#include "task.h"\r
-#include "croutine.h"\r
+\r
+#if ( configUSE_CO_ROUTINES == 1 )\r
+ #include "croutine.h"\r
+#endif\r
+\r
+#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE\r
\r
/*-----------------------------------------------------------\r
* PUBLIC LIST API documented in list.h\r
*----------------------------------------------------------*/\r
\r
/* Constants used with the cRxLock and cTxLock structure members. */\r
-#define queueUNLOCKED ( ( signed portBASE_TYPE ) -1 )\r
-#define queueERRONEOUS_UNBLOCK ( -1 )\r
+#define queueUNLOCKED ( ( signed portBASE_TYPE ) -1 )\r
+#define queueLOCKED_UNMODIFIED ( ( signed portBASE_TYPE ) 0 )\r
+\r
+#define queueERRONEOUS_UNBLOCK ( -1 )\r
\r
/* For internal use only. */\r
-#define queueSEND_TO_BACK ( 0 )\r
-#define queueSEND_TO_FRONT ( 1 )\r
+#define queueSEND_TO_BACK ( 0 )\r
+#define queueSEND_TO_FRONT ( 1 )\r
\r
/* Effectively make a union out of the xQUEUE structure. */\r
-#define pxMutexHolder pcTail\r
-#define uxQueueType pcHead\r
-#define queueQUEUE_IS_MUTEX NULL\r
+#define pxMutexHolder pcTail\r
+#define uxQueueType pcHead\r
+#define uxRecursiveCallCount pcReadFrom\r
+#define queueQUEUE_IS_MUTEX NULL\r
+\r
+/* Semaphores do not actually store or copy data, so have an items size of\r
+zero. */\r
+#define queueSEMAPHORE_QUEUE_ITEM_LENGTH ( ( unsigned portBASE_TYPE ) 0 )\r
+#define queueDONT_BLOCK ( ( portTickType ) 0U )\r
+#define queueMUTEX_GIVE_BLOCK_TIME ( ( portTickType ) 0U )\r
+\r
+/* These definitions *must* match those in queue.h. */\r
+#define queueQUEUE_TYPE_BASE ( 0U )\r
+#define queueQUEUE_TYPE_MUTEX ( 1U )\r
+#define queueQUEUE_TYPE_COUNTING_SEMAPHORE ( 2U )\r
+#define queueQUEUE_TYPE_BINARY_SEMAPHORE ( 3U )\r
+#define queueQUEUE_TYPE_RECURSIVE_MUTEX ( 4U )\r
\r
/*\r
* Definition of the queue used by the scheduler.\r
*/\r
typedef struct QueueDefinition\r
{\r
- signed portCHAR *pcHead; /*< Points to the beginning of the queue storage area. */\r
- 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. */\r
+ signed char *pcHead; /*< Points to the beginning of the queue storage area. */\r
+ signed char *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. */\r
\r
- signed portCHAR *pcWriteTo; /*< Points to the free next place in the storage area. */\r
- signed portCHAR *pcReadFrom; /*< Points to the last place that a queued item was read from. */\r
+ signed char *pcWriteTo; /*< Points to the free next place in the storage area. */\r
+ signed char *pcReadFrom; /*< Points to the last place that a queued item was read from. */\r
\r
xList xTasksWaitingToSend; /*< List of tasks that are blocked waiting to post onto this queue. Stored in priority order. */\r
xList xTasksWaitingToReceive; /*< List of tasks that are blocked waiting to read from this queue. Stored in priority order. */\r
\r
- unsigned portBASE_TYPE uxMessagesWaiting;/*< The number of items currently in the queue. */\r
+ volatile unsigned portBASE_TYPE uxMessagesWaiting;/*< The number of items currently in the queue. */\r
unsigned portBASE_TYPE uxLength; /*< The length of the queue defined as the number of items it will hold, not the number of bytes. */\r
unsigned portBASE_TYPE uxItemSize; /*< The size of each items that the queue will hold. */\r
\r
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. */\r
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. */\r
+ \r
+ #if ( configUSE_TRACE_FACILITY == 1 )\r
+ unsigned char ucQueueNumber;\r
+ unsigned char ucQueueType;\r
+ #endif\r
+\r
} xQUEUE;\r
/*-----------------------------------------------------------*/\r
\r
* include the API header file (as it defines xQueueHandle differently). These\r
* functions are documented in the API header file.\r
*/\r
-xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize );\r
-signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition );\r
-unsigned portBASE_TYPE uxQueueMessagesWaiting( xQueueHandle pxQueue );\r
-void vQueueDelete( xQueueHandle xQueue );\r
-signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE xTaskPreviouslyWoken, portBASE_TYPE xCopyPosition );\r
-signed portBASE_TYPE xQueueGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking );\r
-signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken );\r
-xQueueHandle xQueueCreateMutex( void );\r
+xQueueHandle xQueueGenericCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize, unsigned char ucQueueType ) PRIVILEGED_FUNCTION;\r
+signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION;\r
+unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;\r
+void vQueueDelete( xQueueHandle xQueue ) PRIVILEGED_FUNCTION;\r
+signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION;\r
+signed portBASE_TYPE xQueueGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking ) PRIVILEGED_FUNCTION;\r
+signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken ) PRIVILEGED_FUNCTION;\r
+xQueueHandle xQueueCreateMutex( unsigned char ucQueueType ) PRIVILEGED_FUNCTION;\r
+xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount ) PRIVILEGED_FUNCTION;\r
+portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle xMutex, portTickType xBlockTime ) PRIVILEGED_FUNCTION;\r
+portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle xMutex ) PRIVILEGED_FUNCTION;\r
+signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION;\r
+signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking ) PRIVILEGED_FUNCTION;\r
+signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;\r
+signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;\r
+unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;\r
+void vQueueWaitForMessageRestricted( xQueueHandle pxQueue, portTickType xTicksToWait ) PRIVILEGED_FUNCTION;\r
+unsigned char ucQueueGetQueueNumber( xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;\r
+void vQueueSetQueueNumber( xQueueHandle pxQueue, unsigned char ucQueueNumber ) PRIVILEGED_FUNCTION;\r
+unsigned char ucQueueGetQueueType( xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;\r
+portBASE_TYPE xQueueGenericReset( xQueueHandle pxQueue, portBASE_TYPE xNewQueue ) PRIVILEGED_FUNCTION;\r
\r
+/*\r
+ * Co-routine queue functions differ from task queue functions. Co-routines are\r
+ * an optional component.\r
+ */\r
#if configUSE_CO_ROUTINES == 1\r
- signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken );\r
- signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxTaskWoken );\r
- signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait );\r
- signed portBASE_TYPE xQueueCRReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait );\r
+ signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken ) PRIVILEGED_FUNCTION;\r
+ signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxTaskWoken ) PRIVILEGED_FUNCTION;\r
+ signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait ) PRIVILEGED_FUNCTION;\r
+ signed portBASE_TYPE xQueueCRReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait ) PRIVILEGED_FUNCTION;\r
+#endif\r
+\r
+/*\r
+ * The queue registry is just a means for kernel aware debuggers to locate\r
+ * queue structures. It has no other purpose so is an optional component.\r
+ */\r
+#if configQUEUE_REGISTRY_SIZE > 0\r
+\r
+ /* The type stored within the queue registry array. This allows a name\r
+ to be assigned to each queue making kernel aware debugging a little\r
+ more user friendly. */\r
+ typedef struct QUEUE_REGISTRY_ITEM\r
+ {\r
+ signed char *pcQueueName;\r
+ xQueueHandle xHandle;\r
+ } xQueueRegistryItem;\r
+\r
+ /* The queue registry is simply an array of xQueueRegistryItem structures.\r
+ The pcQueueName member of a structure being NULL is indicative of the\r
+ array position being vacant. */\r
+ xQueueRegistryItem xQueueRegistry[ configQUEUE_REGISTRY_SIZE ];\r
+\r
+ /* Removes a queue from the registry by simply setting the pcQueueName\r
+ member to NULL. */\r
+ static void vQueueUnregisterQueue( xQueueHandle xQueue ) PRIVILEGED_FUNCTION;\r
+ void vQueueAddToRegistry( xQueueHandle xQueue, signed char *pcQueueName ) PRIVILEGED_FUNCTION;\r
#endif\r
\r
/*\r
* to indicate that a task may require unblocking. When the queue in unlocked\r
* these lock counts are inspected, and the appropriate action taken.\r
*/\r
-static void prvUnlockQueue( xQueueHandle pxQueue );\r
+static void prvUnlockQueue( xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;\r
\r
/*\r
* Uses a critical section to determine if there is any data in a queue.\r
*\r
* @return pdTRUE if the queue contains no items, otherwise pdFALSE.\r
*/\r
-static signed portBASE_TYPE prvIsQueueEmpty( const xQueueHandle pxQueue );\r
+static signed portBASE_TYPE prvIsQueueEmpty( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;\r
\r
/*\r
* Uses a critical section to determine if there is any space in a queue.\r
*\r
* @return pdTRUE if there is no space, otherwise pdFALSE;\r
*/\r
-static signed portBASE_TYPE prvIsQueueFull( const xQueueHandle pxQueue );\r
+static signed portBASE_TYPE prvIsQueueFull( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;\r
\r
/*\r
* Copies an item into the queue, either at the front of the queue or the\r
* back of the queue.\r
*/\r
-static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition );\r
+static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition ) PRIVILEGED_FUNCTION;\r
\r
/*\r
* Copies an item out of a queue.\r
*/\r
-static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer );\r
+static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer ) PRIVILEGED_FUNCTION;\r
/*-----------------------------------------------------------*/\r
\r
/*\r
* Macro to mark a queue as locked. Locking a queue prevents an ISR from\r
* accessing the queue event lists.\r
*/\r
-#define prvLockQueue( pxQueue ) \\r
-{ \\r
- taskENTER_CRITICAL(); \\r
- ++( pxQueue->xRxLock ); \\r
- ++( pxQueue->xTxLock ); \\r
- taskEXIT_CRITICAL(); \\r
-}\r
+#define prvLockQueue( pxQueue ) \\r
+ taskENTER_CRITICAL(); \\r
+ { \\r
+ if( ( pxQueue )->xRxLock == queueUNLOCKED ) \\r
+ { \\r
+ ( pxQueue )->xRxLock = queueLOCKED_UNMODIFIED; \\r
+ } \\r
+ if( ( pxQueue )->xTxLock == queueUNLOCKED ) \\r
+ { \\r
+ ( pxQueue )->xTxLock = queueLOCKED_UNMODIFIED; \\r
+ } \\r
+ } \\r
+ taskEXIT_CRITICAL()\r
/*-----------------------------------------------------------*/\r
\r
\r
* PUBLIC QUEUE MANAGEMENT API documented in queue.h\r
*----------------------------------------------------------*/\r
\r
-xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize )\r
+portBASE_TYPE xQueueGenericReset( xQueueHandle pxQueue, portBASE_TYPE xNewQueue )\r
+{\r
+portBASE_TYPE xReturn = pdPASS;\r
+\r
+ configASSERT( pxQueue );\r
+\r
+ /* If the queue being reset has already been used (has not just been\r
+ created), then only reset the queue if its event lists are empty. */\r
+ if( xNewQueue != pdTRUE )\r
+ {\r
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
+ {\r
+ xReturn = pdFAIL;\r
+ }\r
+\r
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )\r
+ {\r
+ xReturn = pdFAIL;\r
+ }\r
+ }\r
+\r
+ if( xReturn == pdPASS )\r
+ {\r
+ pxQueue->pcTail = pxQueue->pcHead + ( pxQueue->uxLength * pxQueue->uxItemSize );\r
+ pxQueue->uxMessagesWaiting = ( unsigned portBASE_TYPE ) 0U;\r
+ pxQueue->pcWriteTo = pxQueue->pcHead;\r
+ pxQueue->pcReadFrom = pxQueue->pcHead + ( ( pxQueue->uxLength - ( unsigned portBASE_TYPE ) 1U ) * pxQueue->uxItemSize );\r
+ pxQueue->xRxLock = queueUNLOCKED;\r
+ pxQueue->xTxLock = queueUNLOCKED;\r
+\r
+ /* Ensure the event queues start with the correct state. */\r
+ vListInitialise( &( pxQueue->xTasksWaitingToSend ) );\r
+ vListInitialise( &( pxQueue->xTasksWaitingToReceive ) );\r
+ }\r
+\r
+ return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+xQueueHandle xQueueGenericCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize, unsigned char ucQueueType )\r
{\r
xQUEUE *pxNewQueue;\r
size_t xQueueSizeInBytes;\r
+xQueueHandle xReturn = NULL;\r
+\r
+ /* Remove compiler warnings about unused parameters should \r
+ configUSE_TRACE_FACILITY not be set to 1. */\r
+ ( void ) ucQueueType;\r
\r
/* Allocate the new queue structure. */\r
if( uxQueueLength > ( unsigned portBASE_TYPE ) 0 )\r
longer than asked for to make wrap checking easier/faster. */\r
xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ) + ( size_t ) 1;\r
\r
- pxNewQueue->pcHead = ( signed portCHAR * ) pvPortMalloc( xQueueSizeInBytes );\r
+ pxNewQueue->pcHead = ( signed char * ) pvPortMalloc( xQueueSizeInBytes );\r
if( pxNewQueue->pcHead != NULL )\r
{\r
/* Initialise the queue members as described above where the\r
queue type is defined. */\r
- pxNewQueue->pcTail = pxNewQueue->pcHead + ( uxQueueLength * uxItemSize );\r
- pxNewQueue->uxMessagesWaiting = 0;\r
- pxNewQueue->pcWriteTo = pxNewQueue->pcHead;\r
- pxNewQueue->pcReadFrom = pxNewQueue->pcHead + ( ( uxQueueLength - 1 ) * uxItemSize );\r
pxNewQueue->uxLength = uxQueueLength;\r
pxNewQueue->uxItemSize = uxItemSize;\r
- pxNewQueue->xRxLock = queueUNLOCKED;\r
- pxNewQueue->xTxLock = queueUNLOCKED;\r
-\r
- /* Likewise ensure the event queues start with the correct state. */\r
- vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) );\r
- vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) );\r
+ xQueueGenericReset( pxNewQueue, pdTRUE );\r
+ #if ( configUSE_TRACE_FACILITY == 1 )\r
+ {\r
+ pxNewQueue->ucQueueType = ucQueueType;\r
+ }\r
+ #endif /* configUSE_TRACE_FACILITY */\r
\r
- return pxNewQueue;\r
+ traceQUEUE_CREATE( pxNewQueue );\r
+ xReturn = pxNewQueue;\r
}\r
else\r
{\r
+ traceQUEUE_CREATE_FAILED( ucQueueType );\r
vPortFree( pxNewQueue );\r
}\r
}\r
}\r
\r
- /* Will only reach here if we could not allocate enough memory or no memory\r
- was required. */\r
- return NULL;\r
+ configASSERT( xReturn );\r
+\r
+ return xReturn;\r
}\r
/*-----------------------------------------------------------*/\r
\r
#if ( configUSE_MUTEXES == 1 )\r
\r
- xQueueHandle xQueueCreateMutex( void )\r
+ xQueueHandle xQueueCreateMutex( unsigned char ucQueueType )\r
{\r
xQUEUE *pxNewQueue;\r
+\r
+ /* Prevent compiler warnings about unused parameters if\r
+ configUSE_TRACE_FACILITY does not equal 1. */\r
+ ( void ) ucQueueType;\r
\r
/* Allocate the new queue structure. */\r
pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) );\r
/* Information required for priority inheritance. */\r
pxNewQueue->pxMutexHolder = NULL;\r
pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX;\r
- \r
+\r
/* Queues used as a mutex no data is actually copied into or out\r
of the queue. */\r
pxNewQueue->pcWriteTo = NULL;\r
pxNewQueue->pcReadFrom = NULL;\r
- \r
+\r
/* Each mutex has a length of 1 (like a binary semaphore) and\r
an item size of 0 as nothing is actually copied into or out\r
of the mutex. */\r
- pxNewQueue->uxMessagesWaiting = 0;\r
- pxNewQueue->uxLength = 1;\r
- pxNewQueue->uxItemSize = 0;\r
+ pxNewQueue->uxMessagesWaiting = ( unsigned portBASE_TYPE ) 0U;\r
+ pxNewQueue->uxLength = ( unsigned portBASE_TYPE ) 1U;\r
+ pxNewQueue->uxItemSize = ( unsigned portBASE_TYPE ) 0U;\r
pxNewQueue->xRxLock = queueUNLOCKED;\r
pxNewQueue->xTxLock = queueUNLOCKED;\r
- \r
+ \r
+ #if ( configUSE_TRACE_FACILITY == 1 )\r
+ {\r
+ pxNewQueue->ucQueueType = ucQueueType;\r
+ }\r
+ #endif\r
+\r
/* Ensure the event queues start with the correct state. */\r
vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) );\r
vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) );\r
\r
+ traceCREATE_MUTEX( pxNewQueue );\r
+\r
/* Start with the semaphore in the expected state. */\r
- xQueueGenericSend( pxNewQueue, NULL, 0, queueSEND_TO_BACK );\r
+ xQueueGenericSend( pxNewQueue, NULL, ( portTickType ) 0U, queueSEND_TO_BACK );\r
}\r
- \r
+ else\r
+ {\r
+ traceCREATE_MUTEX_FAILED();\r
+ }\r
+\r
+ configASSERT( pxNewQueue );\r
return pxNewQueue;\r
}\r
\r
#endif /* configUSE_MUTEXES */\r
/*-----------------------------------------------------------*/\r
\r
+#if configUSE_RECURSIVE_MUTEXES == 1\r
+\r
+ portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle pxMutex )\r
+ {\r
+ portBASE_TYPE xReturn;\r
+\r
+ configASSERT( pxMutex );\r
+\r
+ /* If this is the task that holds the mutex then pxMutexHolder will not\r
+ change outside of this task. If this task does not hold the mutex then\r
+ pxMutexHolder can never coincidentally equal the tasks handle, and as\r
+ this is the only condition we are interested in it does not matter if\r
+ pxMutexHolder is accessed simultaneously by another task. Therefore no\r
+ mutual exclusion is required to test the pxMutexHolder variable. */\r
+ if( pxMutex->pxMutexHolder == xTaskGetCurrentTaskHandle() )\r
+ {\r
+ traceGIVE_MUTEX_RECURSIVE( pxMutex );\r
+\r
+ /* uxRecursiveCallCount cannot be zero if pxMutexHolder is equal to\r
+ the task handle, therefore no underflow check is required. Also,\r
+ uxRecursiveCallCount is only modified by the mutex holder, and as\r
+ there can only be one, no mutual exclusion is required to modify the\r
+ uxRecursiveCallCount member. */\r
+ ( pxMutex->uxRecursiveCallCount )--;\r
+\r
+ /* Have we unwound the call count? */\r
+ if( pxMutex->uxRecursiveCallCount == 0 )\r
+ {\r
+ /* Return the mutex. This will automatically unblock any other\r
+ task that might be waiting to access the mutex. */\r
+ xQueueGenericSend( pxMutex, NULL, queueMUTEX_GIVE_BLOCK_TIME, queueSEND_TO_BACK );\r
+ }\r
+\r
+ xReturn = pdPASS;\r
+ }\r
+ else\r
+ {\r
+ /* We cannot give the mutex because we are not the holder. */\r
+ xReturn = pdFAIL;\r
+\r
+ traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex );\r
+ }\r
+\r
+ return xReturn;\r
+ }\r
+\r
+#endif /* configUSE_RECURSIVE_MUTEXES */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if configUSE_RECURSIVE_MUTEXES == 1\r
+\r
+ portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle pxMutex, portTickType xBlockTime )\r
+ {\r
+ portBASE_TYPE xReturn;\r
+\r
+ configASSERT( pxMutex );\r
+\r
+ /* Comments regarding mutual exclusion as per those within\r
+ xQueueGiveMutexRecursive(). */\r
+\r
+ traceTAKE_MUTEX_RECURSIVE( pxMutex );\r
+\r
+ if( pxMutex->pxMutexHolder == xTaskGetCurrentTaskHandle() )\r
+ {\r
+ ( pxMutex->uxRecursiveCallCount )++;\r
+ xReturn = pdPASS;\r
+ }\r
+ else\r
+ {\r
+ xReturn = xQueueGenericReceive( pxMutex, NULL, xBlockTime, pdFALSE );\r
+\r
+ /* pdPASS will only be returned if we successfully obtained the mutex,\r
+ we may have blocked to reach here. */\r
+ if( xReturn == pdPASS )\r
+ {\r
+ ( pxMutex->uxRecursiveCallCount )++;\r
+ }\r
+ else\r
+ {\r
+ traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex );\r
+ }\r
+ }\r
+\r
+ return xReturn;\r
+ }\r
+\r
+#endif /* configUSE_RECURSIVE_MUTEXES */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if configUSE_COUNTING_SEMAPHORES == 1\r
+\r
+ xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount )\r
+ {\r
+ xQueueHandle pxHandle;\r
+\r
+ pxHandle = xQueueGenericCreate( ( unsigned portBASE_TYPE ) uxCountValue, queueSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_COUNTING_SEMAPHORE );\r
+\r
+ if( pxHandle != NULL )\r
+ {\r
+ pxHandle->uxMessagesWaiting = uxInitialCount;\r
+\r
+ traceCREATE_COUNTING_SEMAPHORE();\r
+ }\r
+ else\r
+ {\r
+ traceCREATE_COUNTING_SEMAPHORE_FAILED();\r
+ }\r
+\r
+ configASSERT( pxHandle );\r
+ return pxHandle;\r
+ }\r
+\r
+#endif /* configUSE_COUNTING_SEMAPHORES */\r
+/*-----------------------------------------------------------*/\r
+\r
signed portBASE_TYPE xQueueGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )\r
{\r
-signed portBASE_TYPE xReturn = pdPASS;\r
+signed portBASE_TYPE xEntryTimeSet = pdFALSE;\r
xTimeOutType xTimeOut;\r
\r
- /* Make sure other tasks do not access the queue. */\r
- vTaskSuspendAll();\r
-\r
- /* Capture the current time status for future reference. */\r
- vTaskSetTimeOutState( &xTimeOut );\r
-\r
- /* It is important that this is the only thread/ISR that modifies the\r
- ready or delayed lists until xTaskResumeAll() is called. Places where\r
- the ready/delayed lists are modified include:\r
-\r
- + vTaskDelay() - Nothing can call vTaskDelay as the scheduler is\r
- suspended, vTaskDelay() cannot be called from an ISR.\r
- + vTaskPrioritySet() - Has a critical section around the access.\r
- + vTaskSwitchContext() - This will not get executed while the scheduler\r
- is suspended.\r
- + prvCheckDelayedTasks() - This will not get executed while the\r
- scheduler is suspended.\r
- + xTaskCreate() - Has a critical section around the access.\r
- + vTaskResume() - Has a critical section around the access.\r
- + xTaskResumeAll() - Has a critical section around the access.\r
- + xTaskRemoveFromEventList - Checks to see if the scheduler is\r
- suspended. If so then the TCB being removed from the event is\r
- removed from the event and added to the xPendingReadyList.\r
- */\r
-\r
- /* Make sure interrupts do not access the queue event list. */\r
- prvLockQueue( pxQueue );\r
-\r
- /* It is important that interrupts to not access the event list of the\r
- queue being modified here. Places where the event list is modified\r
- include:\r
-\r
- + xQueueGenericSendFromISR(). This checks the lock on the queue to see\r
- if it has access. If the queue is locked then the Tx lock count is\r
- incremented to signify that a task waiting for data can be made ready\r
- once the queue lock is removed. If the queue is not locked then\r
- a task can be moved from the event list, but will not be removed\r
- from the delayed list or placed in the ready list until the scheduler\r
- is unlocked.\r
-\r
- + xQueueReceiveFromISR(). As per xQueueGenericSendFromISR().\r
- */\r
- \r
- /* If the queue is already full we may have to block. */\r
- do\r
+ configASSERT( pxQueue );\r
+ configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );\r
+\r
+ /* This function relaxes the coding standard somewhat to allow return\r
+ statements within the function itself. This is done in the interest\r
+ of execution time efficiency. */\r
+ for( ;; )\r
{\r
- if( prvIsQueueFull( pxQueue ) )\r
+ taskENTER_CRITICAL();\r
{\r
- /* The queue is full - do we want to block or just leave without\r
- posting? */\r
- if( xTicksToWait > ( portTickType ) 0 )\r
+ /* Is there room on the queue now? To be running we must be\r
+ the highest priority task wanting to access the queue. */\r
+ if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )\r
{\r
- /* We are going to place ourselves on the xTasksWaitingToSend event\r
- list, and will get woken should the delay expire, or space become\r
- available on the queue.\r
- \r
- As detailed above we do not require mutual exclusion on the event\r
- list as nothing else can modify it or the ready lists while we\r
- have the scheduler suspended and queue locked.\r
- \r
- It is possible that an ISR has removed data from the queue since we\r
- checked if any was available. If this is the case then the data\r
- will have been copied from the queue, and the queue variables\r
- updated, but the event list will not yet have been checked to see if\r
- anything is waiting as the queue is locked. */\r
- vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );\r
- \r
- /* Force a context switch now as we are blocked. We can do\r
- this from within a critical section as the task we are\r
- switching to has its own context. When we return here (i.e. we\r
- unblock) we will leave the critical section as normal.\r
- \r
- It is possible that an ISR has caused an event on an unrelated and\r
- unlocked queue. If this was the case then the event list for that\r
- queue will have been updated but the ready lists left unchanged -\r
- instead the readied task will have been added to the pending ready\r
- list. */\r
- taskENTER_CRITICAL();\r
- {\r
- /* We can safely unlock the queue and scheduler here as\r
- interrupts are disabled. We must not yield with anything\r
- locked, but we can yield from within a critical section.\r
- \r
- Tasks that have been placed on the pending ready list cannot\r
- be tasks that are waiting for events on this queue. See\r
- in comment xTaskRemoveFromEventList(). */\r
- prvUnlockQueue( pxQueue );\r
- \r
- /* Resuming the scheduler may cause a yield. If so then there\r
- is no point yielding again here. */\r
- if( !xTaskResumeAll() )\r
- {\r
- taskYIELD();\r
- }\r
+ traceQUEUE_SEND( pxQueue );\r
+ prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );\r
\r
- /* We want to check to see if the queue is still full\r
- before leaving the critical section. This is to prevent\r
- this task placing an item into the queue due to an\r
- interrupt making space on the queue between critical\r
- sections (when there might be a higher priority task\r
- blocked on the queue that cannot run yet because the\r
- scheduler gets suspended). */\r
- if( pxQueue->uxMessagesWaiting == pxQueue->uxLength )\r
+ /* If there was a task waiting for data to arrive on the\r
+ queue then unblock it now. */\r
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
+ {\r
+ if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )\r
{\r
- /* We unblocked but there is no space in the queue,\r
- we probably timed out. */\r
- xReturn = errQUEUE_FULL;\r
+ /* The unblocked task has a priority higher than\r
+ our own so yield immediately. Yes it is ok to do\r
+ this from within the critical section - the kernel\r
+ takes care of that. */\r
+ portYIELD_WITHIN_API();\r
}\r
- \r
- /* Before leaving the critical section we have to ensure\r
- exclusive access again. */\r
- vTaskSuspendAll();\r
- prvLockQueue( pxQueue ); \r
}\r
+\r
taskEXIT_CRITICAL();\r
+\r
+ /* Return to the original privilege level before exiting the\r
+ function. */\r
+ return pdPASS;\r
+ }\r
+ else\r
+ {\r
+ if( xTicksToWait == ( portTickType ) 0 )\r
+ {\r
+ /* The queue was full and no block time is specified (or\r
+ the block time has expired) so leave now. */\r
+ taskEXIT_CRITICAL();\r
+\r
+ /* Return to the original privilege level before exiting\r
+ the function. */\r
+ traceQUEUE_SEND_FAILED( pxQueue );\r
+ return errQUEUE_FULL;\r
+ }\r
+ else if( xEntryTimeSet == pdFALSE )\r
+ {\r
+ /* The queue was full and a block time was specified so\r
+ configure the timeout structure. */\r
+ vTaskSetTimeOutState( &xTimeOut );\r
+ xEntryTimeSet = pdTRUE;\r
+ }\r
}\r
}\r
- \r
- /* If xReturn is errQUEUE_FULL then we unblocked when the queue\r
- was still full. Don't check it again now as it is possible that\r
- an interrupt has removed an item from the queue since we left the\r
- critical section and we don't want to write to the queue in case\r
- there is a task of higher priority blocked waiting for space to\r
- be available on the queue. If this is the case the higher priority\r
- task will execute when the scheduler is unsupended. */\r
- if( xReturn != errQUEUE_FULL )\r
+ taskEXIT_CRITICAL();\r
+\r
+ /* Interrupts and other tasks can send to and receive from the queue\r
+ now the critical section has been exited. */\r
+\r
+ vTaskSuspendAll();\r
+ prvLockQueue( pxQueue );\r
+\r
+ /* Update the timeout state to see if it has expired yet. */\r
+ if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
+ {\r
+ if( prvIsQueueFull( pxQueue ) != pdFALSE )\r
+ {\r
+ traceBLOCKING_ON_QUEUE_SEND( pxQueue );\r
+ vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );\r
+\r
+ /* Unlocking the queue means queue events can effect the\r
+ event list. It is possible that interrupts occurring now\r
+ remove this task from the event list again - but as the\r
+ scheduler is suspended the task will go onto the pending\r
+ ready last instead of the actual ready list. */\r
+ prvUnlockQueue( pxQueue );\r
+\r
+ /* Resuming the scheduler will move tasks from the pending\r
+ ready list into the ready list - so it is feasible that this\r
+ task is already in a ready list before it yields - in which\r
+ case the yield will not cause a context switch unless there\r
+ is also a higher priority task in the pending ready list. */\r
+ if( xTaskResumeAll() == pdFALSE )\r
+ {\r
+ portYIELD_WITHIN_API();\r
+ }\r
+ }\r
+ else\r
+ {\r
+ /* Try again. */\r
+ prvUnlockQueue( pxQueue );\r
+ ( void ) xTaskResumeAll();\r
+ }\r
+ }\r
+ else\r
+ {\r
+ /* The timeout has expired. */\r
+ prvUnlockQueue( pxQueue );\r
+ ( void ) xTaskResumeAll();\r
+\r
+ /* Return to the original privilege level before exiting the\r
+ function. */\r
+ traceQUEUE_SEND_FAILED( pxQueue );\r
+ return errQUEUE_FULL;\r
+ }\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+#if configUSE_ALTERNATIVE_API == 1\r
+\r
+ signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )\r
+ {\r
+ signed portBASE_TYPE xEntryTimeSet = pdFALSE;\r
+ xTimeOutType xTimeOut;\r
+\r
+ configASSERT( pxQueue );\r
+ configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );\r
+\r
+ for( ;; )\r
{\r
- /* When we are here it is possible that we unblocked as space became\r
- available on the queue. It is also possible that an ISR posted to the\r
- queue since we left the critical section, so it may be that again there\r
- is no space. This would only happen if a task and ISR post onto the\r
- same queue. */\r
taskENTER_CRITICAL();\r
{\r
+ /* Is there room on the queue now? To be running we must be\r
+ the highest priority task wanting to access the queue. */\r
if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )\r
{\r
- /* There is room in the queue, copy the data into the queue. */ \r
+ traceQUEUE_SEND( pxQueue );\r
prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );\r
- xReturn = pdPASS;\r
- \r
- /* Update the TxLock count so prvUnlockQueue knows to check for\r
- tasks waiting for data to become available in the queue. */\r
- ++( pxQueue->xTxLock );\r
+\r
+ /* If there was a task waiting for data to arrive on the\r
+ queue then unblock it now. */\r
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
+ {\r
+ if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )\r
+ {\r
+ /* The unblocked task has a priority higher than\r
+ our own so yield immediately. */\r
+ portYIELD_WITHIN_API();\r
+ }\r
+ }\r
+\r
+ taskEXIT_CRITICAL();\r
+ return pdPASS;\r
+ }\r
+ else\r
+ {\r
+ if( xTicksToWait == ( portTickType ) 0 )\r
+ {\r
+ taskEXIT_CRITICAL();\r
+ return errQUEUE_FULL;\r
+ }\r
+ else if( xEntryTimeSet == pdFALSE )\r
+ {\r
+ vTaskSetTimeOutState( &xTimeOut );\r
+ xEntryTimeSet = pdTRUE;\r
+ }\r
+ }\r
+ }\r
+ taskEXIT_CRITICAL();\r
+\r
+ taskENTER_CRITICAL();\r
+ {\r
+ if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
+ {\r
+ if( prvIsQueueFull( pxQueue ) != pdFALSE )\r
+ {\r
+ traceBLOCKING_ON_QUEUE_SEND( pxQueue );\r
+ vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );\r
+ portYIELD_WITHIN_API();\r
+ }\r
}\r
else\r
{\r
- xReturn = errQUEUE_FULL;\r
+ taskEXIT_CRITICAL();\r
+ traceQUEUE_SEND_FAILED( pxQueue );\r
+ return errQUEUE_FULL;\r
}\r
}\r
taskEXIT_CRITICAL();\r
}\r
+ }\r
\r
- if( xReturn == errQUEUE_FULL )\r
+#endif /* configUSE_ALTERNATIVE_API */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if configUSE_ALTERNATIVE_API == 1\r
+\r
+ signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )\r
+ {\r
+ signed portBASE_TYPE xEntryTimeSet = pdFALSE;\r
+ xTimeOutType xTimeOut;\r
+ signed char *pcOriginalReadPosition;\r
+\r
+ configASSERT( pxQueue );\r
+ configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );\r
+\r
+ for( ;; )\r
{\r
- if( xTicksToWait > 0 )\r
+ taskENTER_CRITICAL();\r
+ {\r
+ if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )\r
+ {\r
+ /* Remember our read position in case we are just peeking. */\r
+ pcOriginalReadPosition = pxQueue->pcReadFrom;\r
+\r
+ prvCopyDataFromQueue( pxQueue, pvBuffer );\r
+\r
+ if( xJustPeeking == pdFALSE )\r
+ {\r
+ traceQUEUE_RECEIVE( pxQueue );\r
+\r
+ /* We are actually removing data. */\r
+ --( pxQueue->uxMessagesWaiting );\r
+\r
+ #if ( configUSE_MUTEXES == 1 )\r
+ {\r
+ if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )\r
+ {\r
+ /* Record the information required to implement\r
+ priority inheritance should it become necessary. */\r
+ pxQueue->pxMutexHolder = xTaskGetCurrentTaskHandle();\r
+ }\r
+ }\r
+ #endif\r
+\r
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )\r
+ {\r
+ if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )\r
+ {\r
+ portYIELD_WITHIN_API();\r
+ }\r
+ }\r
+ }\r
+ else\r
+ {\r
+ traceQUEUE_PEEK( pxQueue );\r
+\r
+ /* We are not removing the data, so reset our read\r
+ pointer. */\r
+ pxQueue->pcReadFrom = pcOriginalReadPosition;\r
+\r
+ /* The data is being left in the queue, so see if there are\r
+ any other tasks waiting for the data. */\r
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
+ {\r
+ /* Tasks that are removed from the event list will get added to\r
+ the pending ready list as the scheduler is still suspended. */\r
+ if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
+ {\r
+ /* The task waiting has a higher priority than this task. */\r
+ portYIELD_WITHIN_API();\r
+ }\r
+ }\r
+\r
+ }\r
+\r
+ taskEXIT_CRITICAL();\r
+ return pdPASS;\r
+ }\r
+ else\r
+ {\r
+ if( xTicksToWait == ( portTickType ) 0 )\r
+ {\r
+ taskEXIT_CRITICAL();\r
+ traceQUEUE_RECEIVE_FAILED( pxQueue );\r
+ return errQUEUE_EMPTY;\r
+ }\r
+ else if( xEntryTimeSet == pdFALSE )\r
+ {\r
+ vTaskSetTimeOutState( &xTimeOut );\r
+ xEntryTimeSet = pdTRUE;\r
+ }\r
+ }\r
+ }\r
+ taskEXIT_CRITICAL();\r
+\r
+ taskENTER_CRITICAL();\r
{\r
if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
{\r
- xReturn = queueERRONEOUS_UNBLOCK;\r
+ if( prvIsQueueEmpty( pxQueue ) != pdFALSE )\r
+ {\r
+ traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );\r
+\r
+ #if ( configUSE_MUTEXES == 1 )\r
+ {\r
+ if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )\r
+ {\r
+ portENTER_CRITICAL();\r
+ vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );\r
+ portEXIT_CRITICAL();\r
+ }\r
+ }\r
+ #endif\r
+\r
+ vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );\r
+ portYIELD_WITHIN_API();\r
+ }\r
+ }\r
+ else\r
+ {\r
+ taskEXIT_CRITICAL();\r
+ traceQUEUE_RECEIVE_FAILED( pxQueue );\r
+ return errQUEUE_EMPTY;\r
}\r
}\r
+ taskEXIT_CRITICAL();\r
}\r
}\r
- while( xReturn == queueERRONEOUS_UNBLOCK );\r
\r
- prvUnlockQueue( pxQueue );\r
- xTaskResumeAll();\r
\r
- return xReturn;\r
-}\r
+#endif /* configUSE_ALTERNATIVE_API */\r
/*-----------------------------------------------------------*/\r
\r
-signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE xTaskPreviouslyWoken, portBASE_TYPE xCopyPosition )\r
+signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition )\r
{\r
+signed portBASE_TYPE xReturn;\r
+unsigned portBASE_TYPE uxSavedInterruptStatus;\r
+\r
+ configASSERT( pxQueue );\r
+ configASSERT( pxHigherPriorityTaskWoken );\r
+ configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );\r
+\r
/* Similar to xQueueGenericSend, except we don't block if there is no room\r
in the queue. Also we don't directly wake a task that was blocked on a\r
queue read, instead we return a flag to say whether a context switch is\r
required or not (i.e. has a task with a higher priority than us been woken\r
by this post). */\r
- if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )\r
+ uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();\r
{\r
- prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );\r
-\r
- /* If the queue is locked we do not alter the event list. This will\r
- be done when the queue is unlocked later. */\r
- if( pxQueue->xTxLock == queueUNLOCKED )\r
+ if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )\r
{\r
- /* We only want to wake one task per ISR, so check that a task has\r
- not already been woken. */\r
- if( !xTaskPreviouslyWoken ) \r
+ traceQUEUE_SEND_FROM_ISR( pxQueue );\r
+\r
+ prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );\r
+\r
+ /* If the queue is locked we do not alter the event list. This will\r
+ be done when the queue is unlocked later. */\r
+ if( pxQueue->xTxLock == queueUNLOCKED )\r
{\r
- if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )\r
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
{\r
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
{\r
/* The task waiting has a higher priority so record that a\r
context switch is required. */\r
- return pdTRUE;\r
+ *pxHigherPriorityTaskWoken = pdTRUE;\r
}\r
}\r
}\r
+ else\r
+ {\r
+ /* Increment the lock count so the task that unlocks the queue\r
+ knows that data was posted while it was locked. */\r
+ ++( pxQueue->xTxLock );\r
+ }\r
+\r
+ xReturn = pdPASS;\r
}\r
else\r
{\r
- /* Increment the lock count so the task that unlocks the queue\r
- knows that data was posted while it was locked. */\r
- ++( pxQueue->xTxLock );\r
+ traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue );\r
+ xReturn = errQUEUE_FULL;\r
}\r
}\r
+ portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );\r
\r
- return xTaskPreviouslyWoken;\r
+ return xReturn;\r
}\r
/*-----------------------------------------------------------*/\r
\r
signed portBASE_TYPE xQueueGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )\r
{\r
-signed portBASE_TYPE xReturn = pdTRUE;\r
+signed portBASE_TYPE xEntryTimeSet = pdFALSE;\r
xTimeOutType xTimeOut;\r
-signed portCHAR *pcOriginalReadPosition;\r
-\r
- /* This function is very similar to xQueueGenericSend(). See comments\r
- within xQueueGenericSend() for a more detailed explanation.\r
-\r
- Make sure other tasks do not access the queue. */\r
- vTaskSuspendAll();\r
+signed char *pcOriginalReadPosition;\r
\r
- /* Capture the current time status for future reference. */\r
- vTaskSetTimeOutState( &xTimeOut );\r
+ configASSERT( pxQueue );\r
+ configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );\r
\r
- /* Make sure interrupts do not access the queue. */\r
- prvLockQueue( pxQueue );\r
+ /* This function relaxes the coding standard somewhat to allow return\r
+ statements within the function itself. This is done in the interest\r
+ of execution time efficiency. */\r
\r
- do\r
+ for( ;; )\r
{\r
- /* If there are no messages in the queue we may have to block. */\r
- if( prvIsQueueEmpty( pxQueue ) )\r
+ taskENTER_CRITICAL();\r
{\r
- /* There are no messages in the queue, do we want to block or just\r
- leave with nothing? */ \r
- if( xTicksToWait > ( portTickType ) 0 )\r
+ /* Is there data in the queue now? To be running we must be\r
+ the highest priority task wanting to access the queue. */\r
+ if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )\r
{\r
- #if ( configUSE_MUTEXES == 1 )\r
- {\r
- if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )\r
- {\r
- portENTER_CRITICAL();\r
- vTaskPriorityInherit( ( void * const ) pxQueue->pxMutexHolder );\r
- portEXIT_CRITICAL();\r
- }\r
- }\r
- #endif\r
- \r
- vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );\r
- taskENTER_CRITICAL();\r
+ /* Remember our read position in case we are just peeking. */\r
+ pcOriginalReadPosition = pxQueue->pcReadFrom;\r
+\r
+ prvCopyDataFromQueue( pxQueue, pvBuffer );\r
+\r
+ if( xJustPeeking == pdFALSE )\r
{\r
- prvUnlockQueue( pxQueue );\r
- if( !xTaskResumeAll() )\r
+ traceQUEUE_RECEIVE( pxQueue );\r
+\r
+ /* We are actually removing data. */\r
+ --( pxQueue->uxMessagesWaiting );\r
+\r
+ #if ( configUSE_MUTEXES == 1 )\r
{\r
- taskYIELD();\r
+ if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )\r
+ {\r
+ /* Record the information required to implement\r
+ priority inheritance should it become necessary. */\r
+ pxQueue->pxMutexHolder = xTaskGetCurrentTaskHandle();\r
+ }\r
}\r
+ #endif\r
\r
- if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 )\r
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )\r
{\r
- /* We unblocked but the queue is empty. We probably\r
- timed out. */\r
- xReturn = errQUEUE_EMPTY;\r
+ if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )\r
+ {\r
+ portYIELD_WITHIN_API();\r
+ }\r
}\r
- \r
- vTaskSuspendAll();\r
- prvLockQueue( pxQueue );\r
}\r
- taskEXIT_CRITICAL();\r
- }\r
- }\r
- \r
- if( xReturn != errQUEUE_EMPTY )\r
- {\r
- taskENTER_CRITICAL();\r
- {\r
- if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )\r
+ else\r
{\r
- /* Remember our read position in case we are just peeking. */\r
- pcOriginalReadPosition = pxQueue->pcReadFrom;\r
+ traceQUEUE_PEEK( pxQueue );\r
\r
- prvCopyDataFromQueue( pxQueue, pvBuffer );\r
+ /* We are not removing the data, so reset our read\r
+ pointer. */\r
+ pxQueue->pcReadFrom = pcOriginalReadPosition;\r
\r
- if( xJustPeeking == pdFALSE )\r
+ /* The data is being left in the queue, so see if there are\r
+ any other tasks waiting for the data. */\r
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
{\r
- /* We are actually removing data. */\r
- --( pxQueue->uxMessagesWaiting );\r
- \r
- /* Increment the lock count so prvUnlockQueue knows to check for\r
- tasks waiting for space to become available on the queue. */\r
- ++( pxQueue->xRxLock );\r
- \r
- #if ( configUSE_MUTEXES == 1 )\r
+ /* Tasks that are removed from the event list will get added to\r
+ the pending ready list as the scheduler is still suspended. */\r
+ if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
{\r
- if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )\r
- {\r
- /* Record the information required to implement\r
- priority inheritance should it become necessary. */\r
- pxQueue->pxMutexHolder = xTaskGetCurrentTaskHandle();\r
- }\r
+ /* The task waiting has a higher priority than this task. */\r
+ portYIELD_WITHIN_API();\r
}\r
- #endif\r
- }\r
- else\r
- {\r
- /* We are not removing the data, so reset our read\r
- pointer. */\r
- pxQueue->pcReadFrom = pcOriginalReadPosition; \r
}\r
- \r
- xReturn = pdPASS; \r
+\r
}\r
- else\r
+\r
+ taskEXIT_CRITICAL();\r
+ return pdPASS;\r
+ }\r
+ else\r
+ {\r
+ if( xTicksToWait == ( portTickType ) 0 )\r
{\r
- xReturn = errQUEUE_EMPTY;\r
+ /* The queue was empty and no block time is specified (or\r
+ the block time has expired) so leave now. */\r
+ taskEXIT_CRITICAL();\r
+ traceQUEUE_RECEIVE_FAILED( pxQueue );\r
+ return errQUEUE_EMPTY;\r
+ }\r
+ else if( xEntryTimeSet == pdFALSE )\r
+ {\r
+ /* The queue was empty and a block time was specified so\r
+ configure the timeout structure. */\r
+ vTaskSetTimeOutState( &xTimeOut );\r
+ xEntryTimeSet = pdTRUE;\r
}\r
}\r
- taskEXIT_CRITICAL();\r
}\r
+ taskEXIT_CRITICAL();\r
+\r
+ /* Interrupts and other tasks can send to and receive from the queue\r
+ now the critical section has been exited. */\r
\r
- if( xReturn == errQUEUE_EMPTY )\r
+ vTaskSuspendAll();\r
+ prvLockQueue( pxQueue );\r
+\r
+ /* Update the timeout state to see if it has expired yet. */\r
+ if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
{\r
- if( xTicksToWait > 0 )\r
+ if( prvIsQueueEmpty( pxQueue ) != pdFALSE )\r
{\r
- if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
+ traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );\r
+\r
+ #if ( configUSE_MUTEXES == 1 )\r
{\r
- xReturn = queueERRONEOUS_UNBLOCK;\r
+ if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )\r
+ {\r
+ portENTER_CRITICAL();\r
+ {\r
+ vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );\r
+ }\r
+ portEXIT_CRITICAL();\r
+ }\r
+ }\r
+ #endif\r
+\r
+ vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );\r
+ prvUnlockQueue( pxQueue );\r
+ if( xTaskResumeAll() == pdFALSE )\r
+ {\r
+ portYIELD_WITHIN_API();\r
}\r
}\r
+ else\r
+ {\r
+ /* Try again. */\r
+ prvUnlockQueue( pxQueue );\r
+ ( void ) xTaskResumeAll();\r
+ }\r
}\r
- } while( xReturn == queueERRONEOUS_UNBLOCK );\r
-\r
- /* We no longer require exclusive access to the queue. */\r
- prvUnlockQueue( pxQueue );\r
- xTaskResumeAll();\r
-\r
- return xReturn;\r
+ else\r
+ {\r
+ prvUnlockQueue( pxQueue );\r
+ ( void ) xTaskResumeAll();\r
+ traceQUEUE_RECEIVE_FAILED( pxQueue );\r
+ return errQUEUE_EMPTY;\r
+ }\r
+ }\r
}\r
/*-----------------------------------------------------------*/\r
\r
signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken )\r
{\r
signed portBASE_TYPE xReturn;\r
+unsigned portBASE_TYPE uxSavedInterruptStatus;\r
\r
- /* We cannot block from an ISR, so check there is data available. */\r
- if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )\r
- {\r
- prvCopyDataFromQueue( pxQueue, pvBuffer );\r
- --( pxQueue->uxMessagesWaiting );\r
+ configASSERT( pxQueue );\r
+ configASSERT( pxTaskWoken );\r
+ configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );\r
\r
- /* If the queue is locked we will not modify the event list. Instead\r
- we update the lock count so the task that unlocks the queue will know\r
- that an ISR has removed data while the queue was locked. */\r
- if( pxQueue->xRxLock == queueUNLOCKED )\r
+ uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();\r
+ {\r
+ /* We cannot block from an ISR, so check there is data available. */\r
+ if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )\r
{\r
- /* We only want to wake one task per ISR, so check that a task has\r
- not already been woken. */\r
- if( !( *pxTaskWoken ) )\r
+ traceQUEUE_RECEIVE_FROM_ISR( pxQueue );\r
+\r
+ prvCopyDataFromQueue( pxQueue, pvBuffer );\r
+ --( pxQueue->uxMessagesWaiting );\r
+\r
+ /* If the queue is locked we will not modify the event list. Instead\r
+ we update the lock count so the task that unlocks the queue will know\r
+ that an ISR has removed data while the queue was locked. */\r
+ if( pxQueue->xRxLock == queueUNLOCKED )\r
{\r
- if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) )\r
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )\r
{\r
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )\r
{\r
}\r
}\r
}\r
+ else\r
+ {\r
+ /* Increment the lock count so the task that unlocks the queue\r
+ knows that data was removed while it was locked. */\r
+ ++( pxQueue->xRxLock );\r
+ }\r
+\r
+ xReturn = pdPASS;\r
}\r
else\r
{\r
- /* Increment the lock count so the task that unlocks the queue\r
- knows that data was removed while it was locked. */\r
- ++( pxQueue->xRxLock );\r
+ xReturn = pdFAIL;\r
+ traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue );\r
}\r
-\r
- xReturn = pdPASS;\r
- }\r
- else\r
- {\r
- xReturn = pdFAIL;\r
}\r
+ portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );\r
\r
return xReturn;\r
}\r
/*-----------------------------------------------------------*/\r
\r
-unsigned portBASE_TYPE uxQueueMessagesWaiting( xQueueHandle pxQueue )\r
+unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle pxQueue )\r
{\r
unsigned portBASE_TYPE uxReturn;\r
\r
+ configASSERT( pxQueue );\r
+\r
taskENTER_CRITICAL();\r
uxReturn = pxQueue->uxMessagesWaiting;\r
taskEXIT_CRITICAL();\r
}\r
/*-----------------------------------------------------------*/\r
\r
+unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle pxQueue )\r
+{\r
+unsigned portBASE_TYPE uxReturn;\r
+\r
+ configASSERT( pxQueue );\r
+\r
+ uxReturn = pxQueue->uxMessagesWaiting;\r
+\r
+ return uxReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
void vQueueDelete( xQueueHandle pxQueue )\r
{\r
+ configASSERT( pxQueue );\r
+\r
+ traceQUEUE_DELETE( pxQueue );\r
+ vQueueUnregisterQueue( pxQueue );\r
vPortFree( pxQueue->pcHead );\r
vPortFree( pxQueue );\r
}\r
/*-----------------------------------------------------------*/\r
\r
+#if ( configUSE_TRACE_FACILITY == 1 )\r
+\r
+ unsigned char ucQueueGetQueueNumber( xQueueHandle pxQueue )\r
+ {\r
+ return pxQueue->ucQueueNumber;\r
+ }\r
+\r
+#endif\r
+/*-----------------------------------------------------------*/\r
+\r
+#if ( configUSE_TRACE_FACILITY == 1 )\r
+\r
+ void vQueueSetQueueNumber( xQueueHandle pxQueue, unsigned char ucQueueNumber )\r
+ {\r
+ pxQueue->ucQueueNumber = ucQueueNumber;\r
+ }\r
+\r
+#endif\r
+/*-----------------------------------------------------------*/\r
+\r
+#if ( configUSE_TRACE_FACILITY == 1 )\r
+\r
+ unsigned char ucQueueGetQueueType( xQueueHandle pxQueue )\r
+ {\r
+ return pxQueue->ucQueueType;\r
+ }\r
+\r
+#endif\r
+/*-----------------------------------------------------------*/\r
+\r
static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition )\r
{\r
- if( pxQueue->uxItemSize == 0 )\r
+ if( pxQueue->uxItemSize == ( unsigned portBASE_TYPE ) 0 )\r
{\r
#if ( configUSE_MUTEXES == 1 )\r
{\r
if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )\r
{\r
/* The mutex is no longer being held. */\r
- vTaskPriorityDisinherit( ( void * const ) pxQueue->pxMutexHolder );\r
+ vTaskPriorityDisinherit( ( void * ) pxQueue->pxMutexHolder );\r
+ pxQueue->pxMutexHolder = NULL;\r
}\r
}\r
#endif\r
if( pxQueue->pcReadFrom < pxQueue->pcHead )\r
{\r
pxQueue->pcReadFrom = ( pxQueue->pcTail - pxQueue->uxItemSize );\r
- } \r
+ }\r
}\r
\r
++( pxQueue->uxMessagesWaiting );\r
pxQueue->pcReadFrom = pxQueue->pcHead;\r
}\r
memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );\r
- } \r
+ }\r
}\r
/*-----------------------------------------------------------*/\r
\r
updated. */\r
taskENTER_CRITICAL();\r
{\r
- --( pxQueue->xTxLock );\r
-\r
/* See if data was added to the queue while it was locked. */\r
- if( pxQueue->xTxLock > queueUNLOCKED )\r
+ while( pxQueue->xTxLock > queueLOCKED_UNMODIFIED )\r
{\r
- pxQueue->xTxLock = queueUNLOCKED;\r
-\r
/* Data was posted while the queue was locked. Are any tasks\r
blocked waiting for data to become available? */\r
- if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )\r
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
{\r
/* Tasks that are removed from the event list will get added to\r
the pending ready list as the scheduler is still suspended. */\r
context switch is required. */\r
vTaskMissedYield();\r
}\r
- } \r
+\r
+ --( pxQueue->xTxLock );\r
+ }\r
+ else\r
+ {\r
+ break;\r
+ }\r
}\r
+\r
+ pxQueue->xTxLock = queueUNLOCKED;\r
}\r
taskEXIT_CRITICAL();\r
\r
/* Do the same for the Rx lock. */\r
taskENTER_CRITICAL();\r
{\r
- --( pxQueue->xRxLock );\r
-\r
- if( pxQueue->xRxLock > queueUNLOCKED )\r
+ while( pxQueue->xRxLock > queueLOCKED_UNMODIFIED )\r
{\r
- pxQueue->xRxLock = queueUNLOCKED;\r
-\r
- if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) )\r
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )\r
{\r
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )\r
{\r
vTaskMissedYield();\r
}\r
- } \r
+\r
+ --( pxQueue->xRxLock );\r
+ }\r
+ else\r
+ {\r
+ break;\r
+ }\r
}\r
+\r
+ pxQueue->xRxLock = queueUNLOCKED;\r
}\r
taskEXIT_CRITICAL();\r
}\r
}\r
/*-----------------------------------------------------------*/\r
\r
+signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle pxQueue )\r
+{\r
+signed portBASE_TYPE xReturn;\r
+\r
+ configASSERT( pxQueue );\r
+ xReturn = ( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 );\r
+\r
+ return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
static signed portBASE_TYPE prvIsQueueFull( const xQueueHandle pxQueue )\r
{\r
signed portBASE_TYPE xReturn;\r
}\r
/*-----------------------------------------------------------*/\r
\r
+signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle pxQueue )\r
+{\r
+signed portBASE_TYPE xReturn;\r
+\r
+ configASSERT( pxQueue );\r
+ xReturn = ( pxQueue->uxMessagesWaiting == pxQueue->uxLength );\r
+\r
+ return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
#if configUSE_CO_ROUTINES == 1\r
signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait )\r
{\r
signed portBASE_TYPE xReturn;\r
- \r
+\r
/* If the queue is already full we may have to block. A critical section\r
is required to prevent an interrupt removing something from the queue\r
between the check to see if the queue is full and blocking on the queue. */\r
portDISABLE_INTERRUPTS();\r
{\r
- if( prvIsQueueFull( pxQueue ) )\r
+ if( prvIsQueueFull( pxQueue ) != pdFALSE )\r
{\r
/* The queue is full - do we want to block or just leave without\r
posting? */\r
{\r
/* As this is called from a coroutine we cannot block directly, but\r
return indicating that we need to block. */\r
- vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToSend ) ); \r
+ vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToSend ) );\r
portENABLE_INTERRUPTS();\r
return errQUEUE_BLOCKED;\r
}\r
}\r
}\r
portENABLE_INTERRUPTS();\r
- \r
+\r
portNOP();\r
\r
portDISABLE_INTERRUPTS();\r
{\r
if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )\r
{\r
- /* There is room in the queue, copy the data into the queue. */ \r
+ /* There is room in the queue, copy the data into the queue. */\r
prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );\r
xReturn = pdPASS;\r
\r
/* Were any co-routines waiting for data to become available? */\r
- if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )\r
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
{\r
/* In this instance the co-routine could be placed directly\r
into the ready list as we are within a critical section.\r
if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 )\r
{\r
/* There are no messages in the queue, do we want to block or just\r
- leave with nothing? */ \r
+ leave with nothing? */\r
if( xTicksToWait > ( portTickType ) 0 )\r
{\r
/* As this is a co-routine we cannot block directly, but return\r
xReturn = pdPASS;\r
\r
/* Were any co-routines waiting for space to become available? */\r
- if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) )\r
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )\r
{\r
/* In this instance the co-routine could be placed directly\r
into the ready list as we are within a critical section.\r
{\r
xReturn = errQUEUE_YIELD;\r
}\r
- } \r
+ }\r
}\r
else\r
{\r
\r
/* We only want to wake one co-routine per ISR, so check that a\r
co-routine has not already been woken. */\r
- if( !xCoRoutinePreviouslyWoken ) \r
+ if( xCoRoutinePreviouslyWoken == pdFALSE )\r
{\r
- if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )\r
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
{\r
if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
{\r
--( pxQueue->uxMessagesWaiting );\r
memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );\r
\r
- if( !( *pxCoRoutineWoken ) )\r
+ if( ( *pxCoRoutineWoken ) == pdFALSE )\r
{\r
- if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) )\r
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )\r
{\r
if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )\r
{\r
#endif\r
/*-----------------------------------------------------------*/\r
\r
+#if configQUEUE_REGISTRY_SIZE > 0\r
+\r
+ void vQueueAddToRegistry( xQueueHandle xQueue, signed char *pcQueueName )\r
+ {\r
+ unsigned portBASE_TYPE ux;\r
+\r
+ /* See if there is an empty space in the registry. A NULL name denotes\r
+ a free slot. */\r
+ for( ux = ( unsigned portBASE_TYPE ) 0U; ux < ( unsigned portBASE_TYPE ) configQUEUE_REGISTRY_SIZE; ux++ )\r
+ {\r
+ if( xQueueRegistry[ ux ].pcQueueName == NULL )\r
+ {\r
+ /* Store the information on this queue. */\r
+ xQueueRegistry[ ux ].pcQueueName = pcQueueName;\r
+ xQueueRegistry[ ux ].xHandle = xQueue;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+#endif\r
+/*-----------------------------------------------------------*/\r
+\r
+#if configQUEUE_REGISTRY_SIZE > 0\r
+\r
+ static void vQueueUnregisterQueue( xQueueHandle xQueue )\r
+ {\r
+ unsigned portBASE_TYPE ux;\r
+\r
+ /* See if the handle of the queue being unregistered in actually in the\r
+ registry. */\r
+ for( ux = ( unsigned portBASE_TYPE ) 0U; ux < ( unsigned portBASE_TYPE ) configQUEUE_REGISTRY_SIZE; ux++ )\r
+ {\r
+ if( xQueueRegistry[ ux ].xHandle == xQueue )\r
+ {\r
+ /* Set the name to NULL to show that this slot if free again. */\r
+ xQueueRegistry[ ux ].pcQueueName = NULL;\r
+ break;\r
+ }\r
+ }\r
+\r
+ }\r
+\r
+#endif\r
+/*-----------------------------------------------------------*/\r
+\r
+#if configUSE_TIMERS == 1\r
+\r
+ void vQueueWaitForMessageRestricted( xQueueHandle pxQueue, portTickType xTicksToWait )\r
+ {\r
+ /* This function should not be called by application code hence the\r
+ 'Restricted' in its name. It is not part of the public API. It is\r
+ designed for use by kernel code, and has special calling requirements.\r
+ It can result in vListInsert() being called on a list that can only\r
+ possibly ever have one item in it, so the list will be fast, but even\r
+ so it should be called with the scheduler locked and not from a critical\r
+ section. */\r
+\r
+ /* Only do anything if there are no messages in the queue. This function\r
+ will not actually cause the task to block, just place it on a blocked\r
+ list. It will not block until the scheduler is unlocked - at which\r
+ time a yield will be performed. If an item is added to the queue while\r
+ the queue is locked, and the calling task blocks on the queue, then the\r
+ calling task will be immediately unblocked when the queue is unlocked. */\r
+ prvLockQueue( pxQueue );\r
+ if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0U )\r
+ {\r
+ /* There is nothing in the queue, block for the specified period. */\r
+ vTaskPlaceOnEventListRestricted( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );\r
+ }\r
+ prvUnlockQueue( pxQueue );\r
+ }\r
+\r
+#endif\r
+\r