]> git.sur5r.net Git - freertos/commitdiff
Add new test file.
authorRichardBarry <RichardBarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Sun, 18 May 2008 16:21:59 +0000 (16:21 +0000)
committerRichardBarry <RichardBarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Sun, 18 May 2008 16:21:59 +0000 (16:21 +0000)
git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@353 1d2547de-c912-0410-9cb9-b8ca96c0e9e2

Demo/Common/Minimal/IntQueue.c [new file with mode: 0644]

diff --git a/Demo/Common/Minimal/IntQueue.c b/Demo/Common/Minimal/IntQueue.c
new file mode 100644 (file)
index 0000000..02753ef
--- /dev/null
@@ -0,0 +1,643 @@
+/*\r
+       FreeRTOS.org V5.0.0 - Copyright (C) 2003-2008 Richard Barry.\r
+\r
+       This file is part of the FreeRTOS.org distribution.\r
+\r
+       FreeRTOS.org is free software; you can redistribute it and/or modify\r
+       it under the terms of the GNU General Public License as published by\r
+       the Free Software Foundation; either version 2 of the License, or\r
+       (at your option) any later version.\r
+\r
+       FreeRTOS.org is distributed in the hope that it will be useful,\r
+       but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+       GNU General Public License for more details.\r
+\r
+       You should have received a copy of the GNU General Public License\r
+       along with FreeRTOS.org; if not, write to the Free Software\r
+       Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+\r
+       A special exception to the GPL can be applied should you wish to distribute\r
+       a combined work that includes FreeRTOS.org, without being obliged to provide\r
+       the source code for any proprietary components.  See the licensing section\r
+       of http://www.FreeRTOS.org for full details of how and when the exception\r
+       can be applied.\r
+\r
+    ***************************************************************************\r
+    ***************************************************************************\r
+    *                                                                         *\r
+    * SAVE TIME AND MONEY!  We can port FreeRTOS.org to your own hardware,    *\r
+    * and even write all or part of your application on your behalf.          *\r
+    * See http://www.OpenRTOS.com for details of the services we provide to   *\r
+    * expedite your project.                                                  *\r
+    *                                                                         *\r
+    ***************************************************************************\r
+    ***************************************************************************\r
+\r
+       Please ensure to read the configuration and relevant port sections of the\r
+       online documentation.\r
+\r
+       http://www.FreeRTOS.org - Documentation, latest information, license and \r
+       contact details.\r
+\r
+       http://www.SafeRTOS.com - A version that is certified for use in safety \r
+       critical systems.\r
+\r
+       http://www.OpenRTOS.com - Commercial support, development, porting, \r
+       licensing and training services.\r
+*/\r
+\r
+/* Standard includes. */\r
+#include <string.h>\r
+\r
+/* SafeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "queue.h"\r
+#include "task.h"\r
+\r
+/* Demo app includes. */\r
+#include "IntQueue.h"\r
+#include "IntQueueTimer.h"\r
+\r
+/* Priorities used by test tasks. */\r
+#define intqHIGHER_PRIORITY            1\r
+#define intqLOWER_PRIORITY             0\r
+\r
+/* The number of values to send/receive before checking that all values were\r
+processed as expected. */\r
+#define intqNUM_VALUES_TO_LOG  ( 200 )\r
+#define intqSHORT_DELAY                        ( 75 )\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
+#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 intqFIRST_INTERRUPT            ( ( unsigned portBASE_TYPE ) 4 )\r
+#define intqSECOND_INTERRUPT   ( ( unsigned portBASE_TYPE ) 5 )\r
+#define intqQUEUE_LENGTH               ( ( unsigned portBASE_TYPE ) 10 )\r
+\r
+\r
+#define intqMIN_ACCEPTABLE_TASK_COUNT          ( 5 )\r
+\r
+\r
+#define timerNORMALLY_EMPTY_TX()                                                                                                                                                                                       \\r
+       if( xQueueIsQueueFullFromISR( xNormallyEmptyQueue ) != pdTRUE )                                                                                                                 \\r
+       {                                                                                                                                                                                                                                               \\r
+       unsigned portBASE_TYPE uxSavedInterruptStatus;                                                                                                                                                  \\r
+               uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();                                                                                                                     \\r
+               {                                                                                                                                                                                                                                       \\r
+                       xQueueSendFromISR( xNormallyEmptyQueue, ( void * ) &uxValueForNormallyEmptyQueue, &xHigherPriorityTaskWoken );  \\r
+                       uxValueForNormallyEmptyQueue++;                                                                                                                                                                 \\r
+               }                                                                                                                                                                                                                                       \\r
+               portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );                                                                                                            \\r
+       }                                                                                                                                                                                                                                               \\r
+\r
+#define timerNORMALLY_FULL_TX()                                                                                                                                                                                                \\r
+       if( xQueueIsQueueFullFromISR( xNormallyFullQueue ) != pdTRUE )                                                                                                                  \\r
+       {                                                                                                                                                                                                                                               \\r
+       unsigned portBASE_TYPE uxSavedInterruptStatus;                                                                                                                                                  \\r
+               uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();                                                                                                                     \\r
+               {                                                                                                                                                                                                                                       \\r
+                       xQueueSendFromISR( xNormallyFullQueue, ( void * ) &uxValueForNormallyFullQueue, &xHigherPriorityTaskWoken );    \\r
+                       uxValueForNormallyFullQueue++;                                                                                                                                                                  \\r
+               }                                                                                                                                                                                                                                       \\r
+               portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );                                                                                                            \\r
+       }                                                                                                                                                                                                                                               \\r
+\r
+#define timerNORMALLY_EMPTY_RX()                                                                                                                                                       \\r
+       if( xQueueReceiveFromISR( xNormallyEmptyQueue, &uxRxedValue, &xHigherPriorityTaskWoken ) != pdPASS )    \\r
+       {                                                                                                                                                                                                               \\r
+               prvQueueAccessLogError( __LINE__ );                                                                                                                                     \\r
+       }                                                                                                                                                                                                               \\r
+       else                                                                                                                                                                                                    \\r
+       {                                                                                                                                                                                                               \\r
+               prvRecordValue_NormallyEmpty( uxRxedValue, intqSECOND_INTERRUPT );                                                                      \\r
+       }\r
+\r
+#define timerNORMALLY_FULL_RX()                                                                                                                                                                \\r
+       if( xQueueReceiveFromISR( xNormallyFullQueue, &uxRxedValue, &xHigherPriorityTaskWoken ) == pdPASS )             \\r
+       {                                                                                                                                                                                                               \\r
+               prvRecordValue_NormallyFull( uxRxedValue, intqSECOND_INTERRUPT );                                                                       \\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
+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
+caused the error in xErrorLine. */\r
+static portBASE_TYPE xErrorStatus = pdPASS;\r
+static unsigned portBASE_TYPE xErrorLine = ( unsigned portBASE_TYPE ) 0;\r
+\r
+static portBASE_TYPE xWasSuspended = pdFALSE;\r
+\r
+/* The values that are sent to the queues.  An incremented value is sent each\r
+time to each queue. */\r
+volatile unsigned portBASE_TYPE uxValueForNormallyEmptyQueue = 0, uxValueForNormallyFullQueue = 0;\r
+\r
+/* A handle to some of the tasks is required so they can be suspended/resumed. */\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
+static unsigned portCHAR ucNormallyEmptyReceivedValues[ intqNUM_VALUES_TO_LOG ] = { 0 };\r
+static unsigned portCHAR ucNormallyFullReceivedValues[ intqNUM_VALUES_TO_LOG ] = { 0 };\r
+\r
+/* The test tasks themselves. */\r
+static void prvLowerPriorityNormallyEmptyTask( void *pvParameters );\r
+static void prvLowerPriorityNormallyFullTask( void *pvParameters );\r
+static void prvHigherPriorityNormallyEmptyTask( void *pvParameters );\r
+static void prv1stHigherPriorityNormallyFullTask( void *pvParameters );\r
+static void prv2ndHigherPriorityNormallyFullTask( void *pvParameters );\r
+\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
+/* Logs the line on which an error occurred. */\r
+static void prvQueueAccessLogError( unsigned portBASE_TYPE uxLine );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+void vStartInterruptQueueTasks( void )\r
+{\r
+       /* Start the test tasks. */\r
+       xTaskCreate( prvHigherPriorityNormallyEmptyTask, ( signed portCHAR * ) "H1QRx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIROITY_TASK1, intqHIGHER_PRIORITY, &xHighPriorityNormallyEmptyTask1 );\r
+       xTaskCreate( prvHigherPriorityNormallyEmptyTask, ( signed portCHAR * ) "H2QRx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIROITY_TASK2, intqHIGHER_PRIORITY, &xHighPriorityNormallyEmptyTask2 );\r
+       xTaskCreate( prvLowerPriorityNormallyEmptyTask, ( signed portCHAR * ) "LQRx", configMINIMAL_STACK_SIZE, NULL, intqLOWER_PRIORITY, NULL );\r
+       xTaskCreate( prv1stHigherPriorityNormallyFullTask, ( signed portCHAR * ) "H1QTx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIROITY_TASK1, intqHIGHER_PRIORITY, &xHighPriorityNormallyFullTask1 );\r
+       xTaskCreate( prv2ndHigherPriorityNormallyFullTask, ( signed portCHAR * ) "H1QTx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIROITY_TASK2, intqHIGHER_PRIORITY, &xHighPriorityNormallyFullTask2 );\r
+       xTaskCreate( prvLowerPriorityNormallyFullTask, ( signed portCHAR * ) "LQRx", configMINIMAL_STACK_SIZE, NULL, intqLOWER_PRIORITY, NULL );\r
+\r
+       /* Create the queues that are accessed by multiple tasks and multiple \r
+       interrupts. */\r
+       xNormallyFullQueue = xQueueCreate( intqQUEUE_LENGTH, ( unsigned portBASE_TYPE ) sizeof( unsigned portBASE_TYPE ) );\r
+       xNormallyEmptyQueue = xQueueCreate( intqQUEUE_LENGTH, ( unsigned portBASE_TYPE ) sizeof( unsigned portBASE_TYPE ) );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\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
+               if( ucNormallyFullReceivedValues[ uxValue ] != 0x00 )\r
+               {\r
+                       prvQueueAccessLogError( __LINE__ );\r
+               }\r
+               \r
+               /* Log that this value has been received. */\r
+               ucNormallyFullReceivedValues[ uxValue ] = uxSource;\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvRecordValue_NormallyEmpty( 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
+               if( ucNormallyEmptyReceivedValues[ uxValue ] != 0x00 )\r
+               {\r
+                       prvQueueAccessLogError( __LINE__ );\r
+               }\r
+               \r
+               /* Log that this value has been received. */\r
+               ucNormallyEmptyReceivedValues[ uxValue ] = uxSource;\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvQueueAccessLogError( unsigned portBASE_TYPE uxLine )\r
+{\r
+       /* Latch the line number that caused the error. */\r
+       xErrorLine = uxLine;\r
+       xErrorStatus = pdFAIL;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvHigherPriorityNormallyEmptyTask( void *pvParameters )\r
+{\r
+unsigned portBASE_TYPE uxRxed, ux, uxTask1, uxTask2;\r
+\r
+       /* The timer should not be started until after the scheduler has started. \r
+       More than one task is running this code so we check the parameter value\r
+       to determine which task should start the timer. */\r
+       if( ( unsigned portBASE_TYPE ) pvParameters == intqHIGH_PRIROITY_TASK1 )\r
+       {\r
+               vInitialiseTimerForIntQueueTest();\r
+       }\r
+\r
+       for( ;; )\r
+       {\r
+               /* Block waiting to receive a value from the normally empty queue.\r
+               Interrupts will write to the queue so we should receive a value. */\r
+               if( xQueueReceive( xNormallyEmptyQueue, &uxRxed, intqSHORT_DELAY ) != pdPASS )\r
+               {\r
+                       prvQueueAccessLogError( __LINE__ );\r
+               }\r
+               else\r
+               {\r
+                       /* Note which value was received so we can check all expected\r
+                       values are received and no values are duplicated. */\r
+                       prvRecordValue_NormallyEmpty( uxRxed, ( unsigned portBASE_TYPE ) pvParameters );\r
+               }\r
+               \r
+               /* Ensure the other task running this code gets a chance to execute. */\r
+               taskYIELD();\r
+               \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
+                       {\r
+                               vTaskSuspend( xHighPriorityNormallyEmptyTask2 );\r
+                               \r
+                               uxTask1 = 0;\r
+                               uxTask2 = 0;\r
+               \r
+                               /* Loop through the array, checking that both tasks have\r
+                               placed values into the array, and that no values are missing. */\r
+                               for( ux = 0; ux < intqNUM_VALUES_TO_LOG; ux++ )\r
+                               {\r
+                                       if( ucNormallyEmptyReceivedValues[ ux ] == 0 )\r
+                                       {\r
+                                               /* A value is missing. */\r
+                                               prvQueueAccessLogError( __LINE__ );\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               if( ucNormallyEmptyReceivedValues[ ux ] == intqHIGH_PRIROITY_TASK1 )\r
+                                               {\r
+                                                       /* Value was placed into the array by task 1. */\r
+                                                       uxTask1++;\r
+                                               }\r
+                                               else if( ucNormallyEmptyReceivedValues[ ux ] == intqHIGH_PRIROITY_TASK2 )\r
+                                               {\r
+                                                       /* Value was placed into the array by task 2. */\r
+                                                       uxTask2++;\r
+                                               }\r
+                                       }\r
+                               }\r
+                               \r
+                               if( uxTask1 < intqMIN_ACCEPTABLE_TASK_COUNT )\r
+                               {\r
+                                       /* Only task 2 seemed to log any values. */\r
+                                       prvQueueAccessLogError( __LINE__ );\r
+                               }\r
+                               \r
+                               if( uxTask2 < intqMIN_ACCEPTABLE_TASK_COUNT  )\r
+                               {\r
+                                       /* Only task 1 seemed to log any values. */\r
+                                       prvQueueAccessLogError( __LINE__ );\r
+                               }\r
+\r
+                               /* Clear the array again, ready to start a new cycle. */\r
+                               memset( ucNormallyEmptyReceivedValues, 0x00, sizeof( ucNormallyEmptyReceivedValues ) );\r
+                               \r
+                               uxHighPriorityLoops1++;\r
+                               uxValueForNormallyEmptyQueue = 0;\r
+\r
+                               /* Suspend ourselves, allowing the lower priority task to \r
+                               actually receive something from the queue.  Until now it\r
+                               will have been prevented from doing so by the higher\r
+                               priority tasks.  The lower priority task will resume us\r
+                               if it receives something.  We will then resume the other\r
+                               higher priority task. */\r
+                               vTaskSuspend( NULL );           \r
+                               vTaskResume( xHighPriorityNormallyEmptyTask2 );\r
+                       }\r
+               }\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvLowerPriorityNormallyEmptyTask( void *pvParameters )\r
+{\r
+unsigned portBASE_TYPE uxValue, uxRxed;\r
+portBASE_TYPE xQueueStatus;\r
+\r
+       /* The paramters are not being used so avoid compiler warnings. */\r
+       ( void ) pvParameters;\r
+       \r
+       for( ;; )\r
+       {       \r
+               if( ( xQueueStatus = xQueueReceive( xNormallyEmptyQueue, &uxRxed, intqONE_TICK_DELAY ) ) != errQUEUE_EMPTY )\r
+               {\r
+                       /* We should only obtain a value when the high priority task is\r
+                       suspended. */\r
+                       if( xTaskIsTaskSuspended( xHighPriorityNormallyEmptyTask1 ) == pdFALSE )\r
+                       {\r
+                               prvQueueAccessLogError( __LINE__ );\r
+                       }\r
+\r
+                       prvRecordValue_NormallyEmpty( uxRxed, intqLOW_PRIROITY_TASK );\r
+                       \r
+                       /* Wake the higher priority task again. */\r
+                       vTaskResume( xHighPriorityNormallyEmptyTask1 );\r
+                       uxLowPriorityLoops1++;\r
+               }\r
+               else\r
+               {\r
+                       /* Raise our priority while we send so we can preempt the higher\r
+                       priority task, and ensure we get the Tx value into the queue. */\r
+                       vTaskPrioritySet( NULL, intqHIGHER_PRIORITY + 1 );\r
+                       \r
+                       portENTER_CRITICAL();\r
+                       {\r
+                               uxValue = uxValueForNormallyEmptyQueue;\r
+                               uxValueForNormallyEmptyQueue++;\r
+                       }\r
+                       portEXIT_CRITICAL();\r
+                       \r
+                       if( xQueueSend( xNormallyEmptyQueue, &uxValue, portMAX_DELAY ) != pdPASS )\r
+                       {\r
+                               prvQueueAccessLogError( __LINE__ );\r
+                       }\r
+                       \r
+                       vTaskPrioritySet( NULL, intqLOWER_PRIORITY );\r
+               }\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
+       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
+       ( void ) pvParameters;\r
+       \r
+       /* Make sure the queue starts full or near full.  >> 1 as there are two\r
+       high priority tasks. */\r
+       for( ux = 0; ux < ( intqQUEUE_LENGTH >> 1 ); ux++ )\r
+       {\r
+               portENTER_CRITICAL();\r
+               {\r
+                       uxValueToTx = uxValueForNormallyFullQueue;\r
+                       uxValueForNormallyFullQueue++;\r
+               }\r
+               portEXIT_CRITICAL();\r
+\r
+               xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY );                \r
+       }\r
+\r
+       for( ;; )\r
+       {\r
+               portENTER_CRITICAL();\r
+               {\r
+                       uxValueToTx = uxValueForNormallyFullQueue;\r
+                       uxValueForNormallyFullQueue++;\r
+               }\r
+               portEXIT_CRITICAL();\r
+\r
+               if( ( xQueueStatus = xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY ) ) != pdPASS )\r
+               {\r
+                       /* intqHIGH_PRIROITY_TASK2 is never suspended so we would not \r
+                       expect it to ever time out. */\r
+                       prvQueueAccessLogError( __LINE__ );\r
+               }\r
+\r
+               /* Allow the other task running this code to run. */\r
+               taskYIELD();\r
+               \r
+               /* Have all the expected values been sent to the queue? */\r
+               if( uxValueToTx > ( intqNUM_VALUES_TO_LOG + 50 ) )\r
+               {\r
+                       /* Make sure the other high priority task completes its send of\r
+                       any values below intqNUM_VALUE_TO_LOG. */\r
+                       vTaskDelay( intqSHORT_DELAY );\r
+                       \r
+                       vTaskSuspend( xHighPriorityNormallyFullTask2 );\r
+                       \r
+                       if( xWasSuspended == pdTRUE )\r
+                       {\r
+                               /* We would have expected the other high pririty task to have\r
+                               set this back to false by now. */\r
+                               prvQueueAccessLogError( __LINE__ );\r
+                       }\r
+                       \r
+                       /* Set the suspended flag so an error is not logged if the other\r
+                       task recognises a time out when it is unsuspended. */\r
+                       xWasSuspended = pdTRUE;\r
+       \r
+                       for( ux = 0; ux < intqNUM_VALUES_TO_LOG; ux++ )\r
+                       {\r
+                               if( ucNormallyFullReceivedValues[ ux ] == 0 )\r
+                               {\r
+                                       /* A value was missing. */\r
+                                       prvQueueAccessLogError( __LINE__ );\r
+                               }\r
+                       }                               \r
+\r
+                       /* Reset the array ready for the next cycle. */\r
+                       memset( ucNormallyFullReceivedValues, 0x00, sizeof( ucNormallyFullReceivedValues ) );                           \r
+                       \r
+                       uxHighPriorityLoops2++;\r
+                       uxValueForNormallyFullQueue = 0;\r
+\r
+                       /* Suspend ourselves, allowing the lower priority task to \r
+                       actually receive something from the queue.  Until now it\r
+                       will have been prevented from doing so by the higher\r
+                       priority tasks.  The lower priority task will resume us\r
+                       if it receives something.  We will then resume the other\r
+                       higher priority task. */\r
+                       vTaskSuspend( NULL );   \r
+                       vTaskResume( xHighPriorityNormallyFullTask2 );\r
+               }\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prv2ndHigherPriorityNormallyFullTask( 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
+       ( void ) pvParameters;\r
+       \r
+       /* Make sure the queue starts full or near full.  >> 1 as there are two\r
+       high priority tasks. */\r
+       for( ux = 0; ux < ( intqQUEUE_LENGTH >> 1 ); ux++ )\r
+       {\r
+               portENTER_CRITICAL();\r
+               {\r
+                       uxValueToTx = uxValueForNormallyFullQueue;\r
+                       uxValueForNormallyFullQueue++;\r
+               }\r
+               portEXIT_CRITICAL();\r
+\r
+               xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY );                \r
+       }\r
+\r
+       for( ;; )\r
+       {\r
+               portENTER_CRITICAL();\r
+               {\r
+                       uxValueToTx = uxValueForNormallyFullQueue;\r
+                       uxValueForNormallyFullQueue++;\r
+               }\r
+               portEXIT_CRITICAL();\r
+\r
+               if( ( xQueueStatus = xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY ) ) != pdPASS )\r
+               {\r
+                       if( xWasSuspended != pdTRUE )\r
+                       {\r
+                               /* It is ok to time out if the task has been suspended. */\r
+                               prvQueueAccessLogError( __LINE__ );\r
+                       }\r
+               }\r
+\r
+               xWasSuspended = pdFALSE;\r
+               \r
+               taskYIELD();\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvLowerPriorityNormallyFullTask( void *pvParameters )\r
+{\r
+unsigned portBASE_TYPE uxValue, uxTxed = 9999;\r
+portBASE_TYPE xQueueStatus;\r
+\r
+       /* The paramters are not being used so avoid compiler warnings. */\r
+       ( void ) pvParameters;\r
+       \r
+       for( ;; )\r
+       {       \r
+               if( ( xQueueStatus = xQueueSend( xNormallyFullQueue, &uxTxed, intqONE_TICK_DELAY ) ) != errQUEUE_FULL )\r
+               {\r
+                       /* We would only expect to succeed when the higher priority task\r
+                       is suspended. */\r
+                       if( xTaskIsTaskSuspended( xHighPriorityNormallyFullTask1 ) == pdFALSE )\r
+                       {\r
+                               prvQueueAccessLogError( __LINE__ );\r
+                       }\r
+\r
+                       vTaskResume( xHighPriorityNormallyFullTask1 );\r
+                       uxLowPriorityLoops2++;\r
+               }\r
+               else\r
+               {\r
+                       /* Raise our priority while we receive so we can preempt the higher\r
+                       priority task, and ensure we get the value from the queue. */\r
+                       vTaskPrioritySet( NULL, intqHIGHER_PRIORITY + 1 );\r
+                       \r
+                       if( xQueueReceive( xNormallyFullQueue, &uxValue, portMAX_DELAY ) != pdPASS )\r
+                       {\r
+                               prvQueueAccessLogError( __LINE__ );\r
+                       }\r
+                       else\r
+                       {\r
+                               prvRecordValue_NormallyFull( uxValue, intqLOW_PRIROITY_TASK );\r
+                       }\r
+                       \r
+                       vTaskPrioritySet( NULL, intqLOWER_PRIORITY );\r
+               }\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+portBASE_TYPE xFirstTimerHandler( void )\r
+{\r
+portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE, uxRxedValue;\r
+static unsigned portBASE_TYPE uxNextOperation = 0;\r
+\r
+       uxNextOperation++;\r
+       \r
+       if( uxNextOperation & ( unsigned portBASE_TYPE ) 0x01 )\r
+       {\r
+               timerNORMALLY_EMPTY_TX();\r
+               timerNORMALLY_EMPTY_TX();       \r
+               timerNORMALLY_EMPTY_TX();\r
+       }\r
+       else\r
+       {\r
+               timerNORMALLY_FULL_RX();\r
+               timerNORMALLY_FULL_RX();\r
+               timerNORMALLY_FULL_RX();\r
+       }\r
+       \r
+       return xHigherPriorityTaskWoken;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+portBASE_TYPE xSecondTimerHandler( void )\r
+{\r
+unsigned portBASE_TYPE uxRxedValue;\r
+portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;\r
+static unsigned portBASE_TYPE uxNextOperation = 0;\r
+\r
+       uxNextOperation++;\r
+       \r
+       if( uxNextOperation & ( unsigned portBASE_TYPE ) 0x01 )\r
+       {\r
+               timerNORMALLY_EMPTY_TX();\r
+               timerNORMALLY_EMPTY_TX();\r
+\r
+               timerNORMALLY_EMPTY_RX();\r
+               timerNORMALLY_EMPTY_RX();\r
+       }\r
+       else\r
+       {       \r
+               timerNORMALLY_FULL_RX();\r
+               timerNORMALLY_FULL_TX();\r
+               timerNORMALLY_FULL_TX();\r
+               timerNORMALLY_FULL_TX();\r
+               timerNORMALLY_FULL_TX();\r
+       }\r
+       \r
+       return xHigherPriorityTaskWoken;\r
+}\r
+\r
+\r