/*\r
- FreeRTOS V7.5.2 - Copyright (C) 2013 Real Time Engineers Ltd.\r
+ FreeRTOS V7.6.0 - Copyright (C) 2013 Real Time Engineers Ltd. \r
+ All rights reserved\r
\r
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
\r
* queuesetINITIAL_ISR_TX_VALUE to ULONG_MAX.\r
*/\r
\r
+\r
/* Standard includes. */\r
#include <stdlib.h>\r
#include <limits.h>\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_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
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
* 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
*/\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
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( 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
\r
static void prvQueueSetSendingTask( void *pvParameters )\r
{\r
-unsigned long ulTaskTxValue = 0;\r
-portBASE_TYPE xQueueToWriteTo;\r
+unsigned long ulTaskTxValue = 0, ulQueueToWriteTo;\r
xQueueHandle xQueueInUse;\r
-unsigned portBASE_TYPE uxPriority = queuesetMEDIUM_PRIORITY, ulLoops = 0;\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
+ #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
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
- vTaskPrioritySet( NULL, uxPriority );\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
+ 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
{\r
unsigned long ulReceived;\r
xQueueHandle xActivatedQueue;\r
-xTaskHandle xQueueSetSendingTask;\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
{\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
{\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
{\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
{\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
}\r
/*-----------------------------------------------------------*/\r
\r
-static void prvSetupTest( xTaskHandle xQueueSetSendingTask )\r
+static void prvSetupTest( void )\r
{\r
portBASE_TYPE x;\r
unsigned long ulValueToSend = 0;\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