/*\r
- FreeRTOS V7.3.0 - Copyright (C) 2012 Real Time Engineers Ltd.\r
+ FreeRTOS V7.6.0 - Copyright (C) 2013 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 distribute\r
+ >>! a combined work that includes FreeRTOS without being obliged to provide\r
+ >>! the source code for proprietary components outside of the FreeRTOS\r
+ >>! 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
- * 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 a queue set receive. A transmit task repeatedly unblocks the\r
- * receive task by sending messages to the queues in a pseudo random order.\r
- * The receive task removes the messages from the queues and flags an error if\r
- * the received message does not match that expected.\r
+ * blocking on the queue set receive. A transmit task and (optionally) an\r
+ * interrupt repeatedly unblocks the receive task by sending messages to the\r
+ * queues in a pseudo random order. The receive task removes the messages from\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 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
+#include "FreeRTOS.h"\r
#include "task.h"\r
#include "queue.h"\r
\r
#define queuesetSHORT_DELAY 200\r
#define queuesetDONT_BLOCK 0\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 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
+\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 ( ( 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_RATE_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
\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
\r
xAreQueueSetTasksStillRunning() returns pdPASS if the value of\r
ulCycleCounter has changed between consecutive calls, and pdFALSE if\r
ulCycleCounter has stopped incrementing (indicating an error condition). */\r
-volatile unsigned long ulCycleCounter = 0UL;\r
+static volatile unsigned long ulCycleCounter = 0UL;\r
\r
/* Set to pdFAIL if an error is detected by any queue set task.\r
ulCycleCounter will only be incremented if xQueueSetTasksSatus equals pdPASS. */\r
-volatile portBASE_TYPE xQueueSetTasksStatus = pdPASS;\r
+static volatile portBASE_TYPE xQueueSetTasksStatus = pdPASS;\r
+\r
+/* Just a flag to let the function that writes to a queue from an ISR know that\r
+the queues are setup and can be used. */\r
+static volatile portBASE_TYPE xSetupComplete = pdFALSE;\r
+\r
+/* The value sent to the queue from the ISR is file scope so the\r
+xAreQueeuSetTasksStillRunning() function can check it is incrementing as\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
+xTaskHandle xQueueSetSendingTask, xQueueSetReceivingTask;\r
\r
/*-----------------------------------------------------------*/\r
\r
-void vStartQueueSetTasks( unsigned portBASE_TYPE uxPriority )\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, uxPriority, &xQueueSetSendingTask );\r
- xTaskCreate( prvQueueSetReceivingTask, ( signed char * ) "Check", configMINIMAL_STACK_SIZE, ( void * ) xQueueSetSendingTask, uxPriority, 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
portBASE_TYPE xAreQueueSetTasksStillRunning( void )\r
{\r
-static unsigned long ulLastCycleCounter;\r
-portBASE_TYPE xReturn;\r
+static unsigned long ulLastCycleCounter, ulLastISRTxValue = 0;\r
+static unsigned long ulLastQueueUsedCounter[ queuesetNUM_QUEUES_IN_SET ] = { 0 };\r
+portBASE_TYPE xReturn = pdPASS, x;\r
\r
if( ulLastCycleCounter == ulCycleCounter )\r
{\r
tasks is stalled or an error has been detected. */\r
xReturn = pdFAIL;\r
}\r
+\r
+ ulLastCycleCounter = ulCycleCounter;\r
+\r
+ /* Ensure that all the queues in the set have been used. This ensures the\r
+ test is working as intended and guards against the rand() in the Tx task\r
+ missing some values. */\r
+ for( x = 0; x < queuesetNUM_QUEUES_IN_SET; x++ )\r
+ {\r
+ if( ulLastQueueUsedCounter[ x ] == ulQueueUsedCounter[ x ] )\r
+ {\r
+ xReturn = pdFAIL;\r
+ }\r
+\r
+ ulLastQueueUsedCounter[ x ] = ulQueueUsedCounter[ x ];\r
+ }\r
+\r
+ /* Check the global status flag. */\r
+ if( xQueueSetTasksStatus != pdPASS )\r
+ {\r
+ xReturn = pdFAIL;\r
+ }\r
+\r
+ /* Check that the ISR is still sending values to the queues too. */\r
+ if( ulISRTxValue == ulLastISRTxValue )\r
+ {\r
+ xReturn = pdFAIL;\r
+ }\r
else\r
{\r
- xReturn = pdPASS;\r
+ ulLastISRTxValue = ulISRTxValue;\r
}\r
\r
return xReturn;\r
\r
static void prvQueueSetSendingTask( void *pvParameters )\r
{\r
-unsigned long ulTxValue = 0;\r
-portBASE_TYPE xQueueToWriteTo;\r
+unsigned long ulTaskTxValue = 0, ulQueueToWriteTo;\r
+xQueueHandle xQueueInUse;\r
\r
/* Remove compiler warning about the unused parameter. */\r
( void ) pvParameters;\r
\r
- srand( ( unsigned int ) &ulTxValue );\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
- if( xQueueSendToBack( xQueues[ xQueueToWriteTo ], &ulTxValue, portMAX_DELAY ) != pdPASS )\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[ 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
+ if( xQueueSendToBack( xQueueInUse, &ulTaskTxValue, portMAX_DELAY ) != pdPASS )\r
{\r
/* The send should always pass as an infinite block time was\r
used. */\r
xQueueSetTasksStatus = pdFAIL;\r
}\r
\r
- ulTxValue++;\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
+ ulTaskTxValue = 0;\r
+ }\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 prvQueueSetReceivingTask( void *pvParameters )\r
+static void prvChangeRelativePriorities( void )\r
{\r
-unsigned long ulReceived, ulLastReceived = ~0UL;\r
-xQueueHandle xActivatedQueue;\r
-portBASE_TYPE x;\r
-xTaskHandle xQueueSetSendingTask;\r
-\r
- /* The handle to the sending task is passed in using the task parameter. */\r
- xQueueSetSendingTask = ( xTaskHandle ) pvParameters;\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
+static unsigned portBASE_TYPE ulLoops = 0;\r
+static eRelativePriorities ePriorities = eEqualPriority;\r
\r
- for( x = 0; x < queuesetNUM_QUEUES_IN_SET; x++ )\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
- /* Create the queue and add it to the set. */\r
- xQueues[ x ] = xQueueCreate( queuesetQUEUE_LENGTH, sizeof( unsigned long ) );\r
- configASSERT( xQueues[ x ] );\r
- if( xQueueAddToQueueSet( xQueues[ x ], xQueueSet ) != pdPASS )\r
- {\r
- xQueueSetTasksStatus = pdFAIL;\r
- }\r
+ ulLoops = 0;\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
+ switch( ePriorities )\r
{\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
- /* 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 = xQueueReadMultiple( xQueueSet, queuesetSHORT_DELAY );\r
- configASSERT( xActivatedQueue == NULL );\r
+static void prvQueueSetReceivingTask( void *pvParameters )\r
+{\r
+unsigned long ulReceived;\r
+xQueueHandle xActivatedQueue;\r
\r
- /* Resume the task that writes to the queues. */\r
- vTaskResume( xQueueSetSendingTask );\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();\r
\r
for( ;; )\r
{\r
/* Wait for a message to arrive on one of the queues in the set. */\r
- xActivatedQueue = xQueueReadMultiple( xQueueSet, portMAX_DELAY );\r
+ xActivatedQueue = xQueueSelectFromSet( xQueueSet, portMAX_DELAY );\r
configASSERT( xActivatedQueue );\r
\r
if( xActivatedQueue == NULL )\r
xQueueSetTasksStatus = pdFAIL;\r
}\r
\r
- /* It is always expected that the received value will be one\r
- greater than the previously received value. */\r
- configASSERT( ulReceived == ( ulLastReceived + 1 ) );\r
- if( ulReceived != ( ulLastReceived + 1 ) )\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
+ if( xQueueSetTasksStatus == pdPASS )\r
+ {\r
+ ulCycleCounter++;\r
+ }\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vQueueSetAccessQueueSetFromISR( void )\r
+{\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
+ /* 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
- else\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
+ {\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
+ /* Check the value against its expected value range. */\r
+ if( prvCheckReceivedValueWithinExpectedRange( ulReceived, ulExpectedReceivedFromTask ) != pdPASS )\r
{\r
- ulLastReceived = ulReceived;\r
+ xQueueSetTasksStatus = pdFAIL;\r
}\r
}\r
\r
- if( xQueueSetTasksStatus == pdPASS )\r
+ configASSERT( xQueueSetTasksStatus );\r
+\r
+ /* It is expected to receive an incrementing number. */\r
+ ulExpectedReceivedFromTask++;\r
+ if( ulExpectedReceivedFromTask >= queuesetINITIAL_ISR_TX_VALUE )\r
{\r
- ulCycleCounter++;\r
+ ulExpectedReceivedFromTask = 0;\r
+ }\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static portBASE_TYPE prvCheckReceivedValueWithinExpectedRange( unsigned long ulReceived, unsigned long ulExpectedReceived )\r
+{\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
+xQueueSetMemberHandle 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
+ /* 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 = xQueueCreateSet( queuesetNUM_QUEUES_IN_SET * queuesetQUEUE_LENGTH );\r
+\r
+ for( x = 0; x < queuesetNUM_QUEUES_IN_SET; x++ )\r
+ {\r
+ /* Create the queue and add it to the set. The queue is just holding\r
+ unsigned long value. */\r
+ xQueues[ x ] = xQueueCreate( queuesetQUEUE_LENGTH, sizeof( unsigned long ) );\r
+ configASSERT( xQueues[ x ] );\r
+ if( xQueueAddToSet( xQueues[ x ], xQueueSet ) != pdPASS )\r
+ {\r
+ xQueueSetTasksStatus = pdFAIL;\r
+ }\r
+ else\r
+ {\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. */\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
+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