licensing and training services.\r
*/\r
\r
+/*\r
+ * This file defines one of the more complex set of demo/test tasks. They are\r
+ * designed to stress test the queue implementation though pseudo simultaneous \r
+ * multiple reads and multiple writes from both tasks of varying priority and \r
+ * interrupts. The interrupts are prioritised such to ensure that nesting \r
+ * occurs (for those ports that support it).\r
+ *\r
+ * The test ensures that, while being accessed from three tasks and two \r
+ * interrupts, all the data sent to the queues is also received from\r
+ * the same queue, and that no duplicate items are either sent or received.\r
+ * The tests also ensure that a low priority task is never able to successfully\r
+ * read from or write to a queue when a task of higher priority is attempting\r
+ * the same operation.\r
+ */\r
+\r
/* Standard includes. */\r
#include <string.h>\r
\r
#define intqNUM_VALUES_TO_LOG ( 200 )\r
#define intqSHORT_DELAY ( 75 )\r
\r
+/* The value by which the value being sent to or received from a queue should\r
+increment past intqNUM_VALUES_TO_LOG before we check that all values have been\r
+sent/received correctly. This is done to ensure that all tasks and interrupts\r
+accessing the queue have completed their accesses with the \r
+intqNUM_VALUES_TO_LOG range. */\r
+#define intqVALUE_OVERRUN ( 50 )\r
+\r
/* The delay used by the polling task. A short delay is used for code \r
coverage. */\r
#define intqONE_TICK_DELAY ( 1 )\r
\r
+/* Each task and interrupt is given a unique identifier. This value is used to \r
+identify which task sent or received each value. The identifier is also used \r
+to distinguish between two tasks that are running the same task function. */\r
#define intqHIGH_PRIROITY_TASK1 ( ( unsigned portBASE_TYPE ) 1 )\r
#define intqHIGH_PRIROITY_TASK2 ( ( unsigned portBASE_TYPE ) 2 )\r
#define intqLOW_PRIROITY_TASK ( ( unsigned portBASE_TYPE ) 3 )\r
#define intqSECOND_INTERRUPT ( ( unsigned portBASE_TYPE ) 5 )\r
#define intqQUEUE_LENGTH ( ( unsigned portBASE_TYPE ) 10 )\r
\r
-\r
+/* At least intqMIN_ACCEPTABLE_TASK_COUNT values should be sent to/received\r
+from each queue by each task, otherwise an error is detected. */\r
#define intqMIN_ACCEPTABLE_TASK_COUNT ( 5 )\r
\r
-\r
+/* Send the next value to the queue that is normally empty. This is called\r
+from within the interrupts. */\r
#define timerNORMALLY_EMPTY_TX() \\r
if( xQueueIsQueueFullFromISR( xNormallyEmptyQueue ) != pdTRUE ) \\r
{ \\r
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \\r
} \\r
\r
+/* Send the next value to the queue that is normally full. This is called\r
+from within the interrupts. */\r
#define timerNORMALLY_FULL_TX() \\r
if( xQueueIsQueueFullFromISR( xNormallyFullQueue ) != pdTRUE ) \\r
{ \\r
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \\r
} \\r
\r
+/* Receive a value from the normally empty queue. This is called from within \r
+an interrupt. */\r
#define timerNORMALLY_EMPTY_RX() \\r
if( xQueueReceiveFromISR( xNormallyEmptyQueue, &uxRxedValue, &xHigherPriorityTaskWoken ) != pdPASS ) \\r
{ \\r
prvRecordValue_NormallyEmpty( uxRxedValue, intqSECOND_INTERRUPT ); \\r
}\r
\r
+/* Receive a value from the normally full queue. This is called from within \r
+an interrupt. */\r
#define timerNORMALLY_FULL_RX() \\r
if( xQueueReceiveFromISR( xNormallyFullQueue, &uxRxedValue, &xHigherPriorityTaskWoken ) == pdPASS ) \\r
{ \\r
} \\r
\r
\r
-\r
-\r
/*-----------------------------------------------------------*/\r
\r
/* The two queues used by the test. */\r
static xQueueHandle xNormallyEmptyQueue, xNormallyFullQueue;\r
\r
-/* Variables used to detect a stall in one of the tasts. */\r
+/* Variables used to detect a stall in one of the tasks. */\r
static unsigned portBASE_TYPE uxHighPriorityLoops1 = 0, uxHighPriorityLoops2 = 0, uxLowPriorityLoops1 = 0, uxLowPriorityLoops2 = 0;\r
\r
/* Any unexpected behaviour sets xErrorStatus to fail and log the line that\r
static portBASE_TYPE xErrorStatus = pdPASS;\r
static unsigned portBASE_TYPE xErrorLine = ( unsigned portBASE_TYPE ) 0;\r
\r
+/* Used for sequencing between tasks. */\r
static portBASE_TYPE xWasSuspended = pdFALSE;\r
\r
/* The values that are sent to the queues. An incremented value is sent each\r
xTaskHandle xHighPriorityNormallyEmptyTask1, xHighPriorityNormallyEmptyTask2, xHighPriorityNormallyFullTask1, xHighPriorityNormallyFullTask2;\r
\r
/* When a value is received in a queue the value is ticked off in the array\r
-the array position of the vlaue is set to a 1. This way missing or duplicate\r
-values can be detected. */\r
+the array position of the value is set to a the identifier of the task or \r
+interrupt that accessed the queue. This way missing or duplicate values can be \r
+detected. */\r
static unsigned portCHAR ucNormallyEmptyReceivedValues[ intqNUM_VALUES_TO_LOG ] = { 0 };\r
static unsigned portCHAR ucNormallyFullReceivedValues[ intqNUM_VALUES_TO_LOG ] = { 0 };\r
\r
static void prv1stHigherPriorityNormallyFullTask( void *pvParameters );\r
static void prv2ndHigherPriorityNormallyFullTask( void *pvParameters );\r
\r
+/* Used to mark the positions within the ucNormallyEmptyReceivedValues and\r
+ucNormallyFullReceivedValues arrays, while checking for duplicates. */\r
static void prvRecordValue_NormallyEmpty( unsigned portBASE_TYPE uxValue, unsigned portBASE_TYPE uxSource );\r
static void prvRecordValue_NormallyFull( unsigned portBASE_TYPE uxValue, unsigned portBASE_TYPE uxSource );\r
\r
if( uxValue < intqNUM_VALUES_TO_LOG )\r
{\r
/* We don't expect to receive the same value twice, so if the value\r
- has already been marked as recieved an error has occurred. */\r
+ has already been marked as received an error has occurred. */\r
if( ucNormallyFullReceivedValues[ uxValue ] != 0x00 )\r
{\r
prvQueueAccessLogError( __LINE__ );\r
if( uxValue < intqNUM_VALUES_TO_LOG )\r
{\r
/* We don't expect to receive the same value twice, so if the value\r
- has already been marked as recieved an error has occurred. */\r
+ has already been marked as received an error has occurred. */\r
if( ucNormallyEmptyReceivedValues[ uxValue ] != 0x00 )\r
{\r
prvQueueAccessLogError( __LINE__ );\r
if( ( unsigned portBASE_TYPE ) pvParameters == intqHIGH_PRIROITY_TASK1 )\r
{\r
/* Have we received all the expected values? */\r
- if( uxValueForNormallyEmptyQueue > ( intqNUM_VALUES_TO_LOG + 50 ) )\r
+ if( uxValueForNormallyEmptyQueue > ( intqNUM_VALUES_TO_LOG + intqVALUE_OVERRUN ) )\r
{\r
vTaskSuspend( xHighPriorityNormallyEmptyTask2 );\r
\r
unsigned portBASE_TYPE uxValue, uxRxed;\r
portBASE_TYPE xQueueStatus;\r
\r
- /* The paramters are not being used so avoid compiler warnings. */\r
+ /* The parameters are not being used so avoid compiler warnings. */\r
( void ) pvParameters;\r
\r
for( ;; )\r
}\r
/*-----------------------------------------------------------*/\r
\r
-portBASE_TYPE xAreIntQueueTasksStillRunning( void )\r
-{\r
-static unsigned portBASE_TYPE uxLastHighPriorityLoops1 = 0, uxLastHighPriorityLoops2 = 0, uxLastLowPriorityLoops1 = 0, uxLastLowPriorityLoops2 = 0;\r
- \r
- if( uxHighPriorityLoops1 == uxLastHighPriorityLoops1 )\r
- {\r
- prvQueueAccessLogError( __LINE__ );\r
- }\r
- \r
- uxLastHighPriorityLoops1 = uxHighPriorityLoops1;\r
- \r
- if( uxHighPriorityLoops2 == uxLastHighPriorityLoops2 )\r
- {\r
- prvQueueAccessLogError( __LINE__ );\r
- }\r
- \r
- uxLastHighPriorityLoops2 = uxHighPriorityLoops2;\r
- \r
- if( uxLowPriorityLoops1 == uxLastLowPriorityLoops1 )\r
- {\r
- prvQueueAccessLogError( __LINE__ );\r
- }\r
-\r
- uxLastLowPriorityLoops1 = uxLowPriorityLoops1;\r
-\r
- if( uxLowPriorityLoops2 == uxLastLowPriorityLoops2 )\r
- {\r
- prvQueueAccessLogError( __LINE__ );\r
- }\r
-\r
- uxLastLowPriorityLoops2 = uxLowPriorityLoops2;\r
-\r
- return xErrorStatus;\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
static void prv1stHigherPriorityNormallyFullTask( void *pvParameters )\r
{\r
unsigned portBASE_TYPE uxValueToTx, ux;\r
portBASE_TYPE xQueueStatus;\r
\r
- /* The paramters are not being used so avoid compiler warnings. */\r
+ /* The parameters are not being used so avoid compiler warnings. */\r
( void ) pvParameters;\r
\r
/* Make sure the queue starts full or near full. >> 1 as there are two\r
taskYIELD();\r
\r
/* Have all the expected values been sent to the queue? */\r
- if( uxValueToTx > ( intqNUM_VALUES_TO_LOG + 50 ) )\r
+ if( uxValueToTx > ( intqNUM_VALUES_TO_LOG + intqVALUE_OVERRUN ) )\r
{\r
/* Make sure the other high priority task completes its send of\r
any values below intqNUM_VALUE_TO_LOG. */\r
\r
if( xWasSuspended == pdTRUE )\r
{\r
- /* We would have expected the other high pririty task to have\r
+ /* We would have expected the other high priority task to have\r
set this back to false by now. */\r
prvQueueAccessLogError( __LINE__ );\r
}\r
unsigned portBASE_TYPE uxValueToTx, ux;\r
portBASE_TYPE xQueueStatus;\r
\r
- /* The paramters are not being used so avoid compiler warnings. */\r
+ /* The parameters are not being used so avoid compiler warnings. */\r
( void ) pvParameters;\r
\r
/* Make sure the queue starts full or near full. >> 1 as there are two\r
unsigned portBASE_TYPE uxValue, uxTxed = 9999;\r
portBASE_TYPE xQueueStatus;\r
\r
- /* The paramters are not being used so avoid compiler warnings. */\r
+ /* The parameters are not being used so avoid compiler warnings. */\r
( void ) pvParameters;\r
\r
for( ;; )\r
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE, uxRxedValue;\r
static unsigned portBASE_TYPE uxNextOperation = 0;\r
\r
+ /* Called from a timer interrupt. Perform various read and write\r
+ accesses on the queues. */\r
+\r
uxNextOperation++;\r
\r
if( uxNextOperation & ( unsigned portBASE_TYPE ) 0x01 )\r
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;\r
static unsigned portBASE_TYPE uxNextOperation = 0;\r
\r
+ /* Called from a timer interrupt. Perform various read and write\r
+ accesses on the queues. */\r
+\r
uxNextOperation++;\r
\r
if( uxNextOperation & ( unsigned portBASE_TYPE ) 0x01 )\r
\r
return xHigherPriorityTaskWoken;\r
}\r
+/*-----------------------------------------------------------*/\r
+\r
+\r
+portBASE_TYPE xAreIntQueueTasksStillRunning( void )\r
+{\r
+static unsigned portBASE_TYPE uxLastHighPriorityLoops1 = 0, uxLastHighPriorityLoops2 = 0, uxLastLowPriorityLoops1 = 0, uxLastLowPriorityLoops2 = 0;\r
+ \r
+ /* xErrorStatus can be set outside of this function. This function just\r
+ checks that all the tasks are still cycling. */\r
\r
+ if( uxHighPriorityLoops1 == uxLastHighPriorityLoops1 )\r
+ {\r
+ /* The high priority 1 task has stalled. */\r
+ prvQueueAccessLogError( __LINE__ );\r
+ }\r
+ \r
+ uxLastHighPriorityLoops1 = uxHighPriorityLoops1;\r
+ \r
+ if( uxHighPriorityLoops2 == uxLastHighPriorityLoops2 )\r
+ {\r
+ /* The high priority 2 task has stalled. */\r
+ prvQueueAccessLogError( __LINE__ );\r
+ }\r
+ \r
+ uxLastHighPriorityLoops2 = uxHighPriorityLoops2;\r
+ \r
+ if( uxLowPriorityLoops1 == uxLastLowPriorityLoops1 )\r
+ {\r
+ /* The low priority 1 task has stalled. */\r
+ prvQueueAccessLogError( __LINE__ );\r
+ }\r
+\r
+ uxLastLowPriorityLoops1 = uxLowPriorityLoops1;\r
+\r
+ if( uxLowPriorityLoops2 == uxLastLowPriorityLoops2 )\r
+ {\r
+ /* The low priority 2 task has stalled. */\r
+ prvQueueAccessLogError( __LINE__ );\r
+ }\r
+\r
+ uxLastLowPriorityLoops2 = uxLowPriorityLoops2;\r
+\r
+ return xErrorStatus;\r
+}\r
\r