#include "BlockQ.h"\r
#include "print.h"\r
\r
-#define blckqSTACK_SIZE ( ( unsigned portSHORT ) 128 )\r
+#define blckqSTACK_SIZE ( ( unsigned portSHORT ) configMINIMAL_STACK_SIZE )\r
#define blckqNUM_TASK_SETS ( 3 )\r
\r
/* Structure used to pass parameters to the blocking queue tasks. */\r
\r
for( ;; )\r
{ \r
- if( xQueueSend( pxQueueParameters->xQueue, ( void * ) &usValue, pxQueueParameters->xBlockTime ) != pdPASS )\r
+ if( xQueueSendToBack( pxQueueParameters->xQueue, ( void * ) &usValue, pxQueueParameters->xBlockTime ) != pdPASS )\r
{\r
vPrintDisplayMessage( &pcTaskErrorMsg );\r
sErrorEverOccurred = pdTRUE;\r
/* Demo program include files. */\r
#include "PollQ.h"\r
\r
-#define pollqSTACK_SIZE ( ( unsigned portSHORT ) 128 )\r
+#define pollqSTACK_SIZE ( ( unsigned portSHORT ) configMINIMAL_STACK_SIZE )\r
\r
/* The task that posts the incrementing number onto the queue. */\r
static void vPolledQueueProducer( void *pvParameters );\r
for( usLoop = 0; usLoop < usNumToProduce; ++usLoop )\r
{\r
/* Send an incrementing number on the queue without blocking. */\r
- if( xQueueSend( *pxQueue, ( void * ) &usValue, ( portTickType ) 0 ) != pdPASS )\r
+ if( xQueueSendToBack( *pxQueue, ( void * ) &usValue, ( portTickType ) 0 ) != pdPASS )\r
{\r
/* We should never find the queue full - this is an error. */\r
vPrintDisplayMessage( &pcTaskErrorMsg );\r
\r
\r
/* Demo task specific constants. */\r
-#define priSTACK_SIZE ( ( unsigned portSHORT ) 128 )\r
+#define priSTACK_SIZE ( ( unsigned portSHORT ) configMINIMAL_STACK_SIZE )\r
#define priSLEEP_TIME ( ( portTickType ) 50 )\r
#define priLOOPS ( 5 )\r
#define priMAX_COUNT ( ( unsigned portLONG ) 0xff )\r
xTaskCreate( vQueueSendWhenSuspendedTask, "SUSP_SEND", priSTACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );\r
xTaskCreate( vQueueReceiveWhenSuspendedTask, "SUSP_RECV", priSTACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );\r
xTaskCreate( prvChangePriorityWhenSuspendedTask, "1st_P_CHANGE", priSTACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL );\r
- xTaskCreate( prvChangePriorityHelperTask, "2nt_P_CHANGE", priSTACK_SIZE, NULL, tskIDLE_PRIORITY, &xChangePriorityWhenSuspendedHandle );\r
+ xTaskCreate( prvChangePriorityHelperTask, "2nd_P_CHANGE", priSTACK_SIZE, NULL, tskIDLE_PRIORITY, &xChangePriorityWhenSuspendedHandle );\r
}\r
/*-----------------------------------------------------------*/\r
\r
#include "print.h"\r
\r
/* Demo specific constants. */\r
-#define evtSTACK_SIZE ( ( unsigned portBASE_TYPE ) 128 )\r
+#define evtSTACK_SIZE ( ( unsigned portBASE_TYPE ) configMINIMAL_STACK_SIZE )\r
#define evtNUM_TASKS ( 4 )\r
#define evtQUEUE_LENGTH ( ( unsigned portBASE_TYPE ) 3 )\r
#define evtNO_DELAY 0\r
--- /dev/null
+/*\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
+/* \r
+ * Tests the extra queue functionality introduced in FreeRTOS.org V4.5.0 - \r
+ * including xQueueSendToFront(), xQueueSendToBack(), xQueuePeek() and \r
+ * mutex behaviour. \r
+ *\r
+ * See the comments above the prvSendFrontAndBackTest() and \r
+ * prvLowPriorityMutexTask() prototypes below for more information.\r
+ */\r
+\r
+\r
+#include <stdlib.h>\r
+\r
+/* Scheduler include files. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "queue.h"\r
+#include "semphr.h"\r
+\r
+/* Demo program include files. */\r
+#include "GenQTest.h"\r
+\r
+#define genqQUEUE_LENGTH ( 5 )\r
+#define genqNO_BLOCK ( 0 )\r
+\r
+#define genqMUTEX_LOW_PRIORITY ( tskIDLE_PRIORITY )\r
+#define genqMUTEX_TEST_PRIORITY ( tskIDLE_PRIORITY + 1 )\r
+#define genqMUTEX_MEDIUM_PRIORITY ( tskIDLE_PRIORITY + 2 )\r
+#define genqMUTEX_HIGH_PRIORITY ( tskIDLE_PRIORITY + 3 )\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * Tests the behaviour of the xQueueSendToFront() and xQueueSendToBack()\r
+ * macros by using both to fill a queue, then reading from the queue to\r
+ * check the resultant queue order is as expected. Queue data is also\r
+ * peeked.\r
+ */\r
+static void prvSendFrontAndBackTest( void *pvParameters );\r
+\r
+/*\r
+ * The following three tasks are used to demonstrate the mutex behaviour.\r
+ * Each task is given a different priority to demonstrate the priority\r
+ * inheritance mechanism.\r
+ *\r
+ * The low priority task obtains a mutex. After this a high priority task\r
+ * attempts to obtain the same mutex, causing its priority to be inherited\r
+ * by the low priority task. The task with the inherited high priority then\r
+ * resumes a medium priority task to ensure it is not blocked by the medium\r
+ * priority task while it holds the inherited high priority. Once the mutex\r
+ * is returned the task with the inherited priority returns to its original\r
+ * low priority, and is therefore immediately preempted by first the high\r
+ * priority task and then the medium prioroity task before it can continue.\r
+ */\r
+static void prvLowPriorityMutexTask( void *pvParameters );\r
+static void prvMediumPriorityMutexTask( void *pvParameters );\r
+static void prvHighPriorityMutexTask( void *pvParameters );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Flag that will be latched to pdTRUE should any unexpected behaviour be\r
+detected in any of the tasks. */\r
+static portBASE_TYPE xErrorDetected = pdFALSE;\r
+\r
+/* Counters that are incremented on each cycle of a test. This is used to\r
+detect a stalled task - a test that is no longer running. */\r
+static volatile unsigned portLONG ulLoopCounter = 0;\r
+static volatile unsigned portLONG ulLoopCounter2 = 0;\r
+\r
+/* The variable that is guarded by the mutex in the mutex demo tasks. */\r
+static volatile unsigned portLONG ulGuardedVariable = 0;\r
+\r
+/* Handles used in the mutext test to suspend and resume the high and medium\r
+priority mutex test tasks. */\r
+static xTaskHandle xHighPriorityMutexTask, xMediumPriorityMutexTask;\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+void vStartGenericQueueTasks( unsigned portBASE_TYPE uxPriority )\r
+{\r
+xQueueHandle xQueue;\r
+xSemaphoreHandle xMutex;\r
+\r
+ /* Create the queue that we are going to use for the\r
+ prvSendFrontAndBackTest demo. */\r
+ xQueue = xQueueCreate( genqQUEUE_LENGTH, sizeof( unsigned portLONG ) );\r
+\r
+ /* Create the demo task and pass it the queue just created. We are\r
+ passing the queue handle by value so it does not matter that it is\r
+ declared on the stack here. */\r
+ xTaskCreate( prvSendFrontAndBackTest, "GenQ", configMINIMAL_STACK_SIZE, ( void * ) xQueue, uxPriority, NULL );\r
+\r
+ /* Create the mutex used by the prvMutexTest task. */\r
+ xMutex = xSemaphoreCreateMutex();\r
+\r
+ /* Create the mutex demo tasks and pass it the mutex just created. We are\r
+ passing the mutex handle by value so it does not matter that it is declared\r
+ on the stack here. */\r
+ xTaskCreate( prvLowPriorityMutexTask, "MuLow", configMINIMAL_STACK_SIZE, ( void * ) xMutex, genqMUTEX_LOW_PRIORITY, NULL );\r
+ xTaskCreate( prvMediumPriorityMutexTask, "MuMed", configMINIMAL_STACK_SIZE, NULL, genqMUTEX_MEDIUM_PRIORITY, &xMediumPriorityMutexTask );\r
+ xTaskCreate( prvHighPriorityMutexTask, "MuHigh", configMINIMAL_STACK_SIZE, ( void * ) xMutex, genqMUTEX_HIGH_PRIORITY, &xHighPriorityMutexTask );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvSendFrontAndBackTest( void *pvParameters )\r
+{\r
+unsigned portLONG ulData, ulData2;\r
+xQueueHandle xQueue;\r
+\r
+ #ifdef USE_STDIO\r
+ void vPrintDisplayMessage( const portCHAR * const * ppcMessageToSend );\r
+ \r
+ const portCHAR * const pcTaskStartMsg = "Queue SendToFront/SendToBack/Peek test started.\r\n";\r
+\r
+ /* Queue a message for printing to say the task has started. */\r
+ vPrintDisplayMessage( &pcTaskStartMsg );\r
+ #endif\r
+\r
+ xQueue = ( xQueueHandle ) pvParameters;\r
+\r
+ for( ;; )\r
+ {\r
+ /* The queue is empty, so sending an item to the back of the queue\r
+ should have the same efect as sending it to the front of the queue.\r
+\r
+ First send to the front and check everything is as expected. */\r
+ xQueueSendToFront( xQueue, ( void * ) &ulLoopCounter, genqNO_BLOCK );\r
+\r
+ if( uxQueueMessagesWaiting( xQueue ) != 1 )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ if( xQueueReceive( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != pdPASS )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ /* The data we sent to the queue should equal the data we just received\r
+ from the queue. */\r
+ if( ulLoopCounter != ulData )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ /* Then do the same, sending the data to the back, checking everything\r
+ is as expected. */\r
+ if( uxQueueMessagesWaiting( xQueue ) != 0 )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ xQueueSendToBack( xQueue, ( void * ) &ulLoopCounter, genqNO_BLOCK );\r
+\r
+ if( uxQueueMessagesWaiting( xQueue ) != 1 )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ if( xQueueReceive( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != pdPASS )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ if( uxQueueMessagesWaiting( xQueue ) != 0 )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ /* The data we sent to the queue should equal the data we just received\r
+ from the queue. */\r
+ if( ulLoopCounter != ulData )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ #if configUSE_PREEMPTION == 0\r
+ taskYIELD();\r
+ #endif\r
+\r
+\r
+\r
+ /* Place 2, 3, 4 into the queue, adding items to the back of the queue. */\r
+ for( ulData = 2; ulData < 5; ulData++ )\r
+ {\r
+ xQueueSendToBack( xQueue, ( void * ) &ulData, genqNO_BLOCK );\r
+ }\r
+\r
+ /* Now the order in the queue should be 2, 3, 4, with 2 being the first\r
+ thing to be read out. Now add 1 then 0 to the front of the queue. */\r
+ if( uxQueueMessagesWaiting( xQueue ) != 3 )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+ ulData = 1;\r
+ xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK );\r
+ ulData = 0;\r
+ xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK );\r
+\r
+ /* Now the queue should be full, and when we read the data out we\r
+ should receive 0, 1, 2, 3, 4. */\r
+ if( uxQueueMessagesWaiting( xQueue ) != 5 )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ if( xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ if( xQueueSendToBack( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ #if configUSE_PREEMPTION == 0\r
+ taskYIELD();\r
+ #endif\r
+\r
+ /* Check the data we read out is in the expected order. */\r
+ for( ulData = 0; ulData < genqQUEUE_LENGTH; ulData++ )\r
+ {\r
+ /* Try peeking the data first. */\r
+ if( xQueuePeek( xQueue, &ulData2, genqNO_BLOCK ) != pdPASS )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ if( ulData != ulData2 )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+ \r
+\r
+ /* Now try receiving the data for real. The value should be the\r
+ same. Clobber the value first so we know we really received it. */\r
+ ulData2 = ~ulData2;\r
+ if( xQueueReceive( xQueue, &ulData2, genqNO_BLOCK ) != pdPASS )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ if( ulData != ulData2 )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+ }\r
+\r
+ /* The queue should now be empty again. */\r
+ if( uxQueueMessagesWaiting( xQueue ) != 0 )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ #if configUSE_PREEMPTION == 0\r
+ taskYIELD();\r
+ #endif\r
+\r
+\r
+ /* Our queue is empty once more, add 10, 11 to the back. */\r
+ ulData = 10;\r
+ if( xQueueSend( xQueue, &ulData, genqNO_BLOCK ) != pdPASS )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+ ulData = 11;\r
+ if( xQueueSend( xQueue, &ulData, genqNO_BLOCK ) != pdPASS )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ if( uxQueueMessagesWaiting( xQueue ) != 2 )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ /* Now we should have 10, 11 in the queue. Add 7, 8, 9 to the\r
+ front. */\r
+ for( ulData = 9; ulData >= 7; ulData-- )\r
+ {\r
+ if( xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != pdPASS )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+ }\r
+\r
+ /* Now check that the queue is full, and that receiving data provides\r
+ the expected sequence of 7, 8, 9, 10, 11. */\r
+ if( uxQueueMessagesWaiting( xQueue ) != 5 )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ if( xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ if( xQueueSendToBack( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ #if configUSE_PREEMPTION == 0\r
+ taskYIELD();\r
+ #endif\r
+\r
+ /* Check the data we read out is in the expected order. */\r
+ for( ulData = 7; ulData < ( 7 + genqQUEUE_LENGTH ); ulData++ )\r
+ {\r
+ if( xQueueReceive( xQueue, &ulData2, genqNO_BLOCK ) != pdPASS )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ if( ulData != ulData2 )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+ }\r
+\r
+ if( uxQueueMessagesWaiting( xQueue ) != 0 )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ ulLoopCounter++;\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvLowPriorityMutexTask( void *pvParameters )\r
+{\r
+xSemaphoreHandle xMutex = ( xSemaphoreHandle ) pvParameters;\r
+\r
+ #ifdef USE_STDIO\r
+ void vPrintDisplayMessage( const portCHAR * const * ppcMessageToSend );\r
+ \r
+ const portCHAR * const pcTaskStartMsg = "Mutex with priority inheritance test started.\r\n";\r
+\r
+ /* Queue a message for printing to say the task has started. */\r
+ vPrintDisplayMessage( &pcTaskStartMsg );\r
+ #endif\r
+\r
+ for( ;; )\r
+ {\r
+ /* Take the mutex. It should be available now. */\r
+ if( xSemaphoreTake( xMutex, genqNO_BLOCK ) != pdPASS )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ /* Set our guarded variable to a known start value. */\r
+ ulGuardedVariable = 0;\r
+\r
+ /* Our priority should be as per that assigned when the task was\r
+ created. */\r
+ if( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ /* Now unsuspend the high priority task. This will attempt to take the\r
+ mutex, and block when it finds it cannot obtain it. */\r
+ vTaskResume( xHighPriorityMutexTask );\r
+\r
+ /* We should now have inherited the prioritoy of the high priority task,\r
+ as by now it will have attempted to get the mutex. */\r
+ if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ /* We can attempt to set our priority to the test priority - between the\r
+ idle priority and the medium/high test priorities, but our actual\r
+ prioroity should remain at the high priority. */\r
+ vTaskPrioritySet( NULL, genqMUTEX_TEST_PRIORITY );\r
+ if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ /* Now unsuspend the medium priority task. This should not run as our\r
+ inherited priority is above that of the medium priority task. */\r
+ vTaskResume( xMediumPriorityMutexTask );\r
+\r
+ /* If the did run then it will have incremented our guarded variable. */\r
+ if( ulGuardedVariable != 0 )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ /* When we give back the semaphore our priority should be disinherited\r
+ back to the priority to which we attempted to set ourselves. This means\r
+ that when the high priority task next blocks, the medium priority task\r
+ should execute and increment the guarded variable. When we next run\r
+ both the high and medium priority tasks will have been suspended again. */\r
+ if( xSemaphoreGive( xMutex ) != pdPASS )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ /* Check that the guarded variable did indeed increment... */\r
+ if( ulGuardedVariable != 1 )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ /* ... and that our priority has been disinherited to\r
+ genqMUTEX_TEST_PRIORITY. */\r
+ if( uxTaskPriorityGet( NULL ) != genqMUTEX_TEST_PRIORITY )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ /* Set our priority back to our original priority ready for the next\r
+ loop around this test. */\r
+ vTaskPrioritySet( NULL, genqMUTEX_LOW_PRIORITY );\r
+\r
+ /* Just to show we are still running. */\r
+ ulLoopCounter2++;\r
+\r
+ #if configUSE_PREEMPTION == 0\r
+ taskYIELD();\r
+ #endif \r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvMediumPriorityMutexTask( void *pvParameters )\r
+{\r
+ for( ;; )\r
+ {\r
+ /* The medium priority task starts by suspending itself. The low\r
+ priority task will unsuspend this task when required. */\r
+ vTaskSuspend( NULL );\r
+\r
+ /* When this task unsuspends all it does is increment the guarded\r
+ variable, this is so the low priority task knows that it has\r
+ executed. */\r
+ ulGuardedVariable++;\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvHighPriorityMutexTask( void *pvParameters )\r
+{\r
+xSemaphoreHandle xMutex = ( xSemaphoreHandle ) pvParameters;\r
+\r
+ for( ;; )\r
+ {\r
+ /* The high priority task starts by suspending itself. The low\r
+ priority task will unsuspend this task when required. */\r
+ vTaskSuspend( NULL );\r
+\r
+ /* When this task unsuspends all it does is attempt to obtain\r
+ the mutex. It should find the mutex is not available so a\r
+ block time is specified. */\r
+ if( xSemaphoreTake( xMutex, portMAX_DELAY ) != pdPASS )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ /* When we eventually obtain the mutex we just give it back then\r
+ return to suspend ready for the next test. */\r
+ if( xSemaphoreGive( xMutex ) != pdPASS )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ } \r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/* This is called to check that all the created tasks are still running. */\r
+portBASE_TYPE xAreGenericQueueTasksStillRunning( void )\r
+{\r
+static unsigned portLONG ulLastLoopCounter = 0, ulLastLoopCounter2 = 0;\r
+\r
+ /* If the demo task is still running then we expect the loopcounters to\r
+ have incremented since this function was last called. */\r
+ if( ulLastLoopCounter == ulLoopCounter )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ if( ulLastLoopCounter2 == ulLoopCounter2 )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ ulLastLoopCounter = ulLoopCounter;\r
+ ulLastLoopCounter2 = ulLoopCounter2; \r
+\r
+ /* Errors detected in the task itself will have latched xErrorDetected\r
+ to true. */\r
+\r
+ return !xErrorDetected;\r
+}\r
+\r
+\r
--- /dev/null
+/*\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
+#ifndef GEN_Q_TEST_H\r
+#define GEN_Q_TEST_H\r
+\r
+void vStartGenericQueueTasks( unsigned portBASE_TYPE uxPriority );\r
+portBASE_TYPE xAreGenericQueueTasksStillRunning( void );\r
+\r
+#endif /* GEN_Q_TEST_H */\r
+\r
+\r
+\r
#define configUSE_IDLE_HOOK 1\r
#define configUSE_TICK_HOOK 1\r
#define configTICK_RATE_HZ ( ( portTickType ) 1000 )\r
-#define configMINIMAL_STACK_SIZE ( ( unsigned portSHORT ) 128 ) /* This can be made smaller if required. */\r
+#define configMINIMAL_STACK_SIZE ( ( unsigned portSHORT ) 256 ) /* This can be made smaller if required. */\r
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 32 * 1024 ) ) \r
#define configMAX_TASK_NAME_LEN ( 16 )\r
#define configUSE_TRACE_FACILITY 1\r
#define configUSE_16_BIT_TICKS 1\r
#define configIDLE_SHOULD_YIELD 1\r
#define configUSE_CO_ROUTINES 1\r
+#define configUSE_MUTEXES 1\r
\r
#define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 10 )\r
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )\r
#include "mevents.h"\r
#include "crhook.h"\r
#include "blocktim.h"\r
+#include "GenQTest.h"\r
\r
/* Priority definitions for the tasks in the demo application. */\r
#define mainLED_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )\r
#define mainQUEUE_BLOCK_PRIORITY ( tskIDLE_PRIORITY + 3 )\r
#define mainCOM_TEST_PRIORITY ( tskIDLE_PRIORITY + 2 )\r
#define mainSEMAPHORE_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )\r
+#define mainGENERIC_QUEUE_PRIORITY ( tskIDLE_PRIORITY )\r
\r
#define mainPRINT_STACK_SIZE ( ( unsigned portSHORT ) 512 )\r
#define mainDEBUG_LOG_BUFFER_SIZE ( ( unsigned portSHORT ) 20480 )\r
vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY );\r
vStartBlockingQueueTasks( mainQUEUE_BLOCK_PRIORITY );\r
vCreateBlockTimeTasks();\r
- \r
+ vStartGenericQueueTasks( mainGENERIC_QUEUE_PRIORITY );\r
vStartSemaphoreTasks( mainSEMAPHORE_TASK_PRIORITY );\r
vStartDynamicPriorityTasks();\r
vStartMultiEventTasks();\r
sErrorHasOccurred = pdTRUE;\r
}\r
\r
+ if( xAreGenericQueueTasksStillRunning() != pdTRUE )\r
+ {\r
+ vDisplayMessage( "Error in generic queue test task!\r\n" );\r
+ sErrorHasOccurred = pdTRUE; \r
+ }\r
+\r
if( sErrorHasOccurred == pdFALSE )\r
{\r
vDisplayMessage( "OK " );\r
de6en\r
1\r
0\r
-0\r
+1\r
4\r
MCommand\r
0\r
0\r
19\r
WPickList\r
-50\r
+52\r
20\r
MItem\r
3\r
WString\r
25\r
d????Include directories:\r
-1\r
+0\r
26\r
WString\r
-97\r
-$(%watcom)\h;..\common\include;..\..\source\include;..\..\source\portable\owatcom\16bitdos\common\r
+99\r
+$(%watcom)\h;..\common\include;..\..\source\include;..\..\source\portable\owatcom\16bitdos\common;.\r
0\r
27\r
MCState\r
WString\r
26\r
?????Force ANSI compliance\r
-1\r
+0\r
1\r
30\r
MCState\r
WString\r
33\r
?????Disable stack depth checking\r
-1\r
+0\r
1\r
33\r
MVState\r
WString\r
23\r
?????Macro definitions:\r
-1\r
+0\r
36\r
WString\r
-52\r
-OPEN_WATCOM_INDUSTRIAL_PC_PORT USE_STDIO DEBUG_BUILD\r
+40\r
+OPEN_WATCOM_INDUSTRIAL_PC_PORT USE_STDIO\r
0\r
37\r
MCState\r
WString\r
34\r
?????Change char default to signed\r
-1\r
+0\r
1\r
40\r
MRState\r
WCC\r
42\r
WString\r
-21\r
-?????Compiler default\r
-1\r
+29\r
+?????No debugging information\r
0\r
+1\r
43\r
MRState\r
44\r
WCC\r
45\r
WString\r
-21\r
-?????Compiler default\r
-1\r
+28\r
+?????Line number information\r
+0\r
0\r
46\r
MRState\r
WCC\r
48\r
WString\r
-25\r
-?????Floating-point calls\r
-1\r
-1\r
+21\r
+?????Compiler default\r
+0\r
+0\r
49\r
-MCState\r
+MRState\r
50\r
WString\r
3\r
WCC\r
51\r
WString\r
-31\r
-???e?SS not assumed equal to DS\r
-1\r
-1\r
+21\r
+?????Compiler default\r
+0\r
+0\r
52\r
MRState\r
53\r
WCC\r
54\r
WString\r
-9\r
-??6??8086\r
-1\r
+25\r
+?????Floating-point calls\r
0\r
+1\r
55\r
-MRState\r
+MCState\r
56\r
WString\r
3\r
WCC\r
57\r
WString\r
-10\r
-??6??80186\r
-1\r
+31\r
+???e?SS not assumed equal to DS\r
+0\r
1\r
58\r
-MVState\r
+MRState\r
59\r
WString\r
3\r
WCC\r
60\r
WString\r
-25\r
-d????Include directories:\r
+9\r
+??6??8086\r
0\r
-61\r
-WString\r
-99\r
-$(%watcom)\h;..\common\include;..\..\source\include;..\..\source\portable\owatcom\16bitdos\common;.\r
0\r
+61\r
+MRState\r
62\r
-MCState\r
-63\r
WString\r
3\r
WCC\r
-64\r
+63\r
WString\r
-26\r
-?????Force ANSI compliance\r
+10\r
+??6??80186\r
0\r
1\r
+64\r
+MVState\r
65\r
-MCState\r
-66\r
WString\r
3\r
WCC\r
+66\r
+WString\r
+25\r
+d????Include directories:\r
+1\r
67\r
WString\r
-33\r
-?????Disable stack depth checking\r
+97\r
+$(%watcom)\h;..\common\include;..\..\source\include;..\..\source\portable\owatcom\16bitdos\common\r
0\r
-1\r
68\r
-MVState\r
+MCState\r
69\r
WString\r
3\r
WCC\r
70\r
WString\r
-23\r
-?????Macro definitions:\r
-0\r
+26\r
+?????Force ANSI compliance\r
+1\r
+1\r
71\r
-WString\r
-40\r
-OPEN_WATCOM_INDUSTRIAL_PC_PORT USE_STDIO\r
-0\r
+MVState\r
72\r
-MCState\r
-73\r
WString\r
3\r
WCC\r
+73\r
+WString\r
+23\r
+?????Macro definitions:\r
+1\r
74\r
WString\r
-34\r
-?????Change char default to signed\r
+52\r
+OPEN_WATCOM_INDUSTRIAL_PC_PORT USE_STDIO DEBUG_BUILD\r
0\r
-1\r
75\r
-MRState\r
+MCState\r
76\r
WString\r
3\r
WCC\r
77\r
WString\r
-29\r
-?????No debugging information\r
-0\r
+34\r
+?????Change char default to signed\r
+1\r
1\r
78\r
-MRState\r
+MCState\r
79\r
WString\r
3\r
WCC\r
80\r
WString\r
-28\r
-?????Line number information\r
-0\r
-0\r
+33\r
+?????Disable stack depth checking\r
+1\r
+1\r
81\r
MRState\r
82\r
WString\r
21\r
?????Compiler default\r
-0\r
+1\r
0\r
84\r
MRState\r
WString\r
21\r
?????Compiler default\r
-0\r
+1\r
0\r
87\r
MRState\r
WString\r
25\r
?????Floating-point calls\r
-0\r
+1\r
1\r
90\r
MCState\r
WString\r
31\r
???e?SS not assumed equal to DS\r
-0\r
+1\r
1\r
93\r
MRState\r
WString\r
9\r
??6??8086\r
-0\r
+1\r
0\r
96\r
MRState\r
WString\r
10\r
??6??80186\r
-0\r
+1\r
1\r
99\r
WVList\r
0\r
180\r
MItem\r
-15\r
-fileio\fileio.c\r
+28\r
+..\COMMON\MINIMAL\GenQTest.c\r
181\r
WString\r
4\r
0\r
184\r
MItem\r
-6\r
-main.c\r
+15\r
+fileio\fileio.c\r
185\r
WString\r
4\r
0\r
188\r
MItem\r
-17\r
-partest\partest.c\r
+6\r
+main.c\r
189\r
WString\r
4\r
0\r
192\r
MItem\r
-15\r
-serial\serial.c\r
+17\r
+partest\partest.c\r
193\r
WString\r
4\r
0\r
196\r
MItem\r
-3\r
-*.h\r
+15\r
+serial\serial.c\r
197\r
WString\r
-3\r
-NIL\r
+4\r
+COBJ\r
198\r
WVList\r
0\r
199\r
WVList\r
0\r
--1\r
+20\r
+1\r
1\r
-0\r
0\r
200\r
MItem\r
-31\r
-..\..\SOURCE\INCLUDE\croutine.h\r
+3\r
+*.h\r
201\r
WString\r
3\r
203\r
WVList\r
0\r
-196\r
-1\r
+-1\r
1\r
0\r
+0\r
204\r
MItem\r
-27\r
-..\..\source\include\list.h\r
+31\r
+..\..\SOURCE\INCLUDE\croutine.h\r
205\r
WString\r
3\r
207\r
WVList\r
0\r
-196\r
+200\r
1\r
1\r
0\r
208\r
MItem\r
-31\r
-..\..\source\include\portable.h\r
+27\r
+..\..\source\include\list.h\r
209\r
WString\r
3\r
211\r
WVList\r
0\r
-196\r
+200\r
1\r
1\r
0\r
212\r
MItem\r
31\r
-..\..\source\include\projdefs.h\r
+..\..\source\include\portable.h\r
213\r
WString\r
3\r
215\r
WVList\r
0\r
-196\r
+200\r
1\r
1\r
0\r
216\r
MItem\r
-28\r
-..\..\source\include\queue.h\r
+31\r
+..\..\source\include\projdefs.h\r
217\r
WString\r
3\r
219\r
WVList\r
0\r
-196\r
+200\r
1\r
1\r
0\r
220\r
MItem\r
-29\r
-..\..\source\include\semphr.h\r
+28\r
+..\..\source\include\queue.h\r
221\r
WString\r
3\r
223\r
WVList\r
0\r
-196\r
+200\r
1\r
1\r
0\r
224\r
MItem\r
-27\r
-..\..\source\include\task.h\r
+29\r
+..\..\source\include\semphr.h\r
225\r
WString\r
3\r
227\r
WVList\r
0\r
-196\r
+200\r
1\r
1\r
0\r
228\r
MItem\r
-55\r
-..\..\source\portable\owatcom\16bitdos\common\portasm.h\r
+27\r
+..\..\source\include\task.h\r
229\r
WString\r
3\r
231\r
WVList\r
0\r
-196\r
+200\r
1\r
1\r
0\r
232\r
MItem\r
-53\r
-..\..\source\portable\owatcom\16bitdos\pc\portmacro.h\r
+55\r
+..\..\source\portable\owatcom\16bitdos\common\portasm.h\r
233\r
WString\r
3\r
235\r
WVList\r
0\r
-196\r
+200\r
1\r
1\r
0\r
236\r
MItem\r
-26\r
-..\common\include\blockq.h\r
+53\r
+..\..\source\portable\owatcom\16bitdos\pc\portmacro.h\r
237\r
WString\r
3\r
239\r
WVList\r
0\r
-196\r
+200\r
1\r
1\r
0\r
240\r
MItem\r
-28\r
-..\COMMON\INCLUDE\blocktim.h\r
+26\r
+..\common\include\blockq.h\r
241\r
WString\r
3\r
243\r
WVList\r
0\r
-196\r
+200\r
1\r
1\r
0\r
244\r
MItem\r
-27\r
-..\common\include\comtest.h\r
+28\r
+..\COMMON\INCLUDE\blocktim.h\r
245\r
WString\r
3\r
247\r
WVList\r
0\r
-196\r
+200\r
1\r
1\r
0\r
248\r
MItem\r
-26\r
-..\COMMON\INCLUDE\crhook.h\r
+27\r
+..\common\include\comtest.h\r
249\r
WString\r
3\r
251\r
WVList\r
0\r
-196\r
+200\r
1\r
1\r
0\r
252\r
MItem\r
-25\r
-..\common\include\death.h\r
+26\r
+..\COMMON\INCLUDE\crhook.h\r
253\r
WString\r
3\r
255\r
WVList\r
0\r
-196\r
+200\r
1\r
1\r
0\r
256\r
MItem\r
-27\r
-..\COMMON\INCLUDE\dynamic.h\r
+25\r
+..\common\include\death.h\r
257\r
WString\r
3\r
259\r
WVList\r
0\r
-196\r
+200\r
1\r
1\r
0\r
260\r
MItem\r
-26\r
-..\common\include\fileio.h\r
+27\r
+..\COMMON\INCLUDE\dynamic.h\r
261\r
WString\r
3\r
263\r
WVList\r
0\r
-196\r
+200\r
1\r
1\r
0\r
264\r
MItem\r
-25\r
-..\common\include\flash.h\r
+26\r
+..\common\include\fileio.h\r
265\r
WString\r
3\r
267\r
WVList\r
0\r
-196\r
+200\r
1\r
1\r
0\r
268\r
MItem\r
-24\r
-..\common\include\flop.h\r
+25\r
+..\common\include\flash.h\r
269\r
WString\r
3\r
271\r
WVList\r
0\r
-196\r
+200\r
1\r
1\r
0\r
272\r
MItem\r
-27\r
-..\common\include\partest.h\r
+24\r
+..\common\include\flop.h\r
273\r
WString\r
3\r
275\r
WVList\r
0\r
-196\r
+200\r
1\r
1\r
0\r
276\r
MItem\r
-25\r
-..\common\include\pollq.h\r
+28\r
+..\COMMON\INCLUDE\GenQTest.h\r
277\r
WString\r
3\r
279\r
WVList\r
0\r
-196\r
+200\r
1\r
1\r
0\r
280\r
MItem\r
-25\r
-..\common\include\print.h\r
+27\r
+..\common\include\partest.h\r
281\r
WString\r
3\r
283\r
WVList\r
0\r
-196\r
+200\r
1\r
1\r
0\r
284\r
MItem\r
-27\r
-..\common\include\semtest.h\r
+25\r
+..\common\include\pollq.h\r
285\r
WString\r
3\r
287\r
WVList\r
0\r
-196\r
+200\r
1\r
1\r
0\r
288\r
MItem\r
-26\r
-..\common\include\serial.h\r
+25\r
+..\common\include\print.h\r
289\r
WString\r
3\r
291\r
WVList\r
0\r
-196\r
+200\r
1\r
1\r
0\r
292\r
MItem\r
-16\r
-FreeRTOSConfig.h\r
+27\r
+..\common\include\semtest.h\r
293\r
WString\r
3\r
295\r
WVList\r
0\r
-196\r
+200\r
+1\r
+1\r
+0\r
+296\r
+MItem\r
+26\r
+..\common\include\serial.h\r
+297\r
+WString\r
+3\r
+NIL\r
+298\r
+WVList\r
+0\r
+299\r
+WVList\r
+0\r
+200\r
+1\r
+1\r
+0\r
+300\r
+MItem\r
+16\r
+FreeRTOSConfig.h\r
+301\r
+WString\r
+3\r
+NIL\r
+302\r
+WVList\r
+0\r
+303\r
+WVList\r
+0\r
+200\r
1\r
1\r
0\r
0\r
0\r
7168\r
-7168\r
+8523\r
0\r
0\r
9\r
12\r
rtosdemo.tgt\r
0\r
-25\r
+26\r
7\r
portSHORT sInterruptID;\r
portCHAR cIn, cOut;\r
portBASE_TYPE xTaskWokenByPost = pdFALSE, xAnotherTaskWokenByPost = pdFALSE, xTaskWokenByTx = pdFALSE;\r
+extern void vComTestUnsuspendTask( void );\r
\r
portOUTPUT_BYTE( pxPort->us8259InterruptMaskReg, ( portINPUT_BYTE( pxPort->us8259InterruptMaskReg) | ~pxPort->ucInterruptEnableMast ) );\r
\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
+ 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
+ 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
#define INC_FREERTOS_H\r
\r
\r
-/* \r
- * Include the generic headers required for the FreeRTOS port being used. \r
+/*\r
+ * Include the generic headers required for the FreeRTOS port being used.\r
*/\r
#include <stddef.h>\r
\r
\r
\r
/*\r
- * Check all the required application specific macros have been defined. \r
+ * Check all the required application specific macros have been defined.\r
* These macros are application specific and (as downloaded) are defined\r
* within FreeRTOSConfig.h.\r
*/\r
#error Missing definition: configUSE_16_BIT_TICKS should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.\r
#endif\r
\r
+#ifndef configUSE_MUTEXES\r
+ #define configUSE_MUTEXES 0\r
+#endif\r
+\r
+#if ( configUSE_MUTEXES == 1 )\r
+ /* xTaskGetCurrentTaskHandle is used by the priority inheritance mechanism\r
+ within the mutex implementation so must be available if mutexes are used. */\r
+ #undef INCLUDE_xTaskGetCurrentTaskHandle\r
+ #define INCLUDE_xTaskGetCurrentTaskHandle 1\r
+#else\r
+ #ifndef INCLUDE_xTaskGetCurrentTaskHandle\r
+ #define INCLUDE_xTaskGetCurrentTaskHandle 0\r
+ #endif\r
#endif\r
+\r
+#endif /* INC_FREERTOS_H */\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
+ 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
+ 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
\r
typedef void * xQueueHandle;\r
\r
+/* For internal use only. */\r
+#define queueSEND_TO_BACK ( 0 )\r
+#define queueSEND_TO_FRONT ( 1 )\r
+\r
+\r
/**\r
* queue. h\r
* <pre>\r
- xQueueHandle xQueueCreate( \r
- unsigned portBASE_TYPE uxQueueLength, \r
- unsigned portBASE_TYPE uxItemSize \r
+ xQueueHandle xQueueCreate(\r
+ unsigned portBASE_TYPE uxQueueLength,\r
+ unsigned portBASE_TYPE uxItemSize\r
);\r
* </pre>\r
*\r
*\r
* @param uxQueueLength The maximum number of items that the queue can contain.\r
*\r
- * @param uxItemSize The number of bytes each item in the queue will require. \r
+ * @param uxItemSize The number of bytes each item in the queue will require.\r
* Items are queued by copy, not by reference, so this is the number of bytes\r
* that will be copied for each posted item. Each item on the queue must be\r
* the same size.\r
*\r
- * @return If the queue is successfully create then a handle to the newly \r
+ * @return If the queue is successfully create then a handle to the newly\r
* created queue is returned. If the queue cannot be created then 0 is\r
* returned.\r
- * \r
+ *\r
* Example usage:\r
<pre>\r
struct AMessage\r
/**\r
* queue. h\r
* <pre>\r
- portBASE_TYPE xQueueSend( \r
- xQueueHandle xQueue, \r
- const void * pvItemToQueue, \r
- portTickType xTicksToWait \r
+ portBASE_TYPE xQueueSendToToFront(\r
+ xQueueHandle xQueue,\r
+ const void * pvItemToQueue,\r
+ portTickType xTicksToWait\r
+ );\r
+ * </pre>\r
+ *\r
+ * This is a macro that calls xQueueGenericSend().\r
+ *\r
+ * Post an item to the front of a queue. The item is queued by copy, not by\r
+ * reference. This function must not be called from an interrupt service\r
+ * routine. See xQueueSendFromISR () for an alternative which may be used\r
+ * in an ISR.\r
+ *\r
+ * @param xQueue The handle to the queue on which the item is to be posted.\r
+ *\r
+ * @param pvItemToQueue A pointer to the item that is to be placed on the\r
+ * queue. The size of the items the queue will hold was defined when the\r
+ * queue was created, so this many bytes will be copied from pvItemToQueue\r
+ * into the queue storage area.\r
+ *\r
+ * @param xTicksToWait The maximum amount of time the task should block\r
+ * waiting for space to become available on the queue, should it already\r
+ * be full. The call will return immediately if this is set to 0. The\r
+ * time is defined in tick periods so the constant portTICK_RATE_MS\r
+ * should be used to convert to real time if this is required.\r
+ *\r
+ * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL.\r
+ *\r
+ * Example usage:\r
+ <pre>\r
+ struct AMessage\r
+ {\r
+ portCHAR ucMessageID;\r
+ portCHAR ucData[ 20 ];\r
+ } xMessage;\r
+\r
+ unsigned portLONG ulVar = 10UL;\r
+\r
+ void vATask( void *pvParameters )\r
+ {\r
+ xQueueHandle xQueue1, xQueue2;\r
+ struct AMessage *pxMessage;\r
+\r
+ // Create a queue capable of containing 10 unsigned long values.\r
+ xQueue1 = xQueueCreate( 10, sizeof( unsigned portLONG ) );\r
+\r
+ // Create a queue capable of containing 10 pointers to AMessage structures.\r
+ // These should be passed by pointer as they contain a lot of data.\r
+ xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );\r
+\r
+ // ...\r
+\r
+ if( xQueue1 != 0 )\r
+ {\r
+ // Send an unsigned long. Wait for 10 ticks for space to become\r
+ // available if necessary.\r
+ if( xQueueSendToFront( xQueue1, ( void * ) &ulVar, ( portTickType ) 10 ) != pdPASS )\r
+ {\r
+ // Failed to post the message, even after 10 ticks.\r
+ }\r
+ }\r
+\r
+ if( xQueue2 != 0 )\r
+ {\r
+ // Send a pointer to a struct AMessage object. Don't block if the\r
+ // queue is already full.\r
+ pxMessage = & xMessage;\r
+ xQueueSendToFront( xQueue2, ( void * ) &pxMessage, ( portTickType ) 0 );\r
+ }\r
+\r
+ // ... Rest of task code.\r
+ }\r
+ </pre>\r
+ * \defgroup xQueueSend xQueueSend\r
+ * \ingroup QueueManagement\r
+ */\r
+#define xQueueSendToFront( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( xQueue, pvItemToQueue, xTicksToWait, queueSEND_TO_FRONT )\r
+\r
+/**\r
+ * queue. h\r
+ * <pre>\r
+ portBASE_TYPE xQueueSendToBack(\r
+ xQueueHandle xQueue,\r
+ const void * pvItemToQueue,\r
+ portTickType xTicksToWait\r
+ );\r
+ * </pre>\r
+ *\r
+ * This is a macro that calls xQueueGenericSend().\r
+ *\r
+ * Post an item to the back of a queue. The item is queued by copy, not by\r
+ * reference. This function must not be called from an interrupt service\r
+ * routine. See xQueueSendFromISR () for an alternative which may be used\r
+ * in an ISR.\r
+ *\r
+ * @param xQueue The handle to the queue on which the item is to be posted.\r
+ *\r
+ * @param pvItemToQueue A pointer to the item that is to be placed on the\r
+ * queue. The size of the items the queue will hold was defined when the\r
+ * queue was created, so this many bytes will be copied from pvItemToQueue\r
+ * into the queue storage area.\r
+ *\r
+ * @param xTicksToWait The maximum amount of time the task should block\r
+ * waiting for space to become available on the queue, should it already\r
+ * be full. The call will return immediately if this is set to 0. The\r
+ * time is defined in tick periods so the constant portTICK_RATE_MS\r
+ * should be used to convert to real time if this is required.\r
+ *\r
+ * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL.\r
+ *\r
+ * Example usage:\r
+ <pre>\r
+ struct AMessage\r
+ {\r
+ portCHAR ucMessageID;\r
+ portCHAR ucData[ 20 ];\r
+ } xMessage;\r
+\r
+ unsigned portLONG ulVar = 10UL;\r
+\r
+ void vATask( void *pvParameters )\r
+ {\r
+ xQueueHandle xQueue1, xQueue2;\r
+ struct AMessage *pxMessage;\r
+\r
+ // Create a queue capable of containing 10 unsigned long values.\r
+ xQueue1 = xQueueCreate( 10, sizeof( unsigned portLONG ) );\r
+\r
+ // Create a queue capable of containing 10 pointers to AMessage structures.\r
+ // These should be passed by pointer as they contain a lot of data.\r
+ xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );\r
+\r
+ // ...\r
+\r
+ if( xQueue1 != 0 )\r
+ {\r
+ // Send an unsigned long. Wait for 10 ticks for space to become\r
+ // available if necessary.\r
+ if( xQueueSendToBack( xQueue1, ( void * ) &ulVar, ( portTickType ) 10 ) != pdPASS )\r
+ {\r
+ // Failed to post the message, even after 10 ticks.\r
+ }\r
+ }\r
+\r
+ if( xQueue2 != 0 )\r
+ {\r
+ // Send a pointer to a struct AMessage object. Don't block if the\r
+ // queue is already full.\r
+ pxMessage = & xMessage;\r
+ xQueueSendToBack( xQueue2, ( void * ) &pxMessage, ( portTickType ) 0 );\r
+ }\r
+\r
+ // ... Rest of task code.\r
+ }\r
+ </pre>\r
+ * \defgroup xQueueSend xQueueSend\r
+ * \ingroup QueueManagement\r
+ */\r
+#define xQueueSendToBack( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( xQueue, pvItemToQueue, xTicksToWait, queueSEND_TO_BACK )\r
+\r
+/**\r
+ * queue. h\r
+ * <pre>\r
+ portBASE_TYPE xQueueSend(\r
+ xQueueHandle xQueue,\r
+ const void * pvItemToQueue,\r
+ portTickType xTicksToWait\r
);\r
* </pre>\r
*\r
+ * This is a macro that calls xQueueGenericSend(). It is included for\r
+ * backward compatibility with versions of FreeRTOS.org that did not\r
+ * include the xQueueSendToFront() and xQueueSendToBack() macros. It is\r
+ * equivalent to xQueueSendToBack().\r
+ *\r
+ * Post an item on a queue. The item is queued by copy, not by reference.\r
+ * This function must not be called from an interrupt service routine.\r
+ * See xQueueSendFromISR () for an alternative which may be used in an ISR.\r
+ *\r
+ * @param xQueue The handle to the queue on which the item is to be posted.\r
+ *\r
+ * @param pvItemToQueue A pointer to the item that is to be placed on the\r
+ * queue. The size of the items the queue will hold was defined when the\r
+ * queue was created, so this many bytes will be copied from pvItemToQueue\r
+ * into the queue storage area.\r
+ *\r
+ * @param xTicksToWait The maximum amount of time the task should block\r
+ * waiting for space to become available on the queue, should it already\r
+ * be full. The call will return immediately if this is set to 0. The\r
+ * time is defined in tick periods so the constant portTICK_RATE_MS\r
+ * should be used to convert to real time if this is required.\r
+ *\r
+ * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL.\r
+ *\r
+ * Example usage:\r
+ <pre>\r
+ struct AMessage\r
+ {\r
+ portCHAR ucMessageID;\r
+ portCHAR ucData[ 20 ];\r
+ } xMessage;\r
+\r
+ unsigned portLONG ulVar = 10UL;\r
+\r
+ void vATask( void *pvParameters )\r
+ {\r
+ xQueueHandle xQueue1, xQueue2;\r
+ struct AMessage *pxMessage;\r
+\r
+ // Create a queue capable of containing 10 unsigned long values.\r
+ xQueue1 = xQueueCreate( 10, sizeof( unsigned portLONG ) );\r
+\r
+ // Create a queue capable of containing 10 pointers to AMessage structures.\r
+ // These should be passed by pointer as they contain a lot of data.\r
+ xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );\r
+\r
+ // ...\r
+\r
+ if( xQueue1 != 0 )\r
+ {\r
+ // Send an unsigned long. Wait for 10 ticks for space to become\r
+ // available if necessary.\r
+ if( xQueueSend( xQueue1, ( void * ) &ulVar, ( portTickType ) 10 ) != pdPASS )\r
+ {\r
+ // Failed to post the message, even after 10 ticks.\r
+ }\r
+ }\r
+\r
+ if( xQueue2 != 0 )\r
+ {\r
+ // Send a pointer to a struct AMessage object. Don't block if the\r
+ // queue is already full.\r
+ pxMessage = & xMessage;\r
+ xQueueSend( xQueue2, ( void * ) &pxMessage, ( portTickType ) 0 );\r
+ }\r
+\r
+ // ... Rest of task code.\r
+ }\r
+ </pre>\r
+ * \defgroup xQueueSend xQueueSend\r
+ * \ingroup QueueManagement\r
+ */\r
+#define xQueueSend( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( xQueue, pvItemToQueue, xTicksToWait, queueSEND_TO_BACK )\r
+\r
+\r
+/**\r
+ * queue. h\r
+ * <pre>\r
+ portBASE_TYPE xQueueGenericSend(\r
+ xQueueHandle xQueue,\r
+ const void * pvItemToQueue,\r
+ portTickType xTicksToWait\r
+ portBASE_TYPE xCopyPosition\r
+ );\r
+ * </pre>\r
+ *\r
+ * It is preferred that the macros xQueueSend(), xQueueSendToFront() and\r
+ * xQueueSendToBack() are used in place of calling this function directly.\r
+ *\r
* Post an item on a queue. The item is queued by copy, not by reference.\r
* This function must not be called from an interrupt service routine.\r
* See xQueueSendFromISR () for an alternative which may be used in an ISR.\r
*\r
* @param xQueue The handle to the queue on which the item is to be posted.\r
- * \r
- * @param pvItemToQueue A pointer to the item that is to be placed on the \r
+ *\r
+ * @param pvItemToQueue A pointer to the item that is to be placed on the\r
* queue. The size of the items the queue will hold was defined when the\r
* queue was created, so this many bytes will be copied from pvItemToQueue\r
* into the queue storage area.\r
* @param xTicksToWait The maximum amount of time the task should block\r
* waiting for space to become available on the queue, should it already\r
* be full. The call will return immediately if this is set to 0. The\r
- * time is defined in tick periods so the constant portTICK_RATE_MS \r
+ * time is defined in tick periods so the constant portTICK_RATE_MS\r
* should be used to convert to real time if this is required.\r
*\r
+ * @param xCopyPosition Can take the value queueSEND_TO_BACK to place the\r
+ * item at the back of the queue, or queueSEND_TO_FRONT to place the item\r
+ * at the front of the queue (for high priority messages).\r
+ *\r
* @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL.\r
*\r
* Example usage:\r
\r
// Create a queue capable of containing 10 pointers to AMessage structures.\r
// These should be passed by pointer as they contain a lot of data.\r
- xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );\r
+ xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );\r
+\r
+ // ...\r
+\r
+ if( xQueue1 != 0 )\r
+ {\r
+ // Send an unsigned long. Wait for 10 ticks for space to become\r
+ // available if necessary.\r
+ if( xQueueGenericSend( xQueue1, ( void * ) &ulVar, ( portTickType ) 10, queueSEND_TO_BACK ) != pdPASS )\r
+ {\r
+ // Failed to post the message, even after 10 ticks.\r
+ }\r
+ }\r
+\r
+ if( xQueue2 != 0 )\r
+ {\r
+ // Send a pointer to a struct AMessage object. Don't block if the\r
+ // queue is already full.\r
+ pxMessage = & xMessage;\r
+ xQueueGenericSend( xQueue2, ( void * ) &pxMessage, ( portTickType ) 0, queueSEND_TO_BACK );\r
+ }\r
+\r
+ // ... Rest of task code.\r
+ }\r
+ </pre>\r
+ * \defgroup xQueueSend xQueueSend\r
+ * \ingroup QueueManagement\r
+ */\r
+signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portTickType xCopyPosition );\r
+\r
+/**\r
+ * queue. h\r
+ * <pre>\r
+ portBASE_TYPE xQueuePeek(\r
+ xQueueHandle xQueue,\r
+ void *pvBuffer,\r
+ portTickType xTicksToWait\r
+ );</pre>\r
+ *\r
+ * This is a macro that calls the xQueueGenericReceive() function.\r
+ *\r
+ * Receive an item from a queue without removing the item from the queue.\r
+ * The item is received by copy so a buffer of adequate size must be\r
+ * provided. The number of bytes copied into the buffer was defined when\r
+ * the queue was created.\r
+ *\r
+ * Successfully received items remain on the queue so will be returned again\r
+ * by the next call, or a call to xQueueReceive().\r
+ *\r
+ * This macro must not be used in an interrupt service routine.\r
+ *\r
+ * @param pxQueue The handle to the queue from which the item is to be\r
+ * received.\r
+ *\r
+ * @param pvBuffer Pointer to the buffer into which the received item will\r
+ * be copied.\r
+ *\r
+ * @param xTicksToWait The maximum amount of time the task should block\r
+ * waiting for an item to receive should the queue be empty at the time\r
+ * of the call. The time is defined in tick periods so the constant\r
+ * portTICK_RATE_MS should be used to convert to real time if this is required.\r
+ *\r
+ * @return pdTRUE if an item was successfully received from the queue,\r
+ * otherwise pdFALSE.\r
+ *\r
+ * Example usage:\r
+ <pre>\r
+ struct AMessage\r
+ {\r
+ portCHAR ucMessageID;\r
+ portCHAR ucData[ 20 ];\r
+ } xMessage;\r
+\r
+ xQueueHandle xQueue;\r
+\r
+ // Task to create a queue and post a value.\r
+ void vATask( void *pvParameters )\r
+ {\r
+ struct AMessage *pxMessage;\r
+\r
+ // Create a queue capable of containing 10 pointers to AMessage structures.\r
+ // These should be passed by pointer as they contain a lot of data.\r
+ xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );\r
+ if( xQueue == 0 )\r
+ {\r
+ // Failed to create the queue.\r
+ }\r
+\r
+ // ...\r
+\r
+ // Send a pointer to a struct AMessage object. Don't block if the\r
+ // queue is already full.\r
+ pxMessage = & xMessage;\r
+ xQueueSend( xQueue, ( void * ) &pxMessage, ( portTickType ) 0 );\r
+\r
+ // ... Rest of task code.\r
+ }\r
+\r
+ // Task to peek the data from the queue.\r
+ void vADifferentTask( void *pvParameters )\r
+ {\r
+ struct AMessage *pxRxedMessage;\r
+\r
+ if( xQueue != 0 )\r
+ {\r
+ // Peek a message on the created queue. Block for 10 ticks if a\r
+ // message is not immediately available.\r
+ if( xQueuePeek( xQueue, &( pxRxedMessage ), ( portTickType ) 10 ) )\r
+ {\r
+ // pcRxedMessage now points to the struct AMessage variable posted\r
+ // by vATask, but the item still remains on the queue.\r
+ }\r
+ }\r
+\r
+ // ... Rest of task code.\r
+ }\r
+ </pre>\r
+ * \defgroup xQueueReceive xQueueReceive\r
+ * \ingroup QueueManagement\r
+ */\r
+#define xQueuePeek( xQueue, pvBuffer, xTicksToWait ) xQueueGenericReceive( xQueue, pvBuffer, xTicksToWait, pdTRUE )\r
+\r
+/**\r
+ * queue. h\r
+ * <pre>\r
+ portBASE_TYPE xQueueReceive(\r
+ xQueueHandle xQueue,\r
+ void *pvBuffer,\r
+ portTickType xTicksToWait\r
+ );</pre>\r
+ *\r
+ * This is a macro that calls the xQueueGenericReceive() function.\r
+ *\r
+ * Receive an item from a queue. The item is received by copy so a buffer of\r
+ * adequate size must be provided. The number of bytes copied into the buffer\r
+ * was defined when the queue was created.\r
+ *\r
+ * Successfully received items are removed from the queue.\r
+ *\r
+ * This function must not be used in an interrupt service routine. See\r
+ * xQueueReceiveFromISR for an alternative that can.\r
+ *\r
+ * @param pxQueue The handle to the queue from which the item is to be\r
+ * received.\r
+ *\r
+ * @param pvBuffer Pointer to the buffer into which the received item will\r
+ * be copied.\r
+ *\r
+ * @param xTicksToWait The maximum amount of time the task should block\r
+ * waiting for an item to receive should the queue be empty at the time\r
+ * of the call. The time is defined in tick periods so the constant\r
+ * portTICK_RATE_MS should be used to convert to real time if this is required.\r
+ *\r
+ * @return pdTRUE if an item was successfully received from the queue,\r
+ * otherwise pdFALSE.\r
+ *\r
+ * Example usage:\r
+ <pre>\r
+ struct AMessage\r
+ {\r
+ portCHAR ucMessageID;\r
+ portCHAR ucData[ 20 ];\r
+ } xMessage;\r
+\r
+ xQueueHandle xQueue;\r
+\r
+ // Task to create a queue and post a value.\r
+ void vATask( void *pvParameters )\r
+ {\r
+ struct AMessage *pxMessage;\r
+\r
+ // Create a queue capable of containing 10 pointers to AMessage structures.\r
+ // These should be passed by pointer as they contain a lot of data.\r
+ xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );\r
+ if( xQueue == 0 )\r
+ {\r
+ // Failed to create the queue.\r
+ }\r
\r
// ...\r
\r
- if( xQueue1 != 0 )\r
+ // Send a pointer to a struct AMessage object. Don't block if the\r
+ // queue is already full.\r
+ pxMessage = & xMessage;\r
+ xQueueSend( xQueue, ( void * ) &pxMessage, ( portTickType ) 0 );\r
+\r
+ // ... Rest of task code.\r
+ }\r
+\r
+ // Task to receive from the queue.\r
+ void vADifferentTask( void *pvParameters )\r
+ {\r
+ struct AMessage *pxRxedMessage;\r
+\r
+ if( xQueue != 0 )\r
{\r
- // Send an unsigned long. Wait for 10 ticks for space to become \r
- // available if necessary.\r
- if( xQueueSend( xQueue1, ( void * ) &ulVar, ( portTickType ) 10 ) != pdPASS )\r
+ // Receive a message on the created queue. Block for 10 ticks if a\r
+ // message is not immediately available.\r
+ if( xQueueReceive( xQueue, &( pxRxedMessage ), ( portTickType ) 10 ) )\r
{\r
- // Failed to post the message, even after 10 ticks.\r
+ // pcRxedMessage now points to the struct AMessage variable posted\r
+ // by vATask.\r
}\r
}\r
\r
- if( xQueue2 != 0 )\r
- {\r
- // Send a pointer to a struct AMessage object. Don't block if the\r
- // queue is already full.\r
- pxMessage = & xMessage;\r
- xQueueSend( xQueue2, ( void * ) &pxMessage, ( portTickType ) 0 );\r
- }\r
-\r
// ... Rest of task code.\r
}\r
</pre>\r
- * \defgroup xQueueSend xQueueSend\r
+ * \defgroup xQueueReceive xQueueReceive\r
* \ingroup QueueManagement\r
*/\r
-signed portBASE_TYPE xQueueSend( xQueueHandle xQueue, const void * pvItemToQueue, portTickType xTicksToWait );\r
+#define xQueueReceive( xQueue, pvBuffer, xTicksToWait ) xQueueGenericReceive( xQueue, pvBuffer, xTicksToWait, pdFALSE )\r
+\r
\r
/**\r
* queue. h\r
* <pre>\r
- portBASE_TYPE xQueueReceive( \r
- xQueueHandle xQueue, \r
- void *pvBuffer, \r
- portTickType xTicksToWait \r
- );</pre>\r
+ portBASE_TYPE xQueueGenericReceive(\r
+ xQueueHandle xQueue,\r
+ void *pvBuffer,\r
+ portTickType xTicksToWait\r
+ portBASE_TYPE xJustPeek\r
+ );</pre>\r
+ *\r
+ * It is preferred that the macro xQueueReceive() be used rather than calling\r
+ * this function directly.\r
*\r
- * Receive an item from a queue. The item is received by copy so a buffer of \r
+ * Receive an item from a queue. The item is received by copy so a buffer of\r
* adequate size must be provided. The number of bytes copied into the buffer\r
* was defined when the queue was created.\r
*\r
*\r
* @param pvBuffer Pointer to the buffer into which the received item will\r
* be copied.\r
- * \r
+ *\r
* @param xTicksToWait The maximum amount of time the task should block\r
* waiting for an item to receive should the queue be empty at the time\r
- * of the call. The time is defined in tick periods so the constant \r
+ * of the call. The time is defined in tick periods so the constant\r
* portTICK_RATE_MS should be used to convert to real time if this is required.\r
*\r
+ * @param xJustPeek When set to true, the item received from the queue is not\r
+ * actually removed from the queue - meaning a subsequent call to\r
+ * xQueueReceive() will return the same item. When set to false, the item\r
+ * being received from the queue is also removed from the queue.\r
+ *\r
* @return pdTRUE if an item was successfully received from the queue,\r
* otherwise pdFALSE.\r
*\r
} xMessage;\r
\r
xQueueHandle xQueue;\r
- \r
+\r
// Task to create a queue and post a value.\r
void vATask( void *pvParameters )\r
{\r
{\r
// Receive a message on the created queue. Block for 10 ticks if a\r
// message is not immediately available.\r
- if( xQueueReceive( xQueue, &( pxRxedMessage ), ( portTickType ) 10 ) )\r
+ if( xQueueGenericReceive( xQueue, &( pxRxedMessage ), ( portTickType ) 10 ) )\r
{\r
// pcRxedMessage now points to the struct AMessage variable posted\r
// by vATask.\r
* \defgroup xQueueReceive xQueueReceive\r
* \ingroup QueueManagement\r
*/\r
-signed portBASE_TYPE xQueueReceive( xQueueHandle xQueue, void *pvBuffer, portTickType xTicksToWait );\r
+signed portBASE_TYPE xQueueGenericReceive( xQueueHandle xQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeek );\r
\r
/**\r
* queue. h\r
* Return the number of messages stored in a queue.\r
*\r
* @param xQueue A handle to the queue being queried.\r
- * \r
+ *\r
* @return The number of messages available in the queue.\r
*\r
* \page uxQueueMessagesWaiting uxQueueMessagesWaiting\r
*\r
* Delete a queue - freeing all the memory allocated for storing of items\r
* placed on the queue.\r
- * \r
+ *\r
* @param xQueue A handle to the queue to be deleted.\r
*\r
* \page vQueueDelete vQueueDelete\r
/**\r
* queue. h\r
* <pre>\r
- portBASE_TYPE xQueueSendFromISR( \r
- xQueueHandle pxQueue, \r
- const void *pvItemToQueue, \r
- portBASE_TYPE xTaskPreviouslyWoken \r
+ portBASE_TYPE xQueueSendToFrontFromISR(\r
+ xQueueHandle pxQueue,\r
+ const void *pvItemToQueue,\r
+ portBASE_TYPE xTaskPreviouslyWoken\r
+ );\r
+ </pre>\r
+ *\r
+ * This is a macro that calls xQueueGenericSendFromISR().\r
+ *\r
+ * Post an item to the front of a queue. It is safe to use this macro from\r
+ * within an interrupt service routine.\r
+ *\r
+ * Items are queued by copy not reference so it is preferable to only\r
+ * queue small items, especially when called from an ISR. In most cases\r
+ * it would be preferable to store a pointer to the item being queued.\r
+ *\r
+ * @param xQueue The handle to the queue on which the item is to be posted.\r
+ *\r
+ * @param pvItemToQueue A pointer to the item that is to be placed on the\r
+ * queue. The size of the items the queue will hold was defined when the\r
+ * queue was created, so this many bytes will be copied from pvItemToQueue\r
+ * into the queue storage area.\r
+ *\r
+ * @param cTaskPreviouslyWoken This is included so an ISR can post onto\r
+ * the same queue multiple times from a single interrupt. The first call\r
+ * should always pass in pdFALSE. Subsequent calls should pass in\r
+ * the value returned from the previous call. See the file serial .c in the\r
+ * PC port for a good example of this mechanism.\r
+ *\r
+ * @return pdTRUE if a task was woken by posting onto the queue. This is\r
+ * used by the ISR to determine if a context switch may be required following\r
+ * the ISR.\r
+ *\r
+ * Example usage for buffered IO (where the ISR can obtain more than one value\r
+ * per call):\r
+ <pre>\r
+ void vBufferISR( void )\r
+ {\r
+ portCHAR cIn;\r
+ portBASE_TYPE xTaskWokenByPost;\r
+\r
+ // We have not woken a task at the start of the ISR.\r
+ cTaskWokenByPost = pdFALSE;\r
+\r
+ // Loop until the buffer is empty.\r
+ do\r
+ {\r
+ // Obtain a byte from the buffer.\r
+ cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS ); \r
+\r
+ // Post the byte. The first time round the loop cTaskWokenByPost\r
+ // will be pdFALSE. If the queue send causes a task to wake we do\r
+ // not want the task to run until we have finished the ISR, so\r
+ // xQueueSendFromISR does not cause a context switch. Also we\r
+ // don't want subsequent posts to wake any other tasks, so we store\r
+ // the return value back into cTaskWokenByPost so xQueueSendFromISR\r
+ // knows not to wake any task the next iteration of the loop.\r
+ xTaskWokenByPost = xQueueSendToFrontFromISR( xRxQueue, &cIn, cTaskWokenByPost );\r
+\r
+ } while( portINPUT_BYTE( BUFFER_COUNT ) );\r
+\r
+ // Now the buffer is empty we can switch context if necessary.\r
+ if( cTaskWokenByPost )\r
+ {\r
+ taskYIELD ();\r
+ }\r
+ }\r
+ </pre>\r
+ *\r
+ * \defgroup xQueueSendFromISR xQueueSendFromISR\r
+ * \ingroup QueueManagement\r
+ */\r
+#define xQueueSendToFromFromISR( pxQueue, pvItemToQueue, xTaskPreviouslyWoken ) xQueueGenericSendFromISR( pxQueue, pvItemToQueue, xTaskPreviouslyWoken, queueSEND_TO_FRONT )\r
+\r
+\r
+/**\r
+ * queue. h\r
+ * <pre>\r
+ portBASE_TYPE xQueueSendToBackFromISR(\r
+ xQueueHandle pxQueue,\r
+ const void *pvItemToQueue,\r
+ portBASE_TYPE xTaskPreviouslyWoken\r
+ );\r
+ </pre>\r
+ *\r
+ * This is a macro that calls xQueueGenericSendFromISR().\r
+ *\r
+ * Post an item to the back of a queue. It is safe to use this macro from\r
+ * within an interrupt service routine.\r
+ *\r
+ * Items are queued by copy not reference so it is preferable to only\r
+ * queue small items, especially when called from an ISR. In most cases\r
+ * it would be preferable to store a pointer to the item being queued.\r
+ *\r
+ * @param xQueue The handle to the queue on which the item is to be posted.\r
+ *\r
+ * @param pvItemToQueue A pointer to the item that is to be placed on the\r
+ * queue. The size of the items the queue will hold was defined when the\r
+ * queue was created, so this many bytes will be copied from pvItemToQueue\r
+ * into the queue storage area.\r
+ *\r
+ * @param cTaskPreviouslyWoken This is included so an ISR can post onto\r
+ * the same queue multiple times from a single interrupt. The first call\r
+ * should always pass in pdFALSE. Subsequent calls should pass in\r
+ * the value returned from the previous call. See the file serial .c in the\r
+ * PC port for a good example of this mechanism.\r
+ *\r
+ * @return pdTRUE if a task was woken by posting onto the queue. This is\r
+ * used by the ISR to determine if a context switch may be required following\r
+ * the ISR.\r
+ *\r
+ * Example usage for buffered IO (where the ISR can obtain more than one value\r
+ * per call):\r
+ <pre>\r
+ void vBufferISR( void )\r
+ {\r
+ portCHAR cIn;\r
+ portBASE_TYPE xTaskWokenByPost;\r
+\r
+ // We have not woken a task at the start of the ISR.\r
+ cTaskWokenByPost = pdFALSE;\r
+\r
+ // Loop until the buffer is empty.\r
+ do\r
+ {\r
+ // Obtain a byte from the buffer.\r
+ cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS ); \r
+\r
+ // Post the byte. The first time round the loop cTaskWokenByPost\r
+ // will be pdFALSE. If the queue send causes a task to wake we do\r
+ // not want the task to run until we have finished the ISR, so\r
+ // xQueueSendFromISR does not cause a context switch. Also we\r
+ // don't want subsequent posts to wake any other tasks, so we store\r
+ // the return value back into cTaskWokenByPost so xQueueSendFromISR\r
+ // knows not to wake any task the next iteration of the loop.\r
+ xTaskWokenByPost = xQueueSendToBackFromISR( xRxQueue, &cIn, cTaskWokenByPost );\r
+\r
+ } while( portINPUT_BYTE( BUFFER_COUNT ) );\r
+\r
+ // Now the buffer is empty we can switch context if necessary.\r
+ if( cTaskWokenByPost )\r
+ {\r
+ taskYIELD ();\r
+ }\r
+ }\r
+ </pre>\r
+ *\r
+ * \defgroup xQueueSendFromISR xQueueSendFromISR\r
+ * \ingroup QueueManagement\r
+ */\r
+#define xQueueSendToBackFromISR( pxQueue, pvItemToQueue, xTaskPreviouslyWoken ) xQueueGenericSendFromISR( pxQueue, pvItemToQueue, xTaskPreviouslyWoken, queueSEND_TO_BACK )\r
+\r
+\r
+/**\r
+ * queue. h\r
+ * <pre>\r
+ portBASE_TYPE xQueueSendFromISR(\r
+ xQueueHandle pxQueue,\r
+ const void *pvItemToQueue,\r
+ portBASE_TYPE xTaskPreviouslyWoken\r
);\r
</pre>\r
*\r
+ * This is a macro that calls xQueueGenericSendFromISR(). It is included\r
+ * for backward compatibility with versions of FreeRTOS.org that did not\r
+ * include the xQueueSendToBackFromISR() and xQueueSendToFrontFromISR()\r
+ * macros.\r
+ *\r
+ * Post an item to the back of a queue. It is safe to use this function from\r
+ * within an interrupt service routine.\r
+ *\r
+ * Items are queued by copy not reference so it is preferable to only\r
+ * queue small items, especially when called from an ISR. In most cases\r
+ * it would be preferable to store a pointer to the item being queued.\r
+ *\r
+ * @param xQueue The handle to the queue on which the item is to be posted.\r
+ *\r
+ * @param pvItemToQueue A pointer to the item that is to be placed on the\r
+ * queue. The size of the items the queue will hold was defined when the\r
+ * queue was created, so this many bytes will be copied from pvItemToQueue\r
+ * into the queue storage area.\r
+ *\r
+ * @param cTaskPreviouslyWoken This is included so an ISR can post onto\r
+ * the same queue multiple times from a single interrupt. The first call\r
+ * should always pass in pdFALSE. Subsequent calls should pass in\r
+ * the value returned from the previous call. See the file serial .c in the\r
+ * PC port for a good example of this mechanism.\r
+ *\r
+ * @return pdTRUE if a task was woken by posting onto the queue. This is\r
+ * used by the ISR to determine if a context switch may be required following\r
+ * the ISR.\r
+ *\r
+ * Example usage for buffered IO (where the ISR can obtain more than one value\r
+ * per call):\r
+ <pre>\r
+ void vBufferISR( void )\r
+ {\r
+ portCHAR cIn;\r
+ portBASE_TYPE xTaskWokenByPost;\r
+\r
+ // We have not woken a task at the start of the ISR.\r
+ cTaskWokenByPost = pdFALSE;\r
+\r
+ // Loop until the buffer is empty.\r
+ do\r
+ {\r
+ // Obtain a byte from the buffer.\r
+ cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS ); \r
+\r
+ // Post the byte. The first time round the loop cTaskWokenByPost\r
+ // will be pdFALSE. If the queue send causes a task to wake we do\r
+ // not want the task to run until we have finished the ISR, so\r
+ // xQueueSendFromISR does not cause a context switch. Also we\r
+ // don't want subsequent posts to wake any other tasks, so we store\r
+ // the return value back into cTaskWokenByPost so xQueueSendFromISR\r
+ // knows not to wake any task the next iteration of the loop.\r
+ xTaskWokenByPost = xQueueSendFromISR( xRxQueue, &cIn, cTaskWokenByPost );\r
+\r
+ } while( portINPUT_BYTE( BUFFER_COUNT ) );\r
+\r
+ // Now the buffer is empty we can switch context if necessary.\r
+ if( cTaskWokenByPost )\r
+ {\r
+ taskYIELD ();\r
+ }\r
+ }\r
+ </pre>\r
+ *\r
+ * \defgroup xQueueSendFromISR xQueueSendFromISR\r
+ * \ingroup QueueManagement\r
+ */\r
+#define xQueueSendFromISR( pxQueue, pvItemToQueue, xTaskPreviouslyWoken ) xQueueGenericSendFromISR( pxQueue, pvItemToQueue, xTaskPreviouslyWoken, queueSEND_TO_BACK )\r
+\r
+/**\r
+ * queue. h\r
+ * <pre>\r
+ portBASE_TYPE xQueueGenericSendFromISR(\r
+ xQueueHandle pxQueue,\r
+ const void *pvItemToQueue,\r
+ portBASE_TYPE xTaskPreviouslyWoken\r
+ portBASE_TYPE xCopyPosition\r
+ );\r
+ </pre>\r
+ *\r
+ * It is preferred that the macros xQueueSendFromISR(),\r
+ * xQueueSendToFrontFromISR() and xQueueSendToBackFromISR() be used in place\r
+ * of calling this function directly.\r
+ *\r
* Post an item on a queue. It is safe to use this function from within an\r
* interrupt service routine.\r
*\r
* it would be preferable to store a pointer to the item being queued.\r
*\r
* @param xQueue The handle to the queue on which the item is to be posted.\r
- * \r
- * @param pvItemToQueue A pointer to the item that is to be placed on the \r
+ *\r
+ * @param pvItemToQueue A pointer to the item that is to be placed on the\r
* queue. The size of the items the queue will hold was defined when the\r
* queue was created, so this many bytes will be copied from pvItemToQueue\r
* into the queue storage area.\r
* the value returned from the previous call. See the file serial .c in the\r
* PC port for a good example of this mechanism.\r
*\r
- * @return pdTRUE if a task was woken by posting onto the queue. This is \r
+ * @param xCopyPosition Can take the value queueSEND_TO_BACK to place the\r
+ * item at the back of the queue, or queueSEND_TO_FRONT to place the item\r
+ * at the front of the queue (for high priority messages).\r
+ *\r
+ * @return pdTRUE if a task was woken by posting onto the queue. This is\r
* used by the ISR to determine if a context switch may be required following\r
* the ISR.\r
*\r
// Post the byte. The first time round the loop cTaskWokenByPost\r
// will be pdFALSE. If the queue send causes a task to wake we do\r
// not want the task to run until we have finished the ISR, so\r
- // xQueueSendFromISR does not cause a context switch. Also we \r
+ // xQueueSendFromISR does not cause a context switch. Also we\r
// don't want subsequent posts to wake any other tasks, so we store\r
// the return value back into cTaskWokenByPost so xQueueSendFromISR\r
// knows not to wake any task the next iteration of the loop.\r
- xTaskWokenByPost = xQueueSendFromISR( xRxQueue, &cIn, cTaskWokenByPost );\r
+ xTaskWokenByPost = xQueueGenericSendFromISR( xRxQueue, &cIn, cTaskWokenByPost, queueSEND_TO_BACK );\r
\r
} while( portINPUT_BYTE( BUFFER_COUNT ) );\r
\r
* \defgroup xQueueSendFromISR xQueueSendFromISR\r
* \ingroup QueueManagement\r
*/\r
-signed portBASE_TYPE xQueueSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xTaskPreviouslyWoken );\r
+signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE xTaskPreviouslyWoken, portBASE_TYPE xCopyPosition );\r
\r
/**\r
* queue. h\r
* <pre>\r
- portBASE_TYPE xQueueReceiveFromISR( \r
- xQueueHandle pxQueue, \r
- void *pvBuffer, \r
- portBASE_TYPE *pxTaskWoken \r
- ); \r
+ portBASE_TYPE xQueueReceiveFromISR(\r
+ xQueueHandle pxQueue,\r
+ void *pvBuffer,\r
+ portBASE_TYPE *pxTaskWoken\r
+ );\r
* </pre>\r
*\r
* Receive an item from a queue. It is safe to use this function from within an\r
*\r
* @param pvBuffer Pointer to the buffer into which the received item will\r
* be copied.\r
- * \r
+ *\r
* @param pxTaskWoken A task may be blocked waiting for space to become\r
* available on the queue. If xQueueReceiveFromISR causes such a task to\r
* unblock *pxTaskWoken will get set to pdTRUE, otherwise *pxTaskWoken will\r
*\r
* Example usage:\r
<pre>\r
- \r
+\r
xQueueHandle xQueue;\r
- \r
+\r
// Function to create a queue and post some values.\r
void vAFunction( void *pvParameters )\r
{\r
xQueueSend( xQueue, ( void * ) &cValueToPost, xBlockTime );\r
}\r
\r
- // ISR that outputs all the characters received on the queue. \r
+ // ISR that outputs all the characters received on the queue.\r
void vISR_Routine( void )\r
{\r
portBASE_TYPE xTaskWokenByReceive = pdFALSE;\r
// A character was received. Output the character now.\r
vOutputCharacter( cRxedChar );\r
\r
- // If removing the character from the queue woke the task that was \r
+ // If removing the character from the queue woke the task that was\r
// posting onto the queue cTaskWokenByReceive will have been set to\r
// pdTRUE. No matter how many times this loop iterates only one\r
// task will be woken.\r
* \defgroup xQueueReceiveFromISR xQueueReceiveFromISR\r
* \ingroup QueueManagement\r
*/\r
-signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxTaskWoken );\r
+signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken );\r
\r
\r
-/* \r
- * The functions defined above are for passing data to and from tasks. The \r
- * functions below are the equivalents for passing data to and from \r
- * co-rtoutines.\r
+/*\r
+ * The functions defined above are for passing data to and from tasks. The\r
+ * functions below are the equivalents for passing data to and from\r
+ * co-routines.\r
*\r
* These functions are called from the co-routine macro implementation and\r
* should not be called directly from application code. Instead use the macro\r
signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait );\r
signed portBASE_TYPE xQueueCRReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait );\r
\r
-#endif\r
+/*\r
+ * For internal use only. Use xSemaphoreCreateMutex() instead of calling\r
+ * this function directly.\r
+ */\r
+xQueueHandle xQueueCreateMutex( void );\r
+\r
+#endif /* QUEUE_H */\r
\r
* as we don't want to actually store any data - we just want to know if the\r
* queue is empty or full.\r
*\r
+ * This type of semaphore can be used for pure synchronisation between tasks or\r
+ * between an interrupt and a task. The semaphore need not be given back once\r
+ * obtained, so one task/interrupt can continuously 'give' the semaphore while\r
+ * another continuously 'takes' the semaphore. For this reason this type of\r
+ * semaphore does not use a priority inheritance mechanism. For an alternative\r
+ * that does use priority inheritance see xSemaphoreCreateMutex().\r
+ *\r
* @param xSemaphore Handle to the created semaphore. Should be of type xSemaphoreHandle.\r
*\r
* Example usage:\r
* \defgroup xSemaphoreGive xSemaphoreGive\r
* \ingroup Semaphores\r
*/\r
-#define xSemaphoreGive( xSemaphore ) xQueueSend( ( xQueueHandle ) xSemaphore, NULL, semGIVE_BLOCK_TIME )\r
+#define xSemaphoreGive( xSemaphore ) xQueueGenericSend( ( xQueueHandle ) xSemaphore, NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK )\r
\r
/**\r
* semphr. h\r
* <i>Macro</i> to release a semaphore. The semaphore must of been created using \r
* vSemaphoreCreateBinary (), and obtained using xSemaphoreTake ().\r
*\r
+ * Mutex type semaphores (those created using a call to xSemaphoreCreateMutex())\r
+ * must not be used with this macro.\r
+ *\r
* This macro can be used from an ISR.\r
*\r
* @param xSemaphore A handle to the semaphore being released. This is the\r
* \defgroup xSemaphoreGiveFromISR xSemaphoreGiveFromISR\r
* \ingroup Semaphores\r
*/\r
-#define xSemaphoreGiveFromISR( xSemaphore, xTaskPreviouslyWoken ) xQueueSendFromISR( ( xQueueHandle ) xSemaphore, NULL, xTaskPreviouslyWoken )\r
+#define xSemaphoreGiveFromISR( xSemaphore, xTaskPreviouslyWoken ) xQueueGenericSendFromISR( ( xQueueHandle ) xSemaphore, NULL, xTaskPreviouslyWoken, queueSEND_TO_BACK )\r
+\r
+/**\r
+ * semphr. h\r
+ * <pre>xSemaphoreCreateMutex( xSemaphoreHandle xSemaphore )</pre>\r
+ *\r
+ * <i>Macro</i> that implements a mutex semaphore by using the existing queue \r
+ * mechanism.\r
+ *\r
+ * This type of semaphore uses a priority inheritance mechanism so a task \r
+ * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the \r
+ * semaphore it is no longer required. \r
+ *\r
+ * Mutex type semaphores cannot be used from within interrupt service routines. \r
+ *\r
+ * See xSemaphoreCreateBinary() for an alternative implemnetation that can be \r
+ * used for pure synchronisation (where one task or interrupt always 'gives' the \r
+ * semaphore and another always 'takes' the semaphore) and from within interrupt \r
+ * service routines.\r
+ *\r
+ * @param xSemaphore Handle to the created mutex semaphore. Should be of type \r
+ * xSemaphoreHandle.\r
+ *\r
+ * Example usage:\r
+ <pre>\r
+ xSemaphoreHandle xSemaphore;\r
+\r
+ void vATask( void * pvParameters )\r
+ {\r
+ // Semaphore cannot be used before a call to vSemaphoreCreateBinary ().\r
+ // This is a macro so pass the variable in directly.\r
+ vSemaphoreCreateMutex( xSemaphore );\r
+\r
+ if( xSemaphore != NULL )\r
+ {\r
+ // The semaphore was created successfully.\r
+ // The semaphore can now be used. \r
+ }\r
+ }\r
+ </pre>\r
+ * \defgroup vSemaphoreCreateMutex vSemaphoreCreateMutex\r
+ * \ingroup Semaphores\r
+ */\r
+#define xSemaphoreCreateMutex() xQueueCreateMutex()\r
+\r
\r
+#endif /* SEMAPHORE_H */\r
\r
-#endif\r
\r
* \defgroup vTaskDelayUntil vTaskDelayUntil\r
* \ingroup TaskCtrl\r
*/\r
-void vTaskDelayUntil( portTickType *pxPreviousWakeTime, portTickType xTimeIncrement );\r
+void vTaskDelayUntil( portTickType * const pxPreviousWakeTime, portTickType xTimeIncrement );\r
\r
/**\r
* task. h\r
* portTICK_RATE_MS can be used to convert kernel ticks into a real time\r
* period.\r
*/\r
-void vTaskPlaceOnEventList( xList *pxEventList, portTickType xTicksToWait );\r
+void vTaskPlaceOnEventList( const xList * const pxEventList, portTickType xTicksToWait );\r
\r
/*\r
* THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN\r
* @return pdTRUE if the task being removed has a higher priority than the task\r
* making the call, otherwise pdFALSE.\r
*/\r
-signed portBASE_TYPE xTaskRemoveFromEventList( const xList *pxEventList );\r
+signed portBASE_TYPE xTaskRemoveFromEventList( const xList * const pxEventList );\r
\r
/*\r
* THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN\r
/*\r
* Capture the current time status for future reference.\r
*/\r
-void vTaskSetTimeOutState( xTimeOutType *pxTimeOut );\r
+void vTaskSetTimeOutState( xTimeOutType * const pxTimeOut );\r
\r
/*\r
* Compare the time status now with that previously captured to see if the\r
* timeout has expired.\r
*/\r
-portBASE_TYPE xTaskCheckForTimeOut( xTimeOutType *pxTimeOut, portTickType * const pxTicksToWait );\r
+portBASE_TYPE xTaskCheckForTimeOut( xTimeOutType * const pxTimeOut, portTickType * const pxTicksToWait );\r
\r
/*\r
* Shortcut used by the queue implementation to prevent unnecessary call to\r
*/\r
portBASE_TYPE xTaskGetSchedulerState( void );\r
\r
+/*\r
+ * Raises the priority of the mutex holder to that of the calling task should\r
+ * the mutex holder have a priority less than the calling task.\r
+ */\r
+void vTaskPriorityInherit( xTaskHandle * const pxMutexHolder );\r
+\r
+/*\r
+ * Set the priority of a task back to its proper priority in the case that it\r
+ * inherited a higher priority while it was holding a semaphore.\r
+ */\r
+void vTaskPriorityDisinherit( xTaskHandle * const pxMutexHolder );\r
+\r
#endif /* TASK_H */\r
\r
\r
*/\r
void portFIRST_CONTEXT( void );\r
\r
-#define portSWITCH_CONTEXT() \r
-// asm { mov ax, seg pxCurrentTCB }\r
-// asm { mov ds, ax }\r
-// asm { les bx, pxCurrentTCB } /* Save the stack pointer into the TCB. */\r
-// asm { mov es:0x2[ bx ], ss }\r
-// asm { mov es:[ bx ], sp }\r
-// asm { call far ptr vTaskSwitchContext } /* Perform the switch. */\r
-// asm { mov ax, seg pxCurrentTCB } /* Restore the stack pointer from the TCB. */\r
-// asm { mov ds, ax }\r
-// asm { les bx, dword ptr pxCurrentTCB }\r
-// asm { mov ss, es:[ bx + 2 ] } \r
-// asm { mov sp, es:[ bx ] }\r
+#define portSWITCH_CONTEXT() \\r
+ asm { mov ax, seg pxCurrentTCB } \\r
+ asm { mov ds, ax } \\r
+ asm { les bx, pxCurrentTCB } /* Save the stack pointer into the TCB. */ \\r
+ asm { mov es:0x2[ bx ], ss } \\r
+ asm { mov es:[ bx ], sp } \\r
+ asm { call far ptr vTaskSwitchContext } /* Perform the switch. */ \\r
+ asm { mov ax, seg pxCurrentTCB } /* Restore the stack pointer from the TCB. */ \\r
+ asm { mov ds, ax } \\r
+ asm { les bx, dword ptr pxCurrentTCB } \\r
+ asm { mov ss, es:[ bx + 2 ] } \\r
+ asm { mov sp, es:[ bx ] }\r
\r
#define portFIRST_CONTEXT() \\r
asm { mov ax, seg pxCurrentTCB } \\r
asm { les bx, dword ptr pxCurrentTCB } \\r
asm { mov ss, es:[ bx + 2 ] } \\r
asm { mov sp, es:[ bx ] } \\r
- asm { pop bx } \\r
+ asm { pop bp } \\r
asm { pop di } \\r
asm { pop si } \\r
asm { pop ds } \\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
+ + 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
*/\r
\r
#define queueUNLOCKED ( ( signed portBASE_TYPE ) -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
+\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
+\r
/*\r
* Definition of the queue used by the scheduler.\r
* Items are queued by copy, not reference.\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
+ 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
} xQUEUE;\r
/*-----------------------------------------------------------*/\r
\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 xQueueSend( xQueueHandle xQueue, const void * pvItemToQueue, portTickType xTicksToWait );\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 xQueueSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xTaskPreviouslyWoken );\r
-signed portBASE_TYPE xQueueReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait );\r
-signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxTaskWoken );\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
\r
#if configUSE_CO_ROUTINES == 1\r
signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken );\r
static signed portBASE_TYPE prvIsQueueFull( const xQueueHandle pxQueue );\r
\r
/*\r
- * Macro that copies an item into the queue. This is done by copying the item\r
- * byte for byte, not by reference. Updates the queue state to ensure it's\r
- * integrity after the copy.\r
+ * Copies an item into the queue, either at the front of the queue or the\r
+ * back of the queue.\r
*/\r
-#define prvCopyQueueData( pxQueue, pvItemToQueue ) \\r
-{ \\r
- memcpy( ( void * ) pxQueue->pcWriteTo, pvItemToQueue, ( unsigned ) pxQueue->uxItemSize ); \\r
- ++( pxQueue->uxMessagesWaiting ); \\r
- pxQueue->pcWriteTo += pxQueue->uxItemSize; \\r
- if( pxQueue->pcWriteTo >= pxQueue->pcTail ) \\r
- { \\r
- pxQueue->pcWriteTo = pxQueue->pcHead; \\r
- } \\r
-}\r
+static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition );\r
+\r
+/*\r
+ * Copies an item out of a queue.\r
+ */\r
+static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer );\r
/*-----------------------------------------------------------*/\r
\r
/*\r
}\r
/*-----------------------------------------------------------*/\r
\r
-signed portBASE_TYPE xQueueSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait )\r
+#if ( configUSE_MUTEXES == 1 )\r
+\r
+ xQueueHandle xQueueCreateMutex( void )\r
+ {\r
+ xQUEUE *pxNewQueue;\r
+ \r
+ /* Allocate the new queue structure. */\r
+ pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) );\r
+ if( pxNewQueue != NULL )\r
+ {\r
+ /* Information required for priority inheritance. */\r
+ pxNewQueue->pxMutexHolder = NULL;\r
+ pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX;\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
+ /* 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->xRxLock = queueUNLOCKED;\r
+ pxNewQueue->xTxLock = queueUNLOCKED;\r
+ \r
+ /* Ensure the event queues start with the correct state. */\r
+ vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) );\r
+ vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) );\r
+\r
+ /* Start with the semaphore in the expected state. */\r
+ xQueueGenericSend( pxNewQueue, NULL, 0, queueSEND_TO_BACK );\r
+ }\r
+ \r
+ return pxNewQueue;\r
+ }\r
+\r
+#endif /* configUSE_MUTEXES */\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
xTimeOutType xTimeOut;\r
queue being modified here. Places where the event list is modified\r
include:\r
\r
- + xQueueSendFromISR(). This checks the lock on the queue to see if\r
- it has access. If the queue is locked then the Tx lock count is\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 xQueueSendFromISR().\r
+ + xQueueReceiveFromISR(). As per xQueueGenericSendFromISR().\r
*/\r
\r
/* If the queue is already full we may have to block. */\r
if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )\r
{\r
/* There is room in the queue, copy the data into the queue. */ \r
- prvCopyQueueData( pxQueue, pvItemToQueue ); \r
+ prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );\r
xReturn = pdPASS;\r
\r
/* Update the TxLock count so prvUnlockQueue knows to check for\r
}\r
/*-----------------------------------------------------------*/\r
\r
-signed portBASE_TYPE xQueueSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xTaskPreviouslyWoken )\r
+signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE xTaskPreviouslyWoken, portBASE_TYPE xCopyPosition )\r
{\r
- /* Similar to xQueueSend, except we don't block if there is no room in the\r
- queue. Also we don't directly wake a task that was blocked on a queue\r
- read, instead we return a flag to say whether a context switch is required\r
- or not (i.e. has a task with a higher priority than us been woken by this\r
- post). */\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
{\r
- prvCopyQueueData( pxQueue, pvItemToQueue );\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
}\r
/*-----------------------------------------------------------*/\r
\r
-signed portBASE_TYPE xQueueReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait )\r
+signed portBASE_TYPE xQueueGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )\r
{\r
signed portBASE_TYPE xReturn = pdTRUE;\r
xTimeOutType xTimeOut;\r
+signed portCHAR *pcOriginalReadPosition;\r
\r
- /* This function is very similar to xQueueSend(). See comments within\r
- xQueueSend() for a more detailed explanation.\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
leave with nothing? */ \r
if( xTicksToWait > ( portTickType ) 0 )\r
{\r
+ #if ( configUSE_MUTEXES == 1 )\r
+ {\r
+ if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )\r
+ {\r
+ portENTER_CRITICAL();\r
+ vTaskPriorityInherit( ( xTaskHandle * const ) pxQueue->pxMutexHolder );\r
+ portEXIT_CRITICAL();\r
+ }\r
+ }\r
+ #endif\r
+ \r
vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );\r
taskENTER_CRITICAL();\r
{\r
{\r
if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )\r
{\r
- pxQueue->pcReadFrom += pxQueue->uxItemSize;\r
- if( pxQueue->pcReadFrom >= pxQueue->pcTail )\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
- pxQueue->pcReadFrom = pxQueue->pcHead;\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
+ {\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
- --( pxQueue->uxMessagesWaiting );\r
- memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );\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
- xReturn = pdPASS;\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
else\r
{\r
}\r
/*-----------------------------------------------------------*/\r
\r
-signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxTaskWoken )\r
+signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken )\r
{\r
signed portBASE_TYPE xReturn;\r
\r
/* We cannot block from an ISR, so check there is data available. */\r
if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )\r
{\r
- /* Copy the data from the queue. */\r
- pxQueue->pcReadFrom += pxQueue->uxItemSize;\r
- if( pxQueue->pcReadFrom >= pxQueue->pcTail )\r
- {\r
- pxQueue->pcReadFrom = pxQueue->pcHead;\r
- }\r
+ prvCopyDataFromQueue( pxQueue, pvBuffer );\r
--( pxQueue->uxMessagesWaiting );\r
- memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );\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
}\r
/*-----------------------------------------------------------*/\r
\r
+static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition )\r
+{\r
+ if( pxQueue->uxItemSize == 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( ( xTaskHandle * const ) pxQueue->pxMutexHolder );\r
+ }\r
+ }\r
+ #endif\r
+ }\r
+ else if( xPosition == queueSEND_TO_BACK )\r
+ {\r
+ memcpy( ( void * ) pxQueue->pcWriteTo, pvItemToQueue, ( unsigned ) pxQueue->uxItemSize );\r
+ pxQueue->pcWriteTo += pxQueue->uxItemSize;\r
+ if( pxQueue->pcWriteTo >= pxQueue->pcTail )\r
+ {\r
+ pxQueue->pcWriteTo = pxQueue->pcHead;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ memcpy( ( void * ) pxQueue->pcReadFrom, pvItemToQueue, ( unsigned ) pxQueue->uxItemSize );\r
+ pxQueue->pcReadFrom -= pxQueue->uxItemSize;\r
+ if( pxQueue->pcReadFrom < pxQueue->pcHead )\r
+ {\r
+ pxQueue->pcReadFrom = ( pxQueue->pcTail - pxQueue->uxItemSize );\r
+ } \r
+ }\r
+\r
+ ++( pxQueue->uxMessagesWaiting );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer )\r
+{\r
+ if( pxQueue->uxQueueType != queueQUEUE_IS_MUTEX )\r
+ {\r
+ pxQueue->pcReadFrom += pxQueue->uxItemSize;\r
+ if( pxQueue->pcReadFrom >= pxQueue->pcTail )\r
+ {\r
+ pxQueue->pcReadFrom = pxQueue->pcHead;\r
+ }\r
+ memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );\r
+ } \r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
static void prvUnlockQueue( xQueueHandle pxQueue )\r
{\r
/* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. */\r
signed portBASE_TYPE xReturn;\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
+ 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( pxQueue->uxMessagesWaiting < pxQueue->uxLength )\r
{\r
/* There is room in the queue, copy the data into the queue. */ \r
- prvCopyQueueData( pxQueue, pvItemToQueue ); \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
{\r
- /* In this instance the co-routine could be placed directly \r
- into the ready list as we are within a critical section. \r
- Instead the same pending ready list mechansim is used as if\r
+ /* In this instance the co-routine could be placed directly\r
+ into the ready list as we are within a critical section.\r
+ Instead the same pending ready list mechanism is used as if\r
the event were caused from within an interrupt. */\r
if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
{\r
- /* The co-routine waiting has a higher priority so record \r
+ /* The co-routine waiting has a higher priority so record\r
that a yield might be appropriate. */\r
xReturn = errQUEUE_YIELD;\r
}\r
signed portBASE_TYPE xReturn;\r
\r
/* If the queue is already empty we may have to block. A critical section\r
- is required to prevent an interrupt adding something to the queue \r
+ is required to prevent an interrupt adding something to the queue\r
between the check to see if the queue is empty and blocking on the queue. */\r
portDISABLE_INTERRUPTS();\r
{\r
/* Were any co-routines waiting for space to become available? */\r
if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) )\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
- Instead the same pending ready list mechansim is used as if\r
+ /* In this instance the co-routine could be placed directly\r
+ into the ready list as we are within a critical section.\r
+ Instead the same pending ready list mechanism is used as if\r
the event were caused from within an interrupt. */\r
if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )\r
{\r
exit without doing anything. */\r
if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )\r
{\r
- prvCopyQueueData( pxQueue, pvItemToQueue );\r
+ prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );\r
\r
- /* We only want to wake one co-routine per ISR, so check that a \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
{\r
#define configMAX_TASK_NAME_LEN 16\r
#endif\r
\r
-#ifndef INCLUDE_xTaskGetCurrentTaskHandle\r
- #define INCLUDE_xTaskGetCurrentTaskHandle 0\r
-#endif\r
-\r
#ifndef configIDLE_SHOULD_YIELD\r
#define configIDLE_SHOULD_YIELD 1\r
#endif\r
xListItem xEventListItem; /*< List item used to place the TCB in event lists. */\r
unsigned portBASE_TYPE uxPriority; /*< The priority of the task where 0 is the lowest priority. */\r
portSTACK_TYPE *pxStack; /*< Points to the start of the stack. */\r
- unsigned portBASE_TYPE uxTCBNumber; /*< This is used for tracing the scheduler and making debugging easier only. */\r
signed portCHAR pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created. Facilitates debugging only. */\r
- unsigned portSHORT usStackDepth; /*< Total depth of the stack (when empty). This is defined as the number of variables the stack can hold, not the number of bytes. */\r
+\r
+ #if ( configUSE_TRACE_FACILITY == 1 )\r
+ unsigned portBASE_TYPE uxTCBNumber; /*< This is used for tracing the scheduler and making debugging easier only. */\r
+ #endif \r
+ \r
+ #if ( configUSE_MUTEXES == 1 )\r
+ unsigned portBASE_TYPE uxBasePriority;\r
+ #endif\r
+ \r
} tskTCB;\r
\r
/*lint -e956 */\r
* Utility to ready a TCB for a given task. Mainly just copies the parameters\r
* into the TCB structure.\r
*/\r
-static void prvInitialiseTCBVariables( tskTCB *pxTCB, unsigned portSHORT usStackDepth, const signed portCHAR * const pcName, unsigned portBASE_TYPE uxPriority );\r
+static void prvInitialiseTCBVariables( tskTCB *pxTCB, const signed portCHAR * const pcName, unsigned portBASE_TYPE uxPriority );\r
\r
/*\r
* Utility to ready all the lists used by the scheduler. This is called\r
*/\r
#if ( configUSE_TRACE_FACILITY == 1 )\r
\r
- static void prvListTaskWithinSingleList( signed portCHAR *pcWriteBuffer, xList *pxList, signed portCHAR cStatus );\r
+ static void prvListTaskWithinSingleList( const signed portCHAR *pcWriteBuffer, xList *pxList, signed portCHAR cStatus );\r
\r
#endif\r
\r
*/\r
#if ( configUSE_TRACE_FACILITY == 1 )\r
\r
- unsigned portSHORT usTaskCheckFreeStackSpace( const unsigned portCHAR *pucStackByte );\r
+ unsigned portSHORT usTaskCheckFreeStackSpace( const unsigned portCHAR * pucStackByte );\r
\r
#endif\r
\r
{\r
signed portBASE_TYPE xReturn;\r
tskTCB * pxNewTCB;\r
-static unsigned portBASE_TYPE uxTaskNumber = 0; /*lint !e956 Static is deliberate - this is guarded before use. */\r
+#if ( configUSE_TRACE_FACILITY == 1 )\r
+ static unsigned portBASE_TYPE uxTaskNumber = 0; /*lint !e956 Static is deliberate - this is guarded before use. */\r
+#endif\r
\r
/* Allocate the memory required by the TCB and stack for the new task.\r
checking that the allocation was successful. */\r
portSTACK_TYPE *pxTopOfStack;\r
\r
/* Setup the newly allocated TCB with the initial state of the task. */\r
- prvInitialiseTCBVariables( pxNewTCB, usStackDepth, pcName, uxPriority );\r
+ prvInitialiseTCBVariables( pxNewTCB, pcName, uxPriority );\r
\r
/* Calculate the top of stack address. This depends on whether the\r
stack grows from high memory to low (as per the 80x86) or visa versa.\r
required by the port. */\r
#if portSTACK_GROWTH < 0\r
{\r
- pxTopOfStack = pxNewTCB->pxStack + ( pxNewTCB->usStackDepth - 1 );\r
+ pxTopOfStack = pxNewTCB->pxStack + ( usStackDepth - 1 );\r
}\r
#else\r
{\r
uxTopUsedPriority = pxNewTCB->uxPriority;\r
}\r
\r
- /* Add a counter into the TCB for tracing only. */\r
- pxNewTCB->uxTCBNumber = uxTaskNumber;\r
- uxTaskNumber++;\r
+ #if ( configUSE_TRACE_FACILITY == 1 )\r
+ {\r
+ /* Add a counter into the TCB for tracing only. */\r
+ pxNewTCB->uxTCBNumber = uxTaskNumber;\r
+ uxTaskNumber++;\r
+ }\r
+ #endif\r
\r
prvAddTaskToReadyQueue( pxNewTCB );\r
\r
\r
#if ( INCLUDE_vTaskDelayUntil == 1 )\r
\r
- void vTaskDelayUntil( portTickType *pxPreviousWakeTime, portTickType xTimeIncrement )\r
+ void vTaskDelayUntil( portTickType * const pxPreviousWakeTime, portTickType xTimeIncrement )\r
{\r
portTickType xTimeToWake;\r
portBASE_TYPE xAlreadyYielded, xShouldDelay = pdFALSE;\r
/* If null is passed in here then we are changing the\r
priority of the calling function. */\r
pxTCB = prvGetTCBFromHandle( pxTask );\r
- uxCurrentPriority = pxTCB->uxPriority;\r
+ \r
+ #if ( configUSE_MUTEXES == 1 )\r
+ {\r
+ uxCurrentPriority = pxTCB->uxBasePriority;\r
+ }\r
+ #else\r
+ {\r
+ uxCurrentPriority = pxTCB->uxPriority;\r
+ }\r
+ #endif\r
\r
if( uxCurrentPriority != uxNewPriority )\r
{\r
/* The priority change may have readied a task of higher\r
priority than the calling task. */\r
- if( uxNewPriority > pxCurrentTCB->uxPriority ) \r
+ if( uxNewPriority > uxCurrentPriority ) \r
{\r
if( pxTask != NULL )\r
{\r
xYieldRequired = pdTRUE;\r
}\r
\r
- pxTCB->uxPriority = uxNewPriority;\r
+ \r
+\r
+ #if ( configUSE_MUTEXES == 1 )\r
+ {\r
+ /* Only change the priority being used if the task is not\r
+ currently using an inherited priority. */\r
+ if( pxTCB->uxBasePriority == pxTCB->uxPriority )\r
+ {\r
+ pxTCB->uxPriority = uxNewPriority;\r
+ }\r
+ \r
+ /* The base priority gets set whatever. */\r
+ pxTCB->uxBasePriority = uxNewPriority; \r
+ }\r
+ #else\r
+ {\r
+ pxTCB->uxPriority = uxNewPriority;\r
+ }\r
+ #endif\r
+\r
listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) uxNewPriority );\r
\r
/* If the task is in the blocked or suspended list we need do\r
{\r
/* We cannot access the delayed or ready lists, so will hold this\r
task pending until the scheduler is resumed, at which point a\r
- yield will be preformed if necessary. */\r
+ yield will be performed if necessary. */\r
vListInsertEnd( ( xList * ) &( xPendingReadyList ), &( pxTCB->xEventListItem ) );\r
}\r
}\r
}\r
/*-----------------------------------------------------------*/\r
\r
-void vTaskPlaceOnEventList( xList *pxEventList, portTickType xTicksToWait )\r
+void vTaskPlaceOnEventList( const xList * const pxEventList, portTickType xTicksToWait )\r
{\r
portTickType xTimeToWake;\r
\r
}\r
/*-----------------------------------------------------------*/\r
\r
-signed portBASE_TYPE xTaskRemoveFromEventList( const xList *pxEventList )\r
+signed portBASE_TYPE xTaskRemoveFromEventList( const xList * const pxEventList )\r
{\r
tskTCB *pxUnblockedTCB;\r
portBASE_TYPE xReturn;\r
}\r
/*-----------------------------------------------------------*/\r
\r
-void vTaskSetTimeOutState( xTimeOutType *pxTimeOut )\r
+void vTaskSetTimeOutState( xTimeOutType * const pxTimeOut )\r
{\r
pxTimeOut->xOverflowCount = xNumOfOverflows;\r
pxTimeOut->xTimeOnEntering = xTickCount;\r
}\r
/*-----------------------------------------------------------*/\r
\r
-portBASE_TYPE xTaskCheckForTimeOut( xTimeOutType *pxTimeOut, portTickType * const pxTicksToWait )\r
+portBASE_TYPE xTaskCheckForTimeOut( xTimeOutType * const pxTimeOut, portTickType * const pxTicksToWait )\r
{\r
portBASE_TYPE xReturn;\r
\r
\r
\r
\r
-static void prvInitialiseTCBVariables( tskTCB *pxTCB, unsigned portSHORT usStackDepth, const signed portCHAR * const pcName, unsigned portBASE_TYPE uxPriority )\r
+static void prvInitialiseTCBVariables( tskTCB *pxTCB, const signed portCHAR * const pcName, unsigned portBASE_TYPE uxPriority )\r
{\r
- pxTCB->usStackDepth = usStackDepth;\r
-\r
/* Store the function name in the TCB. */\r
strncpy( ( char * ) pxTCB->pcTaskName, ( const char * ) pcName, ( unsigned portSHORT ) configMAX_TASK_NAME_LEN );\r
pxTCB->pcTaskName[ ( unsigned portSHORT ) configMAX_TASK_NAME_LEN - ( unsigned portSHORT ) 1 ] = '\0';\r
}\r
\r
pxTCB->uxPriority = uxPriority;\r
+ #if ( configUSE_MUTEXES == 1 )\r
+ {\r
+ pxTCB->uxBasePriority = uxPriority;\r
+ }\r
+ #endif\r
\r
vListInitialiseItem( &( pxTCB->xGenericListItem ) );\r
vListInitialiseItem( &( pxTCB->xEventListItem ) );\r
\r
#if ( configUSE_TRACE_FACILITY == 1 )\r
\r
- static void prvListTaskWithinSingleList( signed portCHAR *pcWriteBuffer, xList *pxList, signed portCHAR cStatus )\r
+ static void prvListTaskWithinSingleList( const signed portCHAR *pcWriteBuffer, xList *pxList, signed portCHAR cStatus )\r
{\r
volatile tskTCB *pxNextTCB, *pxFirstTCB;\r
static portCHAR pcStatusString[ 50 ];\r
/*-----------------------------------------------------------*/\r
\r
#if ( configUSE_TRACE_FACILITY == 1 )\r
- unsigned portSHORT usTaskCheckFreeStackSpace( const unsigned portCHAR *pucStackByte )\r
+ unsigned portSHORT usTaskCheckFreeStackSpace( const unsigned portCHAR * pucStackByte )\r
{\r
register unsigned portSHORT usCount = 0;\r
\r
\r
#endif\r
\r
+#if ( configUSE_MUTEXES == 1 )\r
+ \r
+ void vTaskPriorityInherit( xTaskHandle * const pxMutexHolder )\r
+ {\r
+ tskTCB * const pxTCB = ( tskTCB * ) pxMutexHolder;\r
+\r
+ if( pxTCB->uxPriority < pxCurrentTCB->uxPriority )\r
+ {\r
+ /* Adjust the mutex holder state to account for its new priority. */\r
+ listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) pxCurrentTCB->uxPriority );\r
+\r
+ /* If the task being modified is in the read state it will need to\r
+ be moved in to a new list. */\r
+ if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ) )\r
+ {\r
+ vListRemove( &( pxTCB->xGenericListItem ) );\r
+\r
+ /* Inherit the priority before being moved into the new list. */\r
+ pxTCB->uxPriority = pxCurrentTCB->uxPriority;\r
+ prvAddTaskToReadyQueue( pxTCB );\r
+ }\r
+ else\r
+ {\r
+ /* Just inherit the priority. */\r
+ pxTCB->uxPriority = pxCurrentTCB->uxPriority;\r
+ }\r
+ }\r
+ }\r
+\r
+#endif\r
+\r
+#if ( configUSE_MUTEXES == 1 ) \r
+\r
+ void vTaskPriorityDisinherit( xTaskHandle * const pxMutexHolder )\r
+ {\r
+ tskTCB * const pxTCB = ( tskTCB * ) pxMutexHolder;\r
+\r
+ if( pxMutexHolder != NULL )\r
+ {\r
+ if( pxTCB->uxPriority != pxTCB->uxBasePriority )\r
+ {\r
+ /* We must be the running task to be able to give the mutex back.\r
+ Remove ourselves from the ready list we currently appear in. */\r
+ vListRemove( &( pxTCB->xGenericListItem ) );\r
+\r
+ /* Disinherit the priority before adding ourselves into the new\r
+ ready list. */\r
+ pxTCB->uxPriority = pxTCB->uxBasePriority;\r
+ listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) pxTCB->uxPriority );\r
+ prvAddTaskToReadyQueue( pxTCB );\r
+ }\r
+ }\r
+ }\r
+\r
+#endif\r
+\r
+ \r
+\r
+ \r
\r