/*\r
- FreeRTOS.org V5.1.1 - Copyright (C) 2003-2008 Richard Barry.\r
+ FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.\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
***************************************************************************\r
* *\r
- * SAVE TIME AND MONEY! We can port FreeRTOS.org to your own hardware, *\r
- * and even write all or part of your application on your behalf. *\r
- * See http://www.OpenRTOS.com for details of the services we provide to *\r
- * expedite your project. *\r
+ * If you are: *\r
+ * *\r
+ * + New to FreeRTOS, *\r
+ * + Wanting to learn FreeRTOS or multitasking in general quickly *\r
+ * + Looking for basic training, *\r
+ * + Wanting to improve your FreeRTOS skills and productivity *\r
+ * *\r
+ * then take a look at the FreeRTOS eBook *\r
+ * *\r
+ * "Using the FreeRTOS Real Time Kernel - a Practical Guide" *\r
+ * http://www.FreeRTOS.org/Documentation *\r
+ * *\r
+ * A pdf reference manual is also available. Both are usually delivered *\r
+ * to your inbox within 20 minutes to two hours when purchased between 8am *\r
+ * and 8pm GMT (although please allow up to 24 hours in case of *\r
+ * exceptional circumstances). Thank you for your support! *\r
* *\r
***************************************************************************\r
- ***************************************************************************\r
-\r
- Please ensure to read the configuration and relevant port sections of the\r
- online documentation.\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
+ 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 exception to the GPL is included to allow you to distribute\r
+ a combined work that includes FreeRTOS without being obliged to provide the\r
+ source code for proprietary components outside of the FreeRTOS kernel.\r
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT\r
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
+ 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
+#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 queueLOCKED_UNMODIFIED ( ( signed portBASE_TYPE ) 0 )\r
+#define queueUNLOCKED ( ( signed portBASE_TYPE ) -1 )\r
+#define queueLOCKED_UNMODIFIED ( ( signed portBASE_TYPE ) 0 )\r
\r
-#define queueERRONEOUS_UNBLOCK ( -1 )\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 uxRecursiveCallCount pcReadFrom\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
*/\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
* 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( const xQueueHandle pxQueue );\r
-void vQueueDelete( xQueueHandle xQueue );\r
-signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, 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 xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount );\r
-portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle xMutex, portTickType xBlockTime );\r
-portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle xMutex );\r
-signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition );\r
-signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking );\r
-signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle pxQueue );\r
-signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle pxQueue );\r
-unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle pxQueue );\r
+xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize ) 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( void ) 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
\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
more user friendly. */\r
typedef struct QUEUE_REGISTRY_ITEM\r
{\r
- signed portCHAR *pcQueueName;\r
+ signed char *pcQueueName;\r
xQueueHandle xHandle;\r
} xQueueRegistryItem;\r
\r
\r
/* Removes a queue from the registry by simply setting the pcQueueName\r
member to NULL. */\r
- static void vQueueUnregisterQueue( xQueueHandle xQueue );\r
- void vQueueAddToRegistry( xQueueHandle xQueue, signed portCHAR *pcQueueName );\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
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
vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) );\r
\r
traceQUEUE_CREATE( pxNewQueue );\r
-\r
return pxNewQueue;\r
}\r
else\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
+ xQueueGenericSend( pxMutex, NULL, queueMUTEX_GIVE_BLOCK_TIME, queueSEND_TO_BACK );\r
}\r
\r
xReturn = pdPASS;\r
}\r
else\r
{\r
- xReturn = xQueueGenericReceive( pxMutex, NULL, xBlockTime, pdFALSE );\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
\r
signed portBASE_TYPE xQueueGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )\r
{\r
-signed portBASE_TYPE xReturn = pdTRUE;\r
+signed portBASE_TYPE xEntryTimeSet = pdFALSE;\r
xTimeOutType xTimeOut;\r
\r
- do\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 xTicksToWait is zero then we are not going to block even\r
- if there is no room in the queue to post. */\r
- if( xTicksToWait > ( portTickType ) 0 )\r
- {\r
- vTaskSuspendAll();\r
- prvLockQueue( pxQueue );\r
-\r
- if( xReturn == pdTRUE )\r
- {\r
- /* This is the first time through - we need to capture the\r
- time while the scheduler is locked to ensure we attempt to\r
- block at least once. */\r
- vTaskSetTimeOutState( &xTimeOut );\r
- }\r
-\r
- if( prvIsQueueFull( pxQueue ) )\r
- {\r
- /* Need to call xTaskCheckForTimeout again as time could\r
- have passed since it was last called if this is not the\r
- first time around this loop. */\r
- if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == 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() )\r
- {\r
- taskYIELD();\r
- }\r
- }\r
- else\r
- {\r
- prvUnlockQueue( pxQueue );\r
- ( void ) xTaskResumeAll();\r
- }\r
- }\r
- else\r
- {\r
- /* The queue was not full so we can just unlock the\r
- scheduler and queue again before carrying on. */\r
- prvUnlockQueue( pxQueue );\r
- ( void ) xTaskResumeAll();\r
- }\r
- }\r
-\r
- /* Higher priority tasks and interrupts can execute during\r
- this time and could possible refill the queue - even if we\r
- unblocked because space became available. */\r
-\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
+ /* 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
traceQUEUE_SEND( pxQueue );\r
prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );\r
- xReturn = pdPASS;\r
\r
/* If there was a task waiting for data to arrive on the\r
queue then unblock it now. */\r
{\r
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )\r
{\r
- /* The unblocked task has a priority higher than\r
- our own so yield immediately. */\r
- taskYIELD();\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
+\r
+ taskEXIT_CRITICAL();\r
+\r
+ /* Return to the original privilege level before exiting the\r
+ function. */\r
+ return pdPASS;\r
}\r
else\r
{\r
- /* Setting xReturn to errQUEUE_FULL will force its timeout\r
- to be re-evaluated. This is necessary in case interrupts\r
- and higher priority tasks accessed the queue between this\r
- task being unblocked and subsequently attempting to write\r
- to the queue. */\r
- xReturn = errQUEUE_FULL;\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
taskEXIT_CRITICAL();\r
\r
- if( xReturn == errQUEUE_FULL )\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( xTicksToWait > ( portTickType ) 0 )\r
+ if( prvIsQueueFull( pxQueue ) )\r
{\r
- if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
- {\r
- xReturn = queueERRONEOUS_UNBLOCK;\r
- }\r
- else\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() )\r
{\r
- traceQUEUE_SEND_FAILED( pxQueue );\r
+ portYIELD_WITHIN_API();\r
}\r
}\r
else\r
{\r
- traceQUEUE_SEND_FAILED( pxQueue );\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
- while( xReturn == queueERRONEOUS_UNBLOCK );\r
-\r
- return xReturn;\r
}\r
/*-----------------------------------------------------------*/\r
\r
\r
signed portBASE_TYPE xQueueAltGenericSend( 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
- /* The source code that implements the alternative (Alt) API is\r
- simpler because it makes more use of critical sections. This is\r
- the approach taken by many other RTOSes, but FreeRTOS.org has the\r
- preferred fully featured API too. The fully featured API has more\r
- complex code that takes longer to execute, but makes less use of\r
- critical sections. */\r
-\r
- do\r
+ for( ;; )\r
{\r
- /* If xTicksToWait is zero then we are not going to block even\r
- if there is no room in the queue to post. */\r
- if( xTicksToWait > ( portTickType ) 0 )\r
- {\r
- portENTER_CRITICAL();\r
- {\r
- if( xReturn == pdPASS )\r
- {\r
- /* This is the first time through - capture the time\r
- inside the critical section to ensure we attempt to\r
- block at least once. */\r
- vTaskSetTimeOutState( &xTimeOut );\r
- }\r
-\r
- if( prvIsQueueFull( pxQueue ) )\r
- {\r
- /* Need to call xTaskCheckForTimeout again as time could\r
- have passed since it was last called if this is not the\r
- first time around this loop. */\r
- if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
- {\r
- traceBLOCKING_ON_QUEUE_SEND( pxQueue );\r
- vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );\r
-\r
- /* This will exit the critical section, then re-enter when\r
- the task next runs. */\r
- taskYIELD();\r
- }\r
- }\r
- }\r
- portEXIT_CRITICAL();\r
- }\r
-\r
- /* Higher priority tasks and interrupts can execute during\r
- this time and could possible refill the queue - even if we\r
- unblocked because space became available. */\r
-\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
+ /* 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
traceQUEUE_SEND( pxQueue );\r
prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );\r
- xReturn = pdPASS;\r
\r
/* If there was a task waiting for data to arrive on the\r
queue then unblock it now. */\r
{\r
/* The unblocked task has a priority higher than\r
our own so yield immediately. */\r
- taskYIELD();\r
+ portYIELD_WITHIN_API();\r
}\r
}\r
+\r
+ taskEXIT_CRITICAL();\r
+ return pdPASS;\r
}\r
else\r
{\r
- /* Setting xReturn to errQUEUE_FULL will force its timeout\r
- to be re-evaluated. This is necessary in case interrupts\r
- and higher priority tasks accessed the queue between this\r
- task being unblocked and subsequently attempting to write\r
- to the queue. */\r
- xReturn = errQUEUE_FULL;\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
- if( xReturn == errQUEUE_FULL )\r
+ taskENTER_CRITICAL();\r
{\r
- if( xTicksToWait > ( portTickType ) 0 )\r
+ if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
{\r
- if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
- {\r
- xReturn = queueERRONEOUS_UNBLOCK;\r
- }\r
- else\r
+ if( prvIsQueueFull( pxQueue ) )\r
{\r
- traceQUEUE_SEND_FAILED( pxQueue );\r
+ traceBLOCKING_ON_QUEUE_SEND( pxQueue );\r
+ vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );\r
+ portYIELD_WITHIN_API();\r
}\r
}\r
else\r
{\r
+ taskEXIT_CRITICAL();\r
traceQUEUE_SEND_FAILED( pxQueue );\r
+ return errQUEUE_FULL;\r
}\r
}\r
+ taskEXIT_CRITICAL();\r
}\r
- while( xReturn == queueERRONEOUS_UNBLOCK );\r
-\r
- return xReturn;\r
}\r
\r
#endif /* configUSE_ALTERNATIVE_API */\r
\r
signed portBASE_TYPE xQueueAltGenericReceive( 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
- /* The source code that implements the alternative (Alt) API is\r
- simpler because it makes more use of critical sections. This is\r
- the approach taken by many other RTOSes, but FreeRTOS.org has the\r
- preferred fully featured API too. The fully featured API has more\r
- complex code that takes longer to execute, but makes less use of\r
- critical sections. */\r
+ signed char *pcOriginalReadPosition;\r
\r
- do\r
+ for( ;; )\r
{\r
- /* If there are no messages in the queue we may have to block. */\r
- if( xTicksToWait > ( portTickType ) 0 )\r
- {\r
- portENTER_CRITICAL();\r
- {\r
- if( xReturn == pdPASS )\r
- {\r
- /* This is the first time through - capture the time\r
- inside the critical section to ensure we attempt to\r
- block at least once. */\r
- vTaskSetTimeOutState( &xTimeOut );\r
- }\r
-\r
- if( prvIsQueueEmpty( pxQueue ) )\r
- {\r
- /* Need to call xTaskCheckForTimeout again as time could\r
- have passed since it was last called if this is not the\r
- first time around this loop. */\r
- if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
- {\r
- traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );\r
-\r
- #if ( configUSE_MUTEXES == 1 )\r
- {\r
- if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )\r
- {\r
- vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );\r
- }\r
- }\r
- #endif\r
-\r
- vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );\r
- taskYIELD();\r
- }\r
- }\r
- }\r
- portEXIT_CRITICAL();\r
- }\r
-\r
taskENTER_CRITICAL();\r
{\r
if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )\r
{\r
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )\r
{\r
- taskYIELD();\r
+ portYIELD_WITHIN_API();\r
}\r
}\r
}\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 that this task. */\r
- taskYIELD();\r
+ /* The task waiting has a higher priority than this task. */\r
+ portYIELD_WITHIN_API();\r
}\r
}\r
\r
}\r
\r
- xReturn = pdPASS;\r
+ taskEXIT_CRITICAL();\r
+ return pdPASS;\r
}\r
else\r
{\r
- xReturn = errQUEUE_EMPTY;\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
- if( xReturn == errQUEUE_EMPTY )\r
+ taskENTER_CRITICAL();\r
{\r
- if( xTicksToWait > ( portTickType ) 0 )\r
+ if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
{\r
- if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
- {\r
- xReturn = queueERRONEOUS_UNBLOCK;\r
- }\r
- else\r
+ if( prvIsQueueEmpty( pxQueue ) )\r
{\r
- traceQUEUE_RECEIVE_FAILED( pxQueue );\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
- } while( xReturn == queueERRONEOUS_UNBLOCK );\r
-\r
- return xReturn;\r
+ taskEXIT_CRITICAL();\r
+ }\r
}\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
- do\r
- {\r
- /* If there are no messages in the queue we may have to block. */\r
- if( xTicksToWait > ( portTickType ) 0 )\r
- {\r
- vTaskSuspendAll();\r
- prvLockQueue( pxQueue );\r
-\r
- if( xReturn == pdTRUE )\r
- {\r
- /* This is the first time through - we need to capture the\r
- time while the scheduler is locked to ensure we attempt to\r
- block at least once. */\r
- vTaskSetTimeOutState( &xTimeOut );\r
- }\r
-\r
- if( prvIsQueueEmpty( pxQueue ) )\r
- {\r
- /* Need to call xTaskCheckForTimeout again as time could\r
- have passed since it was last called if this is not the\r
- first time around this loop. */\r
- if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
- {\r
- traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );\r
+signed char *pcOriginalReadPosition;\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
+ /* 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
- vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );\r
- prvUnlockQueue( pxQueue );\r
- if( !xTaskResumeAll() )\r
- {\r
- taskYIELD();\r
- }\r
- }\r
- else\r
- {\r
- prvUnlockQueue( pxQueue );\r
- ( void ) xTaskResumeAll();\r
- }\r
- }\r
- else\r
- {\r
- prvUnlockQueue( pxQueue );\r
- ( void ) xTaskResumeAll();\r
- }\r
- }\r
-\r
-/* The two tasks are blocked on the queue, the low priority task is polling/running. */\r
-\r
-/* An interrupt occurs here - which unblocks the HP tasks, but they do not run. */\r
+ for( ;; )\r
+ {\r
taskENTER_CRITICAL();\r
{\r
-/* Because the interrupt occurred the LP task manages to grab the data as the other two tasks are not yet running. */\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
/* Remember our read position in case we are just peeking. */\r
{\r
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )\r
{\r
- taskYIELD();\r
+ portYIELD_WITHIN_API();\r
}\r
}\r
}\r
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
{\r
/* The task waiting has a higher priority than this task. */\r
- taskYIELD();\r
+ portYIELD_WITHIN_API();\r
}\r
}\r
\r
}\r
\r
- xReturn = pdPASS;\r
+ taskEXIT_CRITICAL();\r
+ return pdPASS;\r
}\r
else\r
{\r
- xReturn = errQUEUE_EMPTY;\r
+ if( xTicksToWait == ( portTickType ) 0 )\r
+ {\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
}\r
taskEXIT_CRITICAL();\r
\r
- if( xReturn == errQUEUE_EMPTY )\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( xTicksToWait > ( portTickType ) 0 )\r
+ if( prvIsQueueEmpty( pxQueue ) )\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
- else\r
+ #endif\r
+\r
+ vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );\r
+ prvUnlockQueue( pxQueue );\r
+ if( !xTaskResumeAll() )\r
{\r
- traceQUEUE_RECEIVE_FAILED( pxQueue );\r
+ portYIELD_WITHIN_API();\r
}\r
}\r
else\r
{\r
- traceQUEUE_RECEIVE_FAILED( pxQueue );\r
+ /* Try again. */\r
+ prvUnlockQueue( pxQueue );\r
+ ( void ) xTaskResumeAll();\r
}\r
}\r
-\r
- } while( xReturn == queueERRONEOUS_UNBLOCK );\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
{\r
/* The mutex is no longer being held. */\r
vTaskPriorityDisinherit( ( void * ) pxQueue->pxMutexHolder );\r
- pxQueue->pxMutexHolder = NULL;\r
+ pxQueue->pxMutexHolder = NULL;\r
}\r
}\r
#endif\r
\r
#if configQUEUE_REGISTRY_SIZE > 0\r
\r
- void vQueueAddToRegistry( xQueueHandle xQueue, signed portCHAR *pcQueueName )\r
+ void vQueueAddToRegistry( xQueueHandle xQueue, signed char *pcQueueName )\r
{\r
unsigned portBASE_TYPE ux;\r
\r
break;\r
}\r
}\r
+\r
}\r
\r
#endif\r