/*\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
- 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.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
+ 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
- * Demonstrates the creation an use of queue sets.\r
+ * Tests the use of queue sets.\r
*\r
* A receive task creates a number of queues and adds them to a queue set before\r
* blocking on the queue set receive. A transmit task and (optionally) an\r
* the queues and flags an error if the received message does not match that\r
* expected. The task sends values in the range 0 to\r
* queuesetINITIAL_ISR_TX_VALUE, and the ISR sends value in the range\r
- * queuesetINITIAL_ISR_TX_VALUE to 0xffffffffUL;\r
+ * queuesetINITIAL_ISR_TX_VALUE to ULONG_MAX.\r
*/\r
\r
+\r
/* Standard includes. */\r
#include <stdlib.h>\r
+#include <limits.h>\r
\r
/* Kernel includes. */\r
#include "FreeRTOS.h"\r
\r
/* Messages are sent in incrementing order from both a task and an interrupt.\r
The task sends values in the range 0 to 0xfffe, and the interrupt sends values\r
-in the range of 0xffff to 0xffffffff; */\r
+in the range of 0xffff to ULONG_MAX. */\r
#define queuesetINITIAL_ISR_TX_VALUE 0xffffUL\r
\r
/* 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
+the received value. */\r
+#define queuesetALLOWABLE_RX_DEVIATION 3\r
+\r
+/* Ignore values that are at the boundaries of allowable values to make the\r
+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
*/\r
static void prvQueueSetReceivingTask( void *pvParameters );\r
\r
+/*\r
+ * Check the value received from a queue is the expected value. Some values\r
+ * originate from the send task, some values originate from the ISR, with the\r
+ * range of the value being used to distinguish between the two message\r
+ * sources.\r
+ */\r
+static void prvCheckReceivedValue( unsigned long ulReceived );\r
+\r
+/*\r
+ * For purposes of test coverage, functions that read from and write to a\r
+ * queue set from an ISR respectively.\r
+ */\r
+static void prvReceiveFromQueueInSetFromISR( void );\r
+static void prvSendToQueueInSetFromISR( void );\r
+\r
+/*\r
+ * Create the queues and add them to a queue set before resuming the Tx\r
+ * task.\r
+ */\r
+static void prvSetupTest( void );\r
+\r
+/*\r
+ * Checks a value received from a queue falls within the range of expected\r
+ * values.\r
+ */\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
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 * ) "Check", configMINIMAL_STACK_SIZE, NULL, queuesetMEDIUM_PRIORITY, &xQueueSetSendingTask );\r
- xTaskCreate( prvQueueSetReceivingTask, ( signed char * ) "Check", 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
}\r
/*-----------------------------------------------------------*/\r
\r
-void vQueueSetWriteToQueueFromISR( void )\r
-{\r
-portBASE_TYPE x = 0;\r
-static unsigned long ulCallCount = 0;\r
-\r
- /* xSetupComplete is set to pdTRUE when the queues have been created and\r
- are available for use. */\r
- if( xSetupComplete == pdTRUE )\r
- {\r
- /* It is intended that this function is called from the tick hook\r
- function, so each call is one tick period apart. */\r
- ulCallCount++;\r
- if( ulCallCount > queuesetISR_TX_PERIOD )\r
- {\r
- ulCallCount = 0;\r
-\r
- /* Look for a queue that can be written to. */\r
- for( x = 0; x < queuesetNUM_QUEUES_IN_SET; x++ )\r
- {\r
- if( xQueues[ x ] != NULL )\r
- {\r
- /* xQueues[ x ] can be written to. Send the next value. */\r
- if( xQueueSendFromISR( xQueues[ x ], ( void * ) &ulISRTxValue, NULL ) == pdPASS )\r
- {\r
- ulISRTxValue++;\r
-\r
- /* If the Tx value has wrapped then set it back to its\r
- initial value. */\r
- if( ulISRTxValue == 0UL )\r
- {\r
- ulISRTxValue = queuesetINITIAL_ISR_TX_VALUE;\r
- }\r
- }\r
-\r
- break;\r
- }\r
- }\r
- }\r
- }\r
-}\r
-/*-----------------------------------------------------------*/\r
-\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
xQueueSetTasksStatus = pdFAIL;\r
}\r
\r
- /* Attempt to remove the queue from a queue set it does not belong\r
- to (NULL being passed as the queue set in this case). */\r
- if( xQueueRemoveFromQueueSet( xQueueInUse, NULL ) != pdFAIL )\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
+ back to 0. */\r
+ if( ulTaskTxValue == queuesetINITIAL_ISR_TX_VALUE )\r
{\r
- /* It is not possible to successfully remove a queue from a queue\r
- set it does not belong to. */\r
- xQueueSetTasksStatus = pdFAIL;\r
+ ulTaskTxValue = 0;\r
}\r
\r
- /* Mark the space in the array of queues as being empty before actually\r
- removing the queue from the queue set. This is to prevent the code\r
- that accesses the queue set from an interrupt from attempting to access\r
- a queue that is no longer in the set. */\r
- xQueues[ xQueueToWriteTo ] = 0;\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
- /* Attempt to remove the queue from the queue set it does belong to. */\r
- if( xQueueRemoveFromQueueSet( xQueueInUse, xQueueSet ) != pdPASS )\r
+ switch( ePriorities )\r
{\r
- /* It should be possible to remove the queue from the queue set it\r
- does belong to. */\r
- xQueueSetTasksStatus = pdFAIL;\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
+/*-----------------------------------------------------------*/\r
+\r
+static void prvQueueSetReceivingTask( void *pvParameters )\r
+{\r
+unsigned long ulReceived;\r
+QueueHandle_t xActivatedQueue;\r
+\r
+ /* Remove compiler warnings. */\r
+ ( void ) pvParameters;\r
\r
- /* Add the queue back before cycling back to run again. */\r
- if( xQueueAddToQueueSet( xQueueInUse, xQueueSet ) != pdPASS )\r
+ /* Create the queues and add them to the queue set before resuming the Tx\r
+ task. */\r
+ prvSetupTest();\r
+\r
+ for( ;; )\r
+ {\r
+ /* Wait for a message to arrive on one of the queues in the set. */\r
+ xActivatedQueue = xQueueSelectFromSet( xQueueSet, portMAX_DELAY );\r
+ configASSERT( xActivatedQueue );\r
+\r
+ if( xActivatedQueue == NULL )\r
{\r
- /* If the queue was successfully removed from the queue set then it\r
- should be possible to add it back in again. */\r
+ /* This should not happen as an infinite delay was used. */\r
xQueueSetTasksStatus = pdFAIL;\r
}\r
+ else\r
+ {\r
+ /* Reading from the queue should pass with a zero block time as\r
+ this task will only run when something has been posted to a task\r
+ in the queue set. */\r
+ if( xQueueReceive( xActivatedQueue, &ulReceived, queuesetDONT_BLOCK ) != pdPASS )\r
+ {\r
+ xQueueSetTasksStatus = pdFAIL;\r
+ }\r
+\r
+ /* Ensure the value received was the value expected. This function\r
+ manipulates file scope data and is also called from an ISR, hence\r
+ the critical section. */\r
+ taskENTER_CRITICAL();\r
+ {\r
+ prvCheckReceivedValue( ulReceived );\r
+ }\r
+ taskEXIT_CRITICAL();\r
+ }\r
\r
- /* Now the queue is back in the set it is ok for the interrupt that\r
- writes to the queues to access it again. */\r
- xQueues[ xQueueToWriteTo ] = xQueueInUse;\r
+ if( xQueueSetTasksStatus == pdPASS )\r
+ {\r
+ ulCycleCounter++;\r
+ }\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
\r
- ulTaskTxValue++;\r
+void vQueueSetAccessQueueSetFromISR( void )\r
+{\r
+static unsigned long ulCallCount = 0;\r
\r
- /* If the Tx value has reached the range used by the ISR then set it\r
- back to 0. */\r
- if( ulTaskTxValue == queuesetINITIAL_ISR_TX_VALUE )\r
+ /* xSetupComplete is set to pdTRUE when the queues have been created and\r
+ are available for use. */\r
+ if( xSetupComplete == pdTRUE )\r
+ {\r
+ /* It is intended that this function is called from the tick hook\r
+ function, so each call is one tick period apart. */\r
+ ulCallCount++;\r
+ if( ulCallCount > queuesetISR_TX_PERIOD )\r
{\r
- ulTaskTxValue = 0;\r
+ ulCallCount = 0;\r
+\r
+ /* First attempt to read from the queue set. */\r
+ prvReceiveFromQueueInSetFromISR();\r
+\r
+ /* Then write to the queue set. */\r
+ prvSendToQueueInSetFromISR();\r
+ }\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvCheckReceivedValue( unsigned long ulReceived )\r
+{\r
+static unsigned long ulExpectedReceivedFromTask = 0, ulExpectedReceivedFromISR = queuesetINITIAL_ISR_TX_VALUE;\r
+\r
+ /* Values are received in tasks and interrupts. It is likely that the\r
+ receiving task will sometimes get preempted by the receiving interrupt\r
+ between reading a value from the queue and calling this function. When\r
+ that happens, if the receiving interrupt calls this function the values\r
+ will get passed into this function slightly out of order. For that\r
+ reason the value passed in is tested against a small range of expected\r
+ values, rather than a single absolute value. To make the range testing\r
+ easier values in the range limits are ignored. */\r
+\r
+ /* If the received value is equal to or greater than\r
+ queuesetINITIAL_ISR_TX_VALUE then it was sent by an ISR. */\r
+ if( ulReceived >= queuesetINITIAL_ISR_TX_VALUE )\r
+ {\r
+ /* The value was sent from the ISR. */\r
+ if( ( ulReceived - queuesetINITIAL_ISR_TX_VALUE ) < queuesetIGNORED_BOUNDARY )\r
+ {\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
+ }\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
+ }\r
+ else\r
+ {\r
+ /* Check the value against its expected value range. */\r
+ if( prvCheckReceivedValueWithinExpectedRange( ulReceived, ulExpectedReceivedFromISR ) != pdPASS )\r
+ {\r
+ xQueueSetTasksStatus = pdFAIL;\r
+ }\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
+ 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
+ {\r
+ /* The value was sent from the Tx task. */\r
+ if( ulReceived < queuesetIGNORED_BOUNDARY )\r
+ {\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
+ }\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
+ }\r
+ else\r
{\r
- ulLoops = 0;\r
- uxPriority++;\r
- if( uxPriority > queuesetHIGH_PRIORITY )\r
+ /* Check the value against its expected value range. */\r
+ if( prvCheckReceivedValueWithinExpectedRange( ulReceived, ulExpectedReceivedFromTask ) != pdPASS )\r
{\r
- uxPriority = queuesetLOW_PRIORITY;\r
+ xQueueSetTasksStatus = pdFAIL;\r
}\r
+ }\r
+\r
+ configASSERT( xQueueSetTasksStatus );\r
\r
- vTaskPrioritySet( NULL, uxPriority );\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
/*-----------------------------------------------------------*/\r
\r
-static void prvQueueSetReceivingTask( void *pvParameters )\r
+static portBASE_TYPE prvCheckReceivedValueWithinExpectedRange( unsigned long ulReceived, unsigned long ulExpectedReceived )\r
{\r
-unsigned long ulReceived, ulExpectedReceivedFromTask = 0, ulExpectedReceivedFromISR = queuesetINITIAL_ISR_TX_VALUE;\r
-xQueueHandle xActivatedQueue;\r
-portBASE_TYPE x;\r
-xTaskHandle xQueueSetSendingTask;\r
+portBASE_TYPE xReturn = pdPASS;\r
+\r
+ if( ulReceived > ulExpectedReceived )\r
+ {\r
+ configASSERT( ( ulReceived - ulExpectedReceived ) <= queuesetALLOWABLE_RX_DEVIATION );\r
+ if( ( ulReceived - ulExpectedReceived ) > queuesetALLOWABLE_RX_DEVIATION )\r
+ {\r
+ xReturn = pdFALSE;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ configASSERT( ( ulExpectedReceived - ulReceived ) <= queuesetALLOWABLE_RX_DEVIATION );\r
+ if( ( ulExpectedReceived - ulReceived ) > queuesetALLOWABLE_RX_DEVIATION )\r
+ {\r
+ xReturn = pdFALSE;\r
+ }\r
+ }\r
+\r
+ return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvReceiveFromQueueInSetFromISR( void )\r
+{\r
+QueueSetMemberHandle_t xActivatedQueue;\r
+unsigned long ulReceived;\r
+\r
+ /* See if any of the queues in the set contain data. */\r
+ xActivatedQueue = xQueueSelectFromSetFromISR( xQueueSet );\r
+\r
+ if( xActivatedQueue != NULL )\r
+ {\r
+ /* Reading from the queue for test purposes only. */\r
+ if( xQueueReceiveFromISR( xActivatedQueue, &ulReceived, NULL ) != pdPASS )\r
+ {\r
+ /* Data should have been available as the handle was returned from\r
+ xQueueSelectFromSetFromISR(). */\r
+ xQueueSetTasksStatus = pdFAIL;\r
+ }\r
+\r
+ /* Ensure the value received was the value expected. */\r
+ prvCheckReceivedValue( ulReceived );\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvSendToQueueInSetFromISR( void )\r
+{\r
+static portBASE_TYPE xQueueToWriteTo = 0;\r
+\r
+ if( xQueueSendFromISR( xQueues[ xQueueToWriteTo ], ( void * ) &ulISRTxValue, NULL ) == pdPASS )\r
+ {\r
+ ulISRTxValue++;\r
+\r
+ /* If the Tx value has wrapped then set it back to its\r
+ initial value. */\r
+ if( ulISRTxValue == 0UL )\r
+ {\r
+ ulISRTxValue = queuesetINITIAL_ISR_TX_VALUE;\r
+ }\r
\r
- /* The handle to the sending task is passed in using the task parameter. */\r
- xQueueSetSendingTask = ( xTaskHandle ) pvParameters;\r
+ /* Use a different queue next time. */\r
+ xQueueToWriteTo++;\r
+ if( xQueueToWriteTo >= queuesetNUM_QUEUES_IN_SET )\r
+ {\r
+ xQueueToWriteTo = 0;\r
+ }\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\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
\r
First Create the queue set such that it will be able to hold a message for\r
every space in every queue in the set. */\r
- xQueueSet = xQueueSetCreate( queuesetNUM_QUEUES_IN_SET * queuesetQUEUE_LENGTH );\r
+ xQueueSet = xQueueCreateSet( queuesetNUM_QUEUES_IN_SET * queuesetQUEUE_LENGTH );\r
\r
for( x = 0; x < queuesetNUM_QUEUES_IN_SET; x++ )\r
{\r
unsigned long value. */\r
xQueues[ x ] = xQueueCreate( queuesetQUEUE_LENGTH, sizeof( unsigned long ) );\r
configASSERT( xQueues[ x ] );\r
- if( xQueueAddToQueueSet( xQueues[ x ], xQueueSet ) != pdPASS )\r
+ if( xQueueAddToSet( xQueues[ x ], xQueueSet ) != pdPASS )\r
{\r
xQueueSetTasksStatus = pdFAIL;\r
}\r
-\r
- /* The queue has now been added to the queue set and cannot be added to\r
- another. */\r
- if( xQueueAddToQueueSet( xQueues[ x ], xQueueSet ) != pdFAIL )\r
+ else\r
{\r
- xQueueSetTasksStatus = pdFAIL;\r
+ /* The queue has now been added to the queue set and cannot be added to\r
+ another. */\r
+ if( xQueueAddToSet( xQueues[ x ], xQueueSet ) != pdFAIL )\r
+ {\r
+ xQueueSetTasksStatus = pdFAIL;\r
+ }\r
}\r
}\r
\r
+ /* Attempt to remove a queue from a queue set it does not belong\r
+ to (NULL being passed as the queue set in this case). */\r
+ if( xQueueRemoveFromSet( xQueues[ 0 ], NULL ) != pdFAIL )\r
+ {\r
+ /* It is not possible to successfully remove a queue from a queue\r
+ set it does not belong to. */\r
+ xQueueSetTasksStatus = pdFAIL;\r
+ }\r
+\r
+ /* Attempt to remove a queue from the queue set it does belong to. */\r
+ if( xQueueRemoveFromSet( xQueues[ 0 ], xQueueSet ) != pdPASS )\r
+ {\r
+ /* It should be possible to remove the queue from the queue set it\r
+ does belong to. */\r
+ xQueueSetTasksStatus = pdFAIL;\r
+ }\r
+\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
+ should be possible to add it back in again. */\r
+ xQueueSetTasksStatus = pdFAIL;\r
+ }\r
+\r
/* The task that sends to the queues is not running yet, so attempting to\r
- read from the queue set should fail, resulting in xActivatedQueue being set\r
- to NULL. */\r
- xActivatedQueue = xQueueBlockMultiple( xQueueSet, queuesetSHORT_DELAY );\r
- configASSERT( xActivatedQueue == NULL );\r
+ read from the queue set should fail. */\r
+ if( xQueueSelectFromSet( xQueueSet, queuesetSHORT_DELAY ) != NULL )\r
+ {\r
+ xQueueSetTasksStatus = pdFAIL;\r
+ }\r
\r
/* Resume the task that writes to the queues. */\r
vTaskResume( xQueueSetSendingTask );\r
\r
/* Let the ISR access the queues also. */\r
xSetupComplete = pdTRUE;\r
+}\r
+/*-----------------------------------------------------------*/\r
\r
- for( ;; )\r
- {\r
- /* Wait for a message to arrive on one of the queues in the set. */\r
- xActivatedQueue = xQueueBlockMultiple( xQueueSet, portMAX_DELAY );\r
- configASSERT( xActivatedQueue );\r
-\r
- if( xActivatedQueue == NULL )\r
- {\r
- /* This should not happen as an infinite delay was used. */\r
- xQueueSetTasksStatus = pdFAIL;\r
- }\r
- else\r
- {\r
- /* Reading from the queue should pass with a zero block time as\r
- this task will only run when something has been posted to a task\r
- in the queue set. */\r
- if( xQueueReceive( xActivatedQueue, &ulReceived, queuesetDONT_BLOCK ) != pdPASS )\r
- {\r
- xQueueSetTasksStatus = pdFAIL;\r
- }\r
-\r
- /* If the received value is equal to or greater than\r
- queuesetINITIAL_ISR_TX_VALUE then it was sent by an ISR. */\r
- if( ulReceived >= queuesetINITIAL_ISR_TX_VALUE )\r
- {\r
- /* The value was sent from the ISR. Check it against its\r
- expected value. */\r
- configASSERT( ulReceived == ulExpectedReceivedFromISR );\r
- if( ulReceived != ulExpectedReceivedFromISR )\r
- {\r
- xQueueSetTasksStatus = pdFAIL;\r
- }\r
- else\r
- {\r
- /* It is expected to receive an incrementing value. */\r
- ulExpectedReceivedFromISR++;\r
-\r
- /* If the expected value has wrapped then set it back to\r
- its initial value. */\r
- if( ulExpectedReceivedFromISR == 0 )\r
- {\r
- ulExpectedReceivedFromISR = queuesetINITIAL_ISR_TX_VALUE;\r
- }\r
- }\r
- }\r
- else\r
- {\r
- /* The value was sent from the Tx task. Check it against its\r
- expected value. */\r
- configASSERT( ulReceived == ulExpectedReceivedFromTask );\r
- if( ulReceived != ulExpectedReceivedFromTask )\r
- {\r
- xQueueSetTasksStatus = pdFAIL;\r
- }\r
- else\r
- {\r
- /* It is expected to receive an incrementing value. */\r
- ulExpectedReceivedFromTask++;\r
-\r
- /* If the expected value has reached the range of values\r
- used by the ISR then set it back to 0. */\r
- if( ulExpectedReceivedFromTask >= queuesetINITIAL_ISR_TX_VALUE )\r
- {\r
- ulExpectedReceivedFromTask = 0;\r
- }\r
- }\r
- }\r
- }\r
+static unsigned long prvRand( void )\r
+{\r
+ ulNextRand = ( ulNextRand * 1103515245UL ) + 12345UL;\r
+ return ( ulNextRand / 65536UL ) % 32768UL;\r
+}\r
+/*-----------------------------------------------------------*/\r
\r
- if( xQueueSetTasksStatus == pdPASS )\r
- {\r
- ulCycleCounter++;\r
- }\r
- }\r
+static void prvSRand( unsigned long ulSeed )\r
+{\r
+ ulNextRand = ulSeed;\r
}\r
\r