]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Demo/Common/Minimal/QueueSet.c
Update version number ready for release.
[freertos] / FreeRTOS / Demo / Common / Minimal / QueueSet.c
index d5f44e3ca4bb1ab97be685bbfc351b2d23e9d2e8..2b405d53a211746efd942b062690719afdc86e5d 100644 (file)
@@ -1,45 +1,38 @@
 /*\r
-    FreeRTOS V7.3.0 - Copyright (C) 2012 Real Time Engineers Ltd.\r
+    FreeRTOS V8.0.1 - Copyright (C) 2014 Real Time Engineers Ltd. \r
+    All rights reserved\r
 \r
-    FEATURES AND PORTS ARE ADDED TO FREERTOS ALL THE TIME.  PLEASE VISIT\r
-    http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
+    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
 \r
     ***************************************************************************\r
      *                                                                       *\r
-     *    FreeRTOS tutorial books are available in pdf and paperback.        *\r
-     *    Complete, revised, and edited pdf reference manuals are also       *\r
-     *    available.                                                         *\r
+     *    FreeRTOS provides completely free yet professionally developed,    *\r
+     *    robust, strictly quality controlled, supported, and cross          *\r
+     *    platform software that has become a de facto standard.             *\r
      *                                                                       *\r
-     *    Purchasing FreeRTOS documentation will not only help you, by       *\r
-     *    ensuring you get running as quickly as possible and with an        *\r
-     *    in-depth knowledge of how to use FreeRTOS, it will also help       *\r
-     *    the FreeRTOS project to continue with its mission of providing     *\r
-     *    professional grade, cross platform, de facto standard solutions    *\r
-     *    for microcontrollers - completely free of charge!                  *\r
+     *    Help yourself get started quickly and support the FreeRTOS         *\r
+     *    project by purchasing a FreeRTOS tutorial book, reference          *\r
+     *    manual, or both from: http://www.FreeRTOS.org/Documentation        *\r
      *                                                                       *\r
-     *    >>> See http://www.FreeRTOS.org/Documentation for details. <<<     *\r
-     *                                                                       *\r
-     *    Thank you for using FreeRTOS, and thank you for your support!      *\r
+     *    Thank you!                                                         *\r
      *                                                                       *\r
     ***************************************************************************\r
 \r
-\r
     This file is part of the FreeRTOS distribution.\r
 \r
     FreeRTOS is free software; you can redistribute it and/or modify it under\r
     the terms of the GNU General Public License (version 2) as published by the\r
-    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.\r
-    >>>NOTE<<< The modification to the GPL is included to allow you to\r
-    distribute a combined work that includes FreeRTOS without being obliged to\r
-    provide the source code for proprietary components outside of the FreeRTOS\r
-    kernel.  FreeRTOS is distributed in the hope that it will be useful, but\r
-    WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
-    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for\r
-    more details. You should have received a copy of the GNU General Public\r
-    License and the FreeRTOS license exception along with FreeRTOS; if not it\r
-    can be viewed here: http://www.freertos.org/a00114.html and also obtained\r
-    by writing to Richard Barry, contact details for whom are available on the\r
-    FreeRTOS WEB site.\r
+    Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.\r
+\r
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<\r
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<\r
+    >>!   obliged to provide the source code for proprietary components     !<<\r
+    >>!   outside of the FreeRTOS kernel.                                   !<<\r
+\r
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
+    FOR A PARTICULAR PURPOSE.  Full license text is available from the following\r
+    link: http://www.freertos.org/a00114.html\r
 \r
     1 tab == 4 spaces!\r
 \r
      *                                                                       *\r
     ***************************************************************************\r
 \r
-\r
-    http://www.FreeRTOS.org - Documentation, training, latest versions, license\r
-    and contact details.\r
+    http://www.FreeRTOS.org - Documentation, books, training, latest versions,\r
+    license and Real Time Engineers Ltd. contact details.\r
 \r
     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
-    including FreeRTOS+Trace - an indispensable productivity tool.\r
+    including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
+    compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
+\r
+    http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High\r
+    Integrity Systems to sell under the OpenRTOS brand.  Low cost OpenRTOS\r
+    licenses offer ticketed support, indemnification and middleware.\r
 \r
-    Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell\r
-    the code with commercial support, indemnification, and middleware, under\r
-    the OpenRTOS brand: http://www.OpenRTOS.com.  High Integrity Systems also\r
-    provide a safety engineered and independently SIL3 certified version under\r
-    the SafeRTOS brand: http://www.SafeRTOS.com.\r
+    http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
+    engineered and independently SIL3 certified version for use in safety and\r
+    mission critical applications that require provable dependability.\r
+\r
+    1 tab == 4 spaces!\r
 */\r
 \r
 /*\r
@@ -79,6 +76,7 @@
  * queuesetINITIAL_ISR_TX_VALUE to ULONG_MAX.\r
  */\r
 \r
+\r
 /* Standard includes. */\r
 #include <stdlib.h>\r
 #include <limits.h>\r
@@ -109,15 +107,19 @@ in the range of 0xffff to ULONG_MAX. */
 /* The priorities used in this demo. */\r
 #define queuesetLOW_PRIORITY   ( tskIDLE_PRIORITY )\r
 #define queuesetMEDIUM_PRIORITY ( queuesetLOW_PRIORITY + 1 )\r
-#define queuesetHIGH_PRIORITY  ( queuesetMEDIUM_PRIORITY + 1 )\r
 \r
 /* For test purposes the priority of the sending task is changed after every\r
 queuesetPRIORITY_CHANGE_LOOPS number of values are sent to a queue. */\r
-#define queuesetPRIORITY_CHANGE_LOOPS  100UL\r
+#define queuesetPRIORITY_CHANGE_LOOPS  ( ( queuesetNUM_QUEUES_IN_SET * queuesetQUEUE_LENGTH ) * 2 )\r
 \r
 /* The ISR sends to the queue every queuesetISR_TX_PERIOD ticks. */\r
 #define queuesetISR_TX_PERIOD  ( 100UL )\r
 \r
+/* A delay inserted when the Tx task changes its priority to be above the idle\r
+task priority to ensure the idle priority tasks get some CPU time before the\r
+next iteration of the queue set Tx task. */\r
+#define queuesetTX_LOOP_DELAY  ( 200 / portTICK_PERIOD_MS )\r
+\r
 /* The allowable maximum deviation between a received value and the expected\r
 received value.  A deviation will occur when data is received from a queue\r
 inside an ISR in between a task receiving from a queue and the task checking\r
@@ -128,6 +130,13 @@ the received value. */
 testing of limits easier (don't have to deal with wrapping values). */\r
 #define queuesetIGNORED_BOUNDARY       ( queuesetALLOWABLE_RX_DEVIATION * 2 )\r
 \r
+typedef enum\r
+{\r
+       eEqualPriority = 0,     /* Tx and Rx tasks have the same priority. */\r
+       eTxHigherPriority,      /* The priority of the Tx task is above that of the Rx task. */\r
+       eTxLowerPriority        /* The priority of the Tx task is below that of the Rx task. */\r
+} eRelativePriorities;\r
+\r
 /*\r
  * The task that periodically sends to the queue set.\r
  */\r
@@ -157,7 +166,7 @@ static void prvSendToQueueInSetFromISR( void );
  * Create the queues and add them to a queue set before resuming the Tx\r
  * task.\r
  */\r
-static void prvSetupTest( xTaskHandle xQueueSetSendingTask );\r
+static void prvSetupTest( void );\r
 \r
 /*\r
  * Checks a value received from a queue falls within the range of expected\r
@@ -165,17 +174,29 @@ static void prvSetupTest( xTaskHandle xQueueSetSendingTask );
  */\r
 static portBASE_TYPE prvCheckReceivedValueWithinExpectedRange( unsigned long ulReceived, unsigned long ulExpectedReceived );\r
 \r
+/*\r
+ * Increase test coverage by occasionally change the priorities of the two tasks\r
+ * relative to each other. */\r
+static void prvChangeRelativePriorities( void );\r
+\r
+/*\r
+ * Local pseudo random number seed and return functions.  Used to avoid calls\r
+ * to the standard library.\r
+ */\r
+static unsigned long prvRand( void );\r
+static void prvSRand( unsigned long ulSeed );\r
+\r
 /*-----------------------------------------------------------*/\r
 \r
 /* The queues that are added to the set. */\r
-static xQueueHandle xQueues[ queuesetNUM_QUEUES_IN_SET ] = { 0 };\r
+static QueueHandle_t xQueues[ queuesetNUM_QUEUES_IN_SET ] = { 0 };\r
 \r
 /* Counts how many times each queue in the set is used to ensure all the\r
 queues are used. */\r
 static unsigned long ulQueueUsedCounter[ queuesetNUM_QUEUES_IN_SET ] = { 0 };\r
 \r
 /* The handle of the queue set to which the queues are added. */\r
-static xQueueSetHandle xQueueSet;\r
+static QueueSetHandle_t xQueueSet;\r
 \r
 /* If the prvQueueSetReceivingTask() task has not detected any errors then\r
 it increments ulCycleCounter on each iteration.\r
@@ -197,17 +218,19 @@ xAreQueeuSetTasksStillRunning() function can check it is incrementing as
 expected. */\r
 static volatile unsigned long ulISRTxValue = queuesetINITIAL_ISR_TX_VALUE;\r
 \r
+/* Used by the pseudo random number generator. */\r
+static unsigned long ulNextRand = 0;\r
+\r
+/* The task handles are stored so their priorities can be changed. */\r
+TaskHandle_t xQueueSetSendingTask, xQueueSetReceivingTask;\r
+\r
 /*-----------------------------------------------------------*/\r
 \r
 void vStartQueueSetTasks( void )\r
 {\r
-xTaskHandle xQueueSetSendingTask;\r
-\r
-       /* Create the two queues.  The handle of the sending task is passed into\r
-       the receiving task using the task parameter.  The receiving task uses the\r
-       handle to resume the sending task after it has created the queues. */\r
-       xTaskCreate( prvQueueSetSendingTask, ( signed char * ) "SetTx", configMINIMAL_STACK_SIZE, NULL, queuesetMEDIUM_PRIORITY, &xQueueSetSendingTask );\r
-       xTaskCreate( prvQueueSetReceivingTask, ( signed char * ) "SetRx", configMINIMAL_STACK_SIZE, ( void * ) xQueueSetSendingTask, queuesetMEDIUM_PRIORITY, NULL );\r
+       /* Create the tasks. */\r
+       xTaskCreate( prvQueueSetSendingTask, "SetTx", configMINIMAL_STACK_SIZE, NULL, queuesetMEDIUM_PRIORITY, &xQueueSetSendingTask );\r
+       xTaskCreate( prvQueueSetReceivingTask, "SetRx", configMINIMAL_STACK_SIZE, ( void * ) xQueueSetSendingTask, queuesetMEDIUM_PRIORITY, &xQueueSetReceivingTask );\r
 \r
        /* It is important that the sending task does not attempt to write to a\r
        queue before the queue has been created.  It is therefore placed into the\r
@@ -268,25 +291,24 @@ portBASE_TYPE xReturn = pdPASS, x;
 \r
 static void prvQueueSetSendingTask( void *pvParameters )\r
 {\r
-unsigned long ulTaskTxValue = 0;\r
-portBASE_TYPE xQueueToWriteTo;\r
-xQueueHandle xQueueInUse;\r
-unsigned portBASE_TYPE uxPriority = queuesetMEDIUM_PRIORITY, ulLoops = 0;\r
+unsigned long ulTaskTxValue = 0, ulQueueToWriteTo;\r
+QueueHandle_t xQueueInUse;\r
 \r
        /* Remove compiler warning about the unused parameter. */\r
        ( void ) pvParameters;\r
 \r
-       srand( ( unsigned int ) &ulTaskTxValue );\r
+       /* Seed mini pseudo random number generator. */\r
+       prvSRand( ( unsigned long ) &ulTaskTxValue );\r
 \r
        for( ;; )\r
        {\r
                /* Generate the index for the queue to which a value is to be sent. */\r
-               xQueueToWriteTo = rand() % queuesetNUM_QUEUES_IN_SET;\r
-               xQueueInUse = xQueues[ xQueueToWriteTo ];\r
+               ulQueueToWriteTo = prvRand() % queuesetNUM_QUEUES_IN_SET;\r
+               xQueueInUse = xQueues[ ulQueueToWriteTo ];\r
 \r
                /* Note which index is being written to to ensure all the queues are\r
                used. */\r
-               ( ulQueueUsedCounter[ xQueueToWriteTo ] )++;\r
+               ( ulQueueUsedCounter[ ulQueueToWriteTo ] )++;\r
 \r
                /* Send to the queue to unblock the task that is waiting for data to\r
                arrive on a queue within the queue set to which this queue belongs. */\r
@@ -297,6 +319,10 @@ unsigned portBASE_TYPE uxPriority = queuesetMEDIUM_PRIORITY, ulLoops = 0;
                        xQueueSetTasksStatus = pdFAIL;\r
                }\r
 \r
+               #if( configUSE_PREEMPTION == 0 )\r
+                       taskYIELD();\r
+               #endif\r
+\r
                ulTaskTxValue++;\r
 \r
                /* If the Tx value has reached the range used by the ISR then set it\r
@@ -306,19 +332,56 @@ unsigned portBASE_TYPE uxPriority = queuesetMEDIUM_PRIORITY, ulLoops = 0;
                        ulTaskTxValue = 0;\r
                }\r
 \r
-               /* Occasionally change the task priority relative to the priority of\r
-               the receiving task. */\r
-               ulLoops++;\r
-               if( ulLoops >= queuesetPRIORITY_CHANGE_LOOPS )\r
-               {\r
-                       ulLoops = 0;\r
-                       uxPriority++;\r
-                       if( uxPriority > queuesetHIGH_PRIORITY )\r
-                       {\r
-                               uxPriority = queuesetLOW_PRIORITY;\r
-                       }\r
+               /* Increase test coverage by occasionally change the priorities of the\r
+               two tasks relative to each other. */\r
+               prvChangeRelativePriorities();\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvChangeRelativePriorities( void )\r
+{\r
+static unsigned portBASE_TYPE ulLoops = 0;\r
+static eRelativePriorities ePriorities = eEqualPriority;\r
+\r
+       /* Occasionally change the task priority relative to the priority of\r
+       the receiving task. */\r
+       ulLoops++;\r
+       if( ulLoops >= queuesetPRIORITY_CHANGE_LOOPS )\r
+       {\r
+               ulLoops = 0;\r
 \r
-                       vTaskPrioritySet( NULL, uxPriority );\r
+               switch( ePriorities )\r
+               {\r
+                       case eEqualPriority:\r
+                               /* Both tasks are running with medium priority.  Now lower the\r
+                               priority of the receiving task so the Tx task has the higher\r
+                               relative priority. */\r
+                               vTaskPrioritySet( xQueueSetReceivingTask, queuesetLOW_PRIORITY );\r
+                               ePriorities = eTxHigherPriority;\r
+                               break;\r
+\r
+                       case eTxHigherPriority:\r
+                               /* The Tx task is running with a higher priority than the Rx\r
+                               task.  Switch the priorities around so the Rx task has the\r
+                               higher relative priority. */\r
+                               vTaskPrioritySet( xQueueSetReceivingTask, queuesetMEDIUM_PRIORITY );\r
+                               vTaskPrioritySet( xQueueSetSendingTask, queuesetLOW_PRIORITY );\r
+                               ePriorities = eTxLowerPriority;\r
+                               break;\r
+\r
+                       case eTxLowerPriority:\r
+                               /* The Tx task is running with a lower priority than the Rx\r
+                               task.  Make the priorities equal again. */\r
+                               vTaskPrioritySet( xQueueSetSendingTask, queuesetMEDIUM_PRIORITY );\r
+                               ePriorities = eEqualPriority;\r
+\r
+                               /* When both tasks are using a non-idle priority the queue set\r
+                               tasks will starve idle priority tasks of execution time - so\r
+                               relax a bit before the next iteration to minimise the impact. */\r
+                               vTaskDelay( queuesetTX_LOOP_DELAY );\r
+\r
+                               break;\r
                }\r
        }\r
 }\r
@@ -327,15 +390,14 @@ unsigned portBASE_TYPE uxPriority = queuesetMEDIUM_PRIORITY, ulLoops = 0;
 static void prvQueueSetReceivingTask( void *pvParameters )\r
 {\r
 unsigned long ulReceived;\r
-xQueueHandle xActivatedQueue;\r
-xTaskHandle xQueueSetSendingTask;\r
+QueueHandle_t xActivatedQueue;\r
 \r
-       /* The handle to the sending task is passed in using the task parameter. */\r
-       xQueueSetSendingTask = ( xTaskHandle ) pvParameters;\r
+       /* Remove compiler warnings. */\r
+       ( void ) pvParameters;\r
 \r
        /* Create the queues and add them to the queue set before resuming the Tx\r
        task. */\r
-       prvSetupTest( xQueueSetSendingTask );\r
+       prvSetupTest();\r
 \r
        for( ;; )\r
        {\r
@@ -423,17 +485,11 @@ static unsigned long ulExpectedReceivedFromTask = 0, ulExpectedReceivedFromISR =
                {\r
                        /* The value received is at the lower limit of the expected range.\r
                        Don't test it and expect to receive one higher next time. */\r
-                       ulExpectedReceivedFromISR++;\r
                }\r
                else if( ( ULONG_MAX - ulReceived ) <= queuesetIGNORED_BOUNDARY )\r
                {\r
                        /* The value received is at the higher limit of the expected range.\r
                        Don't test it and expect to wrap soon. */\r
-                       ulExpectedReceivedFromISR++;\r
-                       if( ulExpectedReceivedFromISR == 0 )\r
-                       {\r
-                               ulExpectedReceivedFromISR = queuesetINITIAL_ISR_TX_VALUE;\r
-                       }\r
                }\r
                else\r
                {\r
@@ -442,11 +498,15 @@ static unsigned long ulExpectedReceivedFromTask = 0, ulExpectedReceivedFromISR =
                        {\r
                                xQueueSetTasksStatus = pdFAIL;\r
                        }\r
-                       else\r
-                       {\r
-                               /* It is expected to receive an incrementing value. */\r
-                               ulExpectedReceivedFromISR++;\r
-                       }\r
+               }\r
+\r
+               configASSERT( xQueueSetTasksStatus );\r
+\r
+               /* It is expected to receive an incrementing number. */\r
+               ulExpectedReceivedFromISR++;\r
+               if( ulExpectedReceivedFromISR == 0 )\r
+               {\r
+                       ulExpectedReceivedFromISR = queuesetINITIAL_ISR_TX_VALUE;\r
                }\r
        }\r
        else\r
@@ -456,17 +516,11 @@ static unsigned long ulExpectedReceivedFromTask = 0, ulExpectedReceivedFromISR =
                {\r
                        /* The value received is at the lower limit of the expected range.\r
                        Don't test it, and expect to receive one higher next time. */\r
-                       ulExpectedReceivedFromTask++;\r
                }\r
                else if( ( ( queuesetINITIAL_ISR_TX_VALUE - 1 ) - ulReceived ) <= queuesetIGNORED_BOUNDARY )\r
                {\r
                        /* The value received is at the higher limit of the expected range.\r
                        Don't test it and expect to wrap soon. */\r
-                       ulExpectedReceivedFromTask++;\r
-                       if( ulExpectedReceivedFromTask >= queuesetINITIAL_ISR_TX_VALUE )\r
-                       {\r
-                               ulExpectedReceivedFromTask = 0;\r
-                       }\r
                }\r
                else\r
                {\r
@@ -475,11 +529,15 @@ static unsigned long ulExpectedReceivedFromTask = 0, ulExpectedReceivedFromISR =
                        {\r
                                xQueueSetTasksStatus = pdFAIL;\r
                        }\r
-                       else\r
-                       {\r
-                               /* It is expected to receive an incrementing value. */\r
-                               ulExpectedReceivedFromTask++;\r
-                       }\r
+               }\r
+\r
+               configASSERT( xQueueSetTasksStatus );\r
+\r
+               /* It is expected to receive an incrementing number. */\r
+               ulExpectedReceivedFromTask++;\r
+               if( ulExpectedReceivedFromTask >= queuesetINITIAL_ISR_TX_VALUE )\r
+               {\r
+                       ulExpectedReceivedFromTask = 0;\r
                }\r
        }\r
 }\r
@@ -512,7 +570,7 @@ portBASE_TYPE xReturn = pdPASS;
 \r
 static void prvReceiveFromQueueInSetFromISR( void )\r
 {\r
-xQueueSetMemberHandle xActivatedQueue;\r
+QueueSetMemberHandle_t xActivatedQueue;\r
 unsigned long ulReceived;\r
 \r
        /* See if any of the queues in the set contain data. */\r
@@ -559,9 +617,10 @@ static portBASE_TYPE xQueueToWriteTo = 0;
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-static void prvSetupTest( xTaskHandle xQueueSetSendingTask )\r
+static void prvSetupTest( void )\r
 {\r
 portBASE_TYPE x;\r
+unsigned long ulValueToSend = 0;\r
 \r
        /* Ensure the queues are created and the queue set configured before the\r
        sending task is unsuspended.\r
@@ -608,7 +667,18 @@ portBASE_TYPE x;
                xQueueSetTasksStatus = pdFAIL;\r
        }\r
 \r
-       /* Add the queue back again before starting the dynamic tests. */\r
+       /* Add an item to the queue before attempting to add it back into the\r
+       set. */\r
+       xQueueSend( xQueues[ 0 ], ( void * ) &ulValueToSend, 0 );\r
+       if( xQueueAddToSet( xQueues[ 0 ], xQueueSet ) != pdFAIL )\r
+       {\r
+               /* Should not be able to add a non-empty queue to a set. */\r
+               xQueueSetTasksStatus = pdFAIL;\r
+       }\r
+\r
+       /* Remove the item from the queue before adding the queue back into the\r
+       set so the dynamic tests can begin. */\r
+       xQueueReceive( xQueues[ 0 ], &ulValueToSend, 0 );\r
        if( xQueueAddToSet( xQueues[ 0 ], xQueueSet ) != pdPASS )\r
        {\r
                /* If the queue was successfully removed from the queue set then it\r
@@ -629,3 +699,17 @@ portBASE_TYPE x;
        /* Let the ISR access the queues also. */\r
        xSetupComplete = pdTRUE;\r
 }\r
+/*-----------------------------------------------------------*/\r
+\r
+static unsigned long prvRand( void )\r
+{\r
+       ulNextRand = ( ulNextRand * 1103515245UL ) + 12345UL;\r
+    return ( ulNextRand / 65536UL ) % 32768UL;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvSRand( unsigned long ulSeed )\r
+{\r
+    ulNextRand = ulSeed;\r
+}\r
+\r