]> git.sur5r.net Git - freertos/commitdiff
A bit of modularisation performed on the TimerDemo.c file - still a work in progress.
authorrichardbarry <richardbarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Thu, 10 Feb 2011 19:08:14 +0000 (19:08 +0000)
committerrichardbarry <richardbarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Thu, 10 Feb 2011 19:08:14 +0000 (19:08 +0000)
git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@1290 1d2547de-c912-0410-9cb9-b8ca96c0e9e2

Demo/Common/Minimal/TimerDemo.c

index 00a67c46f60762fc6a762b99ee92d6e4a5bed8e0..4f7aed6515949fa6c60b2043c5318e2c2f38efd9 100644 (file)
@@ -33,9 +33,9 @@
     FreeRTOS is distributed in the hope that it will be useful, but WITHOUT\r
     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
     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
+    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
 \r
 */\r
 \r
 \r
-/* \r
+/*\r
  * Tests the behaviour of timers.  Some timers are created before hte scheudler\r
  * is started, and some after.\r
  */\r
 \r
+/* Standard includes. */\r
+#include <string.h>\r
 \r
 /* Scheduler include files. */\r
 #include "FreeRTOS.h"\r
 #endif\r
 \r
 #define tmrdemoDONT_BLOCK                              ( ( portTickType ) 0 )\r
-#define tmrdemoONE_SHOT_TIMER_FREQUENCY ( xBaseFrequency * ( portTickType ) 3 )\r
+#define tmrdemoONE_SHOT_TIMER_PERIOD   ( xBasePeriod * ( portTickType ) 3 )\r
 #define trmdemoNUM_TIMER_RESETS                        ( ( unsigned char ) 10 )\r
 \r
 /*-----------------------------------------------------------*/\r
 \r
-static void prvFreeRunningTimerCallback( xTimerHandle pxExpiredTimer );\r
+static void prvAutoReloadTimerCallback( xTimerHandle pxExpiredTimer );\r
 static void prvTimerControlTask( void *pvParameters );\r
 \r
+static void prvTest1_CreateTimersWithoutSchedulerRunning( void );\r
+static void    prvTest3_CheckAutoReloadExpireRates( void );\r
+static void prvTest2_CheckTaskAndTimersInitialState( void );\r
+static void prvTest4_CheckAutoReloadTimersCanBeStopped( void );\r
+static void prvTest5_CheckBasicOneShotTimerBehaviour( void );\r
+static void prvTest6_CheckAutoReloadResetBehaviour( void );\r
+static void prvResetStartConditionsForNextIteration( void );\r
+\r
 /*-----------------------------------------------------------*/\r
 \r
 /* Flag that will be latched to pdFAIL should any unexpected behaviour be\r
@@ -89,75 +99,28 @@ static volatile portBASE_TYPE xTestStatus = pdPASS;
 detect a stalled task - a test that is no longer running. */\r
 static volatile unsigned portLONG ulLoopCounter = 0;\r
 \r
-xTimerHandle xFreeRunningTimers[ configTIMER_QUEUE_LENGTH + 1 ] = { 0 };\r
-unsigned char ucFreeRunningTimerCounters[ configTIMER_QUEUE_LENGTH + 1 ] = { 0 };\r
-unsigned char ucOneShotTimerCounter = ( unsigned char ) 0;\r
+static xTimerHandle xAutoReloadTimers[ configTIMER_QUEUE_LENGTH + 1 ] = { 0 };\r
+static unsigned char ucAutoReloadTimerCounters[ configTIMER_QUEUE_LENGTH + 1 ] = { 0 };\r
+static unsigned char ucOneShotTimerCounter = ( unsigned char ) 0;\r
+\r
+static xTimerHandle xOneShotTimer = NULL;\r
 \r
-static portTickType xBaseFrequency = 0;\r
+static portTickType xBasePeriod = 0;\r
 \r
 /*-----------------------------------------------------------*/\r
 \r
-void vStartTimerDemoTask( portTickType xBaseFrequencyIn )\r
+void vStartTimerDemoTask( portTickType xBasePeriodIn )\r
 {\r
-portBASE_TYPE xTimer;\r
-\r
-       xBaseFrequency = xBaseFrequencyIn;\r
-\r
-       for( xTimer = 0; xTimer < configTIMER_QUEUE_LENGTH; xTimer++ )\r
-       {\r
-               /* As the timer queue is not yet full, it should be possible to both create\r
-               and start a timer.  These timers are being started before the scheduler has\r
-               been started, so their block times should get set to zero within the timer\r
-               API itself. */\r
-               xFreeRunningTimers[ xTimer ] = xTimerCreate( "FR Timer",                                                /* Text name to facilitate debugging.  The kernel does not use this itself. */\r
-                                                                                                       ( ( xTimer + 1 ) * xBaseFrequency ),/* The period for the timer.  The plus 1 ensures a period of zero is not specified. */\r
-                                                                                                       pdTRUE,                                                         /* Autoreload is set to true. */\r
-                                                                                                       ( void * ) xTimer,                                      /* An identifier for the timer as all the free running timers use the same callback. */\r
-                                                                                                       prvFreeRunningTimerCallback );          /* The callback to be called when the timer expires. */\r
-\r
-               if( xFreeRunningTimers[ xTimer ] == NULL )\r
-               {\r
-                       xTestStatus = pdFAIL;\r
-               }\r
-               else\r
-               {\r
-                       /* The scheduler has not yet started, so the block period of \r
-                       portMAX_DELAY should just get set to zero in xTimerStart().  Also,\r
-                       the timer queue is not yet full so xTimerStart() should return\r
-                       pdPASS. */\r
-                       if( xTimerStart( xFreeRunningTimers[ xTimer ], portMAX_DELAY ) != pdPASS )\r
-                       {\r
-                               xTestStatus = pdFAIL;\r
-                       }\r
-               }\r
-       }\r
+       /* Store the period from which all the timer periods will be generated from\r
+       (multiples of). */\r
+       xBasePeriod = xBasePeriodIn;\r
 \r
-       /* The timers queue should now be full, so it should be possible to create\r
-       another timer, but not possible to start it (the timer queue will not get\r
-       drained until the scheduler has been started. */\r
-       xFreeRunningTimers[ configTIMER_QUEUE_LENGTH ] = xTimerCreate( "FR Timer",              /* Text name to facilitate debugging.  The kernel does not use this itself. */\r
-                                                                                                       ( configTIMER_QUEUE_LENGTH * xBaseFrequency ),  /* The period for the timer. */\r
-                                                                                                       pdTRUE,                                                 /* Autoreload is set to true. */\r
-                                                                                                       ( void * ) xTimer,                              /* An identifier for the timer as all the free running timers use the same callback. */\r
-                                                                                                       prvFreeRunningTimerCallback );  /* The callback to be called when the timer expires. */\r
+       /* Create a set of timers for use by this demo/test. */\r
+       prvTest1_CreateTimersWithoutSchedulerRunning();\r
 \r
-       if( xFreeRunningTimers[ configTIMER_QUEUE_LENGTH ] == NULL )\r
-       {\r
-               xTestStatus = pdFAIL;\r
-       }\r
-       else\r
-       {\r
-               if( xTimerStart( xFreeRunningTimers[ xTimer ], portMAX_DELAY ) == pdPASS )\r
-               {\r
-                       /* This time it would not be expected that the timer could be\r
-                       started at this point. */\r
-                       xTestStatus = pdFAIL;\r
-               }\r
-       }\r
-\r
-       /* Create the task that will control and monitor the timers.  This is \r
+       /* Create the task that will control and monitor the timers.  This is\r
        created at a lower priority than the timer service task to ensure, as\r
-       far as it is concerned, commands on timers are actioned immediately \r
+       far as it is concerned, commands on timers are actioned immediately\r
        (sending a command to the timer service task will unblock the timer service\r
        task, which will then preempt this task). */\r
        if( xTestStatus != pdFAIL )\r
@@ -167,14 +130,14 @@ portBASE_TYPE xTimer;
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-static void prvFreeRunningTimerCallback( xTimerHandle pxExpiredTimer )\r
+static void prvAutoReloadTimerCallback( xTimerHandle pxExpiredTimer )\r
 {\r
 portBASE_TYPE xTimerID;\r
 \r
        xTimerID = ( portBASE_TYPE ) pvTimerGetTimerID( pxExpiredTimer );\r
        if( xTimerID <= ( configTIMER_QUEUE_LENGTH + 1 ) )\r
        {\r
-               ( ucFreeRunningTimerCounters[ xTimerID ] )++;\r
+               ( ucAutoReloadTimerCounters[ xTimerID ] )++;\r
        }\r
        else\r
        {\r
@@ -196,16 +159,11 @@ static void prvOneShotTimerCallback( xTimerHandle pxExpiredTimer )
 \r
 static void prvTimerControlTask( void *pvParameters )\r
 {\r
-portTickType xNextWakeTime;\r
-unsigned char ucTimer;\r
-unsigned char ucMaxAllowableValue, ucMinAllowableValue;\r
-xTimerHandle xOneShotTimer = NULL;\r
-\r
        ( void ) pvParameters;\r
 \r
        /* Create a one-shot timer for use later on in this test. */\r
        xOneShotTimer = xTimerCreate(   "Oneshot Timer",                                /* Text name to facilitate debugging.  The kernel does not use this itself. */\r
-                                                                       tmrdemoONE_SHOT_TIMER_FREQUENCY,/* The period for the timer. */\r
+                                                                       tmrdemoONE_SHOT_TIMER_PERIOD,/* The period for the timer. */\r
                                                                        pdFALSE,                                                /* Don't autoreload - hence a one shot timer. */\r
                                                                        ( void * ) 0,                                   /* The timer identifier.  In this case this is not used as the timer has its own callback. */\r
                                                                        prvOneShotTimerCallback );              /* The callback to be called when the timer expires. */\r
@@ -216,349 +174,443 @@ xTimerHandle xOneShotTimer = NULL;
        }\r
 \r
 \r
-       /*-----------------------------------------------------------*/\r
-       /* Test 1 - ensure all the timers are in their expected initial state.  This\r
+       /* Ensure all the timers are in their expected initial state.  This\r
        depends on the timer service task having a higher priority than this task. */\r
+       prvTest2_CheckTaskAndTimersInitialState();\r
 \r
-       /* Free running timers 0 to ( configTIMER_QUEUE_LENGTH - 1 ) should now\r
-       be active, and free running timer configTIMER_QUEUE_LENGTH should not\r
-       yet be active (it could not be started prior to the scheduler being\r
-       started. */\r
-       for( ucTimer = 0; ucTimer < ( unsigned char ) configTIMER_QUEUE_LENGTH; ucTimer++ )\r
+       for( ;; )\r
        {\r
-               if( xTimerIsTimerActive( xFreeRunningTimers[ ucTimer ] ) == pdFALSE )\r
-               {\r
-                       xTestStatus = pdFAIL;\r
-               }\r
+               /* Check the auto reload timers expire at the expected/correct rates. */\r
+               prvTest3_CheckAutoReloadExpireRates();\r
+\r
+               /* Check the auto reload timers can be stopped correctly, and correctly\r
+               report their state. */\r
+               prvTest4_CheckAutoReloadTimersCanBeStopped();\r
+                               \r
+               /* Check the one shot timer only calls its callback once after it has been \r
+               started, and that it reports its state correctly. */\r
+               prvTest5_CheckBasicOneShotTimerBehaviour();\r
+\r
+               /* Check timer reset behaviour. */\r
+               prvTest6_CheckAutoReloadResetBehaviour();\r
+\r
+               /* Start the timers again to restart all the tests over again. */\r
+               prvResetStartConditionsForNextIteration();\r
        }\r
+}\r
+/*-----------------------------------------------------------*/\r
 \r
-       if( xTimerIsTimerActive( xFreeRunningTimers[ configTIMER_QUEUE_LENGTH ] ) != pdFALSE )\r
+/* This is called to check that the created task is still running and has not\r
+detected any errors. */\r
+portBASE_TYPE xAreTimerDemoTasksStillRunning( void )\r
+{\r
+static unsigned portLONG ulLastLoopCounter = 0;\r
+\r
+       /* If the demo task is still running then we expect the loopcounter to\r
+       have incremented since this function was last called. */\r
+       if( ulLastLoopCounter == ulLoopCounter )\r
        {\r
                xTestStatus = pdFAIL;\r
        }\r
 \r
-       for( ;; )\r
-       {\r
-               /*-----------------------------------------------------------*/\r
-               /* Test 2 - Check the free running timers expire at the expcted rates. */\r
+       ulLastLoopCounter = ulLoopCounter;\r
 \r
-               /* Initialise the next wake time value before the call to \r
-               vTaskDelayUntil() as this is not really a periodic task. */\r
-               xNextWakeTime = xTaskGetTickCount();\r
+       /* Errors detected in the task itself will have latched xTestStatus\r
+       to pdFAIL. */\r
 \r
-               /* Delaying for configTIMER_QUEUE_LENGTH * xBaseFrequency ticks \r
-               should allow all the free running timers to expire at least once. */\r
-               vTaskDelayUntil( &xNextWakeTime, ( ( portTickType ) configTIMER_QUEUE_LENGTH ) * xBaseFrequency );\r
+       return xTestStatus;\r
+}\r
+/*-----------------------------------------------------------*/\r
 \r
-               /* Check that all the free running timers have called their callback \r
-               function the expected number of times. */\r
-               for( ucTimer = 0; ucTimer < ( unsigned char ) configTIMER_QUEUE_LENGTH; ucTimer++ )\r
-               {\r
-                       /* The timer in array position 0 should elapse every xBaseFrequency \r
-                       ticks, the timer in array position 1 should elapse every\r
-                       ( 2 * xBaseFrequency ) ticks, etc.  This task blocked for \r
-                       configTIMER_QUEUE_LENGTH * xBaseFrequency, so the timer in array\r
-                       position 0 should have elapsed configTIMER_QUEUE_LENGTH times, the\r
-                       timer in array possition 1 should have elapsed \r
-                       ( configTIMER_QUEUE_LENGTH - 1 ) times, etc. */\r
-                       ucMaxAllowableValue = ( ( ( unsigned char ) configTIMER_QUEUE_LENGTH ) - ucTimer );\r
-                       ucMinAllowableValue = ( ( ( unsigned char ) configTIMER_QUEUE_LENGTH ) - ucTimer ) - 1;\r
-\r
-                       if( ( ucFreeRunningTimerCounters[ ucTimer ] < ucMinAllowableValue ) ||\r
-                               ( ucFreeRunningTimerCounters[ ucTimer ] > ucMaxAllowableValue )\r
-                         )\r
-                       {\r
-                               xTestStatus = pdFAIL;\r
-                       }\r
-               }\r
+static void prvTest1_CreateTimersWithoutSchedulerRunning( void )\r
+{\r
+portBASE_TYPE xTimer;\r
 \r
-               if( xTestStatus == pdPASS )\r
+       for( xTimer = 0; xTimer < configTIMER_QUEUE_LENGTH; xTimer++ )\r
+       {\r
+               /* As the timer queue is not yet full, it should be possible to both create\r
+               and start a timer.  These timers are being started before the scheduler has\r
+               been started, so their block times should get set to zero within the timer\r
+               API itself. */\r
+               xAutoReloadTimers[ xTimer ] = xTimerCreate( "FR Timer",                                         /* Text name to facilitate debugging.  The kernel does not use this itself. */\r
+                                                                                                       ( ( xTimer + 1 ) * xBasePeriod ),/* The period for the timer.  The plus 1 ensures a period of zero is not specified. */\r
+                                                                                                       pdTRUE,                                                         /* Autoreload is set to true. */\r
+                                                                                                       ( void * ) xTimer,                                      /* An identifier for the timer as all the auto reload timers use the same callback. */\r
+                                                                                                       prvAutoReloadTimerCallback );           /* The callback to be called when the timer expires. */\r
+\r
+               if( xAutoReloadTimers[ xTimer ] == NULL )\r
                {\r
-                       /* No errors have been reported so increment the loop counter so\r
-                       the check task knows this task is still running. */\r
-                       ulLoopCounter++;\r
+                       xTestStatus = pdFAIL;\r
                }\r
-\r
-\r
-\r
-\r
-               /*-----------------------------------------------------------*/\r
-               /* Test 3 - Check the free running timers can be stopped correctly, and\r
-               correctly report their state. */\r
-\r
-               /* Stop all the active timers. */\r
-               for( ucTimer = 0; ucTimer < ( unsigned char ) configTIMER_QUEUE_LENGTH; ucTimer++ )\r
+               else\r
                {\r
-                       /* The timer has not been stopped yet! */\r
-                       if( xTimerIsTimerActive( xFreeRunningTimers[ ucTimer ] ) == pdFALSE )\r
+                       /* The scheduler has not yet started, so the block period of\r
+                       portMAX_DELAY should just get set to zero in xTimerStart().  Also,\r
+                       the timer queue is not yet full so xTimerStart() should return\r
+                       pdPASS. */\r
+                       if( xTimerStart( xAutoReloadTimers[ xTimer ], portMAX_DELAY ) != pdPASS )\r
                        {\r
                                xTestStatus = pdFAIL;\r
                        }\r
+               }\r
+       }\r
 \r
-                       /* Now stop the timer.  This will appear to happen immediately to \r
-                       this task because this task is running at a priority below the \r
-                       timer service task. */\r
-                       xTimerStop( xFreeRunningTimers[ ucTimer ], tmrdemoDONT_BLOCK );\r
+       /* The timers queue should now be full, so it should be possible to create\r
+       another timer, but not possible to start it (the timer queue will not get\r
+       drained until the scheduler has been started. */\r
+       xAutoReloadTimers[ configTIMER_QUEUE_LENGTH ] = xTimerCreate( "FR Timer",               /* Text name to facilitate debugging.  The kernel does not use this itself. */\r
+                                                                                                       ( configTIMER_QUEUE_LENGTH * xBasePeriod ),     /* The period for the timer. */\r
+                                                                                                       pdTRUE,                                                 /* Autoreload is set to true. */\r
+                                                                                                       ( void * ) xTimer,                              /* An identifier for the timer as all the auto reload timers use the same callback. */\r
+                                                                                                       prvAutoReloadTimerCallback );   /* The callback to be called when the timer expires. */\r
 \r
-                       /* The timer should now be inactive. */\r
-                       if( xTimerIsTimerActive( xFreeRunningTimers[ ucTimer ] ) != pdFALSE )\r
-                       {\r
-                               xTestStatus = pdFAIL;\r
-                       }\r
+       if( xAutoReloadTimers[ configTIMER_QUEUE_LENGTH ] == NULL )\r
+       {\r
+               xTestStatus = pdFAIL;\r
+       }\r
+       else\r
+       {\r
+               if( xTimerStart( xAutoReloadTimers[ xTimer ], portMAX_DELAY ) == pdPASS )\r
+               {\r
+                       /* This time it would not be expected that the timer could be\r
+                       started at this point. */\r
+                       xTestStatus = pdFAIL;\r
                }\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
 \r
-               taskENTER_CRITICAL();\r
-               {\r
-                       /* The timer in array position configTIMER_QUEUE_LENGTH should not \r
-                       be active.  The critical section is used to ensure the timer does \r
-                       not call its callback between the next line running and the array \r
-                       being cleared back to zero, as that would mask an error condition. */\r
-                       if( ucFreeRunningTimerCounters[ configTIMER_QUEUE_LENGTH ] != ( unsigned char ) 0 )\r
-                       {\r
-                               xTestStatus = pdFAIL;\r
-                       }\r
+static void prvTest2_CheckTaskAndTimersInitialState( void )\r
+{\r
+unsigned char ucTimer;\r
 \r
-                       /* Clear the timer callback count. */\r
-                       memset( ( void * ) ucFreeRunningTimerCounters, 0, sizeof( ucFreeRunningTimerCounters ) );\r
-               }\r
-               taskEXIT_CRITICAL();\r
+       /* Ensure all the timers are in their expected initial state.  This     depends \r
+       on the timer service task having a higher priority than this task.\r
 \r
-               /* The timers are now all inactive, so this time, after delaying, none\r
-               of the callback counters should have incremented. */\r
-               vTaskDelay( ( ( portTickType ) configTIMER_QUEUE_LENGTH ) * xBaseFrequency );\r
-               for( ucTimer = 0; ucTimer < ( unsigned char ) configTIMER_QUEUE_LENGTH; ucTimer++ )\r
+       auto reload timers 0 to ( configTIMER_QUEUE_LENGTH - 1 ) should now be active,\r
+       and auto reload timer configTIMER_QUEUE_LENGTH should not yet be active (it \r
+       could not be started prior to the scheduler being started when it was \r
+       created). */\r
+       for( ucTimer = 0; ucTimer < ( unsigned char ) configTIMER_QUEUE_LENGTH; ucTimer++ )\r
+       {\r
+               if( xTimerIsTimerActive( xAutoReloadTimers[ ucTimer ] ) == pdFALSE )\r
                {\r
-                       if( ucFreeRunningTimerCounters[ ucTimer ] != ( unsigned char ) 0 )\r
-                       {\r
-                               xTestStatus = pdFAIL;\r
-                       }\r
+                       xTestStatus = pdFAIL;\r
                }\r
+       }\r
 \r
-               if( xTestStatus == pdPASS )\r
-               {\r
-                       /* No errors have been reported so increment the loop counter so\r
-                       the check task knows this task is still running. */\r
-                       ulLoopCounter++;\r
-               }\r
+       if( xTimerIsTimerActive( xAutoReloadTimers[ configTIMER_QUEUE_LENGTH ] ) != pdFALSE )\r
+       {\r
+               xTestStatus = pdFAIL;\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
 \r
+static void    prvTest3_CheckAutoReloadExpireRates( void )\r
+{\r
+unsigned char ucMaxAllowableValue, ucMinAllowableValue, ucTimer;\r
+portTickType xNextWakeTime;\r
 \r
+       /* Check the auto reload timers expire at the expcted rates. */\r
 \r
-               /*-----------------------------------------------------------*/\r
-               /* Test 4 - Check the one shot timer only calls its callback once after\r
-               it has been started, and that it reports its state correctly. */\r
+       /* Initialise the next wake time value before the call to vTaskDelayUntil() \r
+       as this is not really a periodic task. */\r
+       xNextWakeTime = xTaskGetTickCount();\r
 \r
-               /* The one shot timer should not be active yet. */\r
-               if( xTimerIsTimerActive( xOneShotTimer ) != pdFALSE )\r
-               {\r
-                       xTestStatus = pdFAIL;\r
-               }\r
+       /* Delaying for configTIMER_QUEUE_LENGTH * xBasePeriod ticks should allow \r
+       all the auto reload timers to expire at least once. */\r
+       vTaskDelayUntil( &xNextWakeTime, ( ( portTickType ) configTIMER_QUEUE_LENGTH ) * xBasePeriod );\r
 \r
-               if( ucOneShotTimerCounter != ( unsigned char ) 0 )\r
+       /* Check that all the auto reload timers have called their callback     \r
+       function the expected number of times. */\r
+       for( ucTimer = 0; ucTimer < ( unsigned char ) configTIMER_QUEUE_LENGTH; ucTimer++ )\r
+       {\r
+               /* The timer in array position 0 should elapse every xBasePeriod ticks, \r
+               the timer in array position 1 should elapse every ( 2 * xBasePeriod ) \r
+               ticks, etc.  This task blocked for configTIMER_QUEUE_LENGTH * xBasePeriod, \r
+               so the timer in array position 0 should have elapsed \r
+               configTIMER_QUEUE_LENGTH times, the     timer in array possition 1 should \r
+               have elapsed ( configTIMER_QUEUE_LENGTH - 1 ) times, etc. */\r
+               ucMaxAllowableValue = ( ( ( unsigned char ) configTIMER_QUEUE_LENGTH ) - ucTimer );\r
+               ucMinAllowableValue = ( ( ( unsigned char ) configTIMER_QUEUE_LENGTH ) - ucTimer ) - 1;\r
+\r
+               if( ( ucAutoReloadTimerCounters[ ucTimer ] < ucMinAllowableValue ) ||\r
+                       ( ucAutoReloadTimerCounters[ ucTimer ] > ucMaxAllowableValue )\r
+                       )\r
                {\r
                        xTestStatus = pdFAIL;\r
                }\r
+       }\r
 \r
-               /* Start the one shot timer and check that it reports its state\r
-               correctly. */\r
-               xTimerStart( xOneShotTimer, tmrdemoDONT_BLOCK );\r
-               if( xTimerIsTimerActive( xOneShotTimer ) == pdFALSE )\r
+       if( xTestStatus == pdPASS )\r
+       {\r
+               /* No errors have been reported so increment the loop counter so the \r
+               check task knows this task is still running. */\r
+               ulLoopCounter++;\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvTest4_CheckAutoReloadTimersCanBeStopped( void )\r
+{              \r
+unsigned char ucTimer;\r
+\r
+       /* Check the auto reload timers can be stopped correctly, and correctly \r
+       report their state. */\r
+\r
+       /* Stop all the active timers. */\r
+       for( ucTimer = 0; ucTimer < ( unsigned char ) configTIMER_QUEUE_LENGTH; ucTimer++ )\r
+       {\r
+               /* The timer has not been stopped yet! */\r
+               if( xTimerIsTimerActive( xAutoReloadTimers[ ucTimer ] ) == pdFALSE )\r
                {\r
                        xTestStatus = pdFAIL;\r
                }\r
 \r
-               /* Delay for three times as long as the one shot timer period, then\r
-               check to ensure it has only called its callback once, and is now\r
-               not in the active state. */\r
-               vTaskDelay( tmrdemoONE_SHOT_TIMER_FREQUENCY * ( portTickType ) 3 );\r
+               /* Now stop the timer.  This will appear to happen immediately to\r
+               this task because this task is running at a priority below the\r
+               timer service task. */\r
+               xTimerStop( xAutoReloadTimers[ ucTimer ], tmrdemoDONT_BLOCK );\r
 \r
-               if( xTimerIsTimerActive( xOneShotTimer ) != pdFALSE )\r
+               /* The timer should now be inactive. */\r
+               if( xTimerIsTimerActive( xAutoReloadTimers[ ucTimer ] ) != pdFALSE )\r
                {\r
                        xTestStatus = pdFAIL;\r
                }\r
+       }\r
 \r
-               if( ucOneShotTimerCounter != ( unsigned char ) 1 )\r
+       taskENTER_CRITICAL();\r
+       {\r
+               /* The timer in array position configTIMER_QUEUE_LENGTH should not\r
+               be active.  The critical section is used to ensure the timer does\r
+               not call its callback between the next line running and the array\r
+               being cleared back to zero, as that would mask an error condition. */\r
+               if( ucAutoReloadTimerCounters[ configTIMER_QUEUE_LENGTH ] != ( unsigned char ) 0 )\r
                {\r
                        xTestStatus = pdFAIL;\r
                }\r
-               else\r
-               {\r
-                       /* Reset the one shot timer callback count. */\r
-                       ucOneShotTimerCounter = ( unsigned char ) 0;\r
-               }\r
 \r
-               if( xTestStatus == pdPASS )\r
+               /* Clear the timer callback count. */\r
+               memset( ( void * ) ucAutoReloadTimerCounters, 0, sizeof( ucAutoReloadTimerCounters ) );\r
+       }\r
+       taskEXIT_CRITICAL();\r
+\r
+       /* The timers are now all inactive, so this time, after delaying, none\r
+       of the callback counters should have incremented. */\r
+       vTaskDelay( ( ( portTickType ) configTIMER_QUEUE_LENGTH ) * xBasePeriod );\r
+       for( ucTimer = 0; ucTimer < ( unsigned char ) configTIMER_QUEUE_LENGTH; ucTimer++ )\r
+       {\r
+               if( ucAutoReloadTimerCounters[ ucTimer ] != ( unsigned char ) 0 )\r
                {\r
-                       /* No errors have been reported so increment the loop counter so\r
-                       the check task knows this task is still running. */\r
-                       ulLoopCounter++;\r
+                       xTestStatus = pdFAIL;\r
                }\r
+       }\r
 \r
+       if( xTestStatus == pdPASS )\r
+       {\r
+               /* No errors have been reported so increment the loop counter so\r
+               the check task knows this task is still running. */\r
+               ulLoopCounter++;\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
 \r
+static void prvTest5_CheckBasicOneShotTimerBehaviour( void )\r
+{\r
+       /* Check the one shot timer only calls its callback once after it has been \r
+       started, and that it reports its state correctly. */\r
 \r
+       /* The one shot timer should not be active yet. */\r
+       if( xTimerIsTimerActive( xOneShotTimer ) != pdFALSE )\r
+       {\r
+               xTestStatus = pdFAIL;\r
+       }\r
 \r
-               /*-----------------------------------------------------------*/\r
-               /* Test 5 - Check all the timers can be reset while they are running. */\r
+       if( ucOneShotTimerCounter != ( unsigned char ) 0 )\r
+       {\r
+               xTestStatus = pdFAIL;\r
+       }\r
 \r
-               /* Restart the one shot timer and check it reports its status \r
-               correctly. */\r
-               xTimerStart( xOneShotTimer, tmrdemoDONT_BLOCK );\r
-               if( xTimerIsTimerActive( xOneShotTimer ) == pdFALSE )\r
-               {\r
-                       xTestStatus = pdFAIL;\r
-               }\r
+       /* Start the one shot timer and check that it reports its state correctly. */\r
+       xTimerStart( xOneShotTimer, tmrdemoDONT_BLOCK );\r
+       if( xTimerIsTimerActive( xOneShotTimer ) == pdFALSE )\r
+       {\r
+               xTestStatus = pdFAIL;\r
+       }\r
 \r
-               /* Restart one of the free running timers and check that it reports its\r
-               status correctly. */\r
-               xTimerStart( xFreeRunningTimers[ configTIMER_QUEUE_LENGTH - 1 ], tmrdemoDONT_BLOCK );\r
-               if( xTimerIsTimerActive( xFreeRunningTimers[ configTIMER_QUEUE_LENGTH - 1 ] ) == pdFALSE )\r
-               {\r
-                       xTestStatus = pdFAIL;\r
-               }\r
+       /* Delay for three times as long as the one shot timer period, then check \r
+       to ensure it has only called its callback once, and is now not in the \r
+       active state. */\r
+       vTaskDelay( tmrdemoONE_SHOT_TIMER_PERIOD * ( portTickType ) 3 );\r
 \r
-               for( ucTimer = 0; ucTimer < trmdemoNUM_TIMER_RESETS; ucTimer++ )\r
-               {\r
-                       /* Delay for half as long as the one shot timer period, then\r
-                       reset it.  It should never expire while this is done, so its callback\r
-                       count should never increment. */\r
-                       vTaskDelay( tmrdemoONE_SHOT_TIMER_FREQUENCY / 2 );\r
-\r
-                       /* Check both running timers are still active, but have not called their\r
-                       callback functions. */\r
-                       if( xTimerIsTimerActive( xOneShotTimer ) != pdFALSE )\r
-                       {\r
-                               xTestStatus = pdFAIL;\r
-                       }\r
+       if( xTimerIsTimerActive( xOneShotTimer ) != pdFALSE )\r
+       {\r
+               xTestStatus = pdFAIL;\r
+       }\r
 \r
-                       if( ucOneShotTimerCounter != ( unsigned char ) 0 )\r
-                       {\r
-                               xTestStatus = pdFAIL;\r
-                       }\r
+       if( ucOneShotTimerCounter != ( unsigned char ) 1 )\r
+       {\r
+               xTestStatus = pdFAIL;\r
+       }\r
+       else\r
+       {\r
+               /* Reset the one shot timer callback count. */\r
+               ucOneShotTimerCounter = ( unsigned char ) 0;\r
+       }\r
 \r
-                       if( xTimerIsTimerActive( xFreeRunningTimers[ configTIMER_QUEUE_LENGTH - 1 ] ) != pdFALSE )\r
-                       {\r
-                               xTestStatus = pdFAIL;\r
-                       }\r
+       if( xTestStatus == pdPASS )\r
+       {\r
+               /* No errors have been reported so increment the loop counter so the \r
+               check task knows this task is still running. */\r
+               ulLoopCounter++;\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
 \r
-                       if( ucFreeRunningTimerCounters[ configTIMER_QUEUE_LENGTH - 1 ] != ( unsigned char ) 0 )\r
-                       {\r
-                               xTestStatus = pdFAIL;\r
-                       }\r
+static void prvTest6_CheckAutoReloadResetBehaviour( void )\r
+{\r
+unsigned char ucTimer;\r
 \r
-                       /* Reset both running timers. */\r
-                       xTimerReset( xOneShotTimer, tmrdemoDONT_BLOCK );\r
-                       xTimerReset( xFreeRunningTimers[ configTIMER_QUEUE_LENGTH - 1 ], tmrdemoDONT_BLOCK );\r
+       /* Check timer reset behaviour. */\r
 \r
-                       if( xTestStatus == pdPASS )\r
-                       {\r
-                               /* No errors have been reported so increment the loop counter so\r
-                               the check task knows this task is still running. */\r
-                               ulLoopCounter++;\r
-                       }\r
-               }\r
+       /* Restart the one shot timer and check it reports its status correctly. */\r
+       xTimerStart( xOneShotTimer, tmrdemoDONT_BLOCK );\r
+       if( xTimerIsTimerActive( xOneShotTimer ) == pdFALSE )\r
+       {\r
+               xTestStatus = pdFAIL;\r
+       }\r
 \r
-               /* Finally delay long enough for both running timers to expire. */\r
-               vTaskDelay( ( ( portTickType ) configTIMER_QUEUE_LENGTH ) * xBaseFrequency );\r
+       /* Restart one of the auto reload timers and check that it reports its\r
+       status correctly. */\r
+       xTimerStart( xAutoReloadTimers[ configTIMER_QUEUE_LENGTH - 1 ], tmrdemoDONT_BLOCK );\r
+       if( xTimerIsTimerActive( xAutoReloadTimers[ configTIMER_QUEUE_LENGTH - 1 ] ) == pdFALSE )\r
+       {\r
+               xTestStatus = pdFAIL;\r
+       }\r
 \r
-               /* The timers were not reset during the above delay period so should now\r
-               both have called their callback functions. */\r
-               if( ucOneShotTimerCounter != ( unsigned char ) 1 )\r
-               {\r
-                       xTestStatus = pdFAIL;\r
-               }\r
+       for( ucTimer = 0; ucTimer < trmdemoNUM_TIMER_RESETS; ucTimer++ )\r
+       {\r
+               /* Delay for half as long as the one shot timer period, then reset it.  \r
+               It should never expire while this is done, so its callback count should \r
+               never increment. */\r
+               vTaskDelay( tmrdemoONE_SHOT_TIMER_PERIOD / 2 );\r
 \r
-               if( ucFreeRunningTimerCounters[ configTIMER_QUEUE_LENGTH - 1 ] == 0 )\r
+               /* Check both running timers are still active, but have not called their\r
+               callback functions. */\r
+               if( xTimerIsTimerActive( xOneShotTimer ) == pdFALSE )\r
                {\r
                        xTestStatus = pdFAIL;\r
                }\r
 \r
-               /* The one shot timer should no longer be active, while the free running\r
-               timer should still be active. */\r
-               if( xTimerIsTimerActive( xFreeRunningTimers[ configTIMER_QUEUE_LENGTH - 1 ] ) == pdFALSE )\r
+               if( ucOneShotTimerCounter != ( unsigned char ) 0 )\r
                {\r
                        xTestStatus = pdFAIL;\r
                }\r
 \r
-               if( xTimerIsTimerActive( xOneShotTimer ) == pdTRUE )\r
+               if( xTimerIsTimerActive( xAutoReloadTimers[ configTIMER_QUEUE_LENGTH - 1 ] ) == pdFALSE )\r
                {\r
                        xTestStatus = pdFAIL;\r
                }\r
 \r
-               /* Stop the free running timer again. */\r
-               xTimerStop( xFreeRunningTimers[ configTIMER_QUEUE_LENGTH - 1 ], tmrdemoDONT_BLOCK );\r
-\r
-               if( xTimerIsTimerActive( xFreeRunningTimers[ configTIMER_QUEUE_LENGTH - 1 ] ) != pdFALSE )\r
+               if( ucAutoReloadTimerCounters[ configTIMER_QUEUE_LENGTH - 1 ] != ( unsigned char ) 0 )\r
                {\r
                        xTestStatus = pdFAIL;\r
                }\r
 \r
-               /* Clear the timer callback counts, ready for another iteration of these\r
-               tests. */\r
-               ucFreeRunningTimerCounters[ configTIMER_QUEUE_LENGTH - 1 ] = ( unsigned char ) 0;\r
-               ucOneShotTimerCounter = ( unsigned char ) 0;\r
+               /* Reset both running timers. */\r
+               xTimerReset( xOneShotTimer, tmrdemoDONT_BLOCK );\r
+               xTimerReset( xAutoReloadTimers[ configTIMER_QUEUE_LENGTH - 1 ], tmrdemoDONT_BLOCK );\r
 \r
                if( xTestStatus == pdPASS )\r
                {\r
-                       /* No errors have been reported so increment the loop counter so\r
+                       /* No errors have been reported so increment the loop counter so \r
                        the check task knows this task is still running. */\r
                        ulLoopCounter++;\r
                }\r
+       }\r
 \r
+       /* Finally delay long enough for both running timers to expire. */\r
+       vTaskDelay( ( ( portTickType ) configTIMER_QUEUE_LENGTH ) * xBasePeriod );\r
 \r
+       /* The timers were not reset during the above delay period so should now\r
+       both have called their callback functions. */\r
+       if( ucOneShotTimerCounter != ( unsigned char ) 1 )\r
+       {\r
+               xTestStatus = pdFAIL;\r
+       }\r
 \r
+       if( ucAutoReloadTimerCounters[ configTIMER_QUEUE_LENGTH - 1 ] == 0 )\r
+       {\r
+               xTestStatus = pdFAIL;\r
+       }\r
 \r
-               /*-----------------------------------------------------------*/\r
-               /* Start the timers again to start all the tests over again. */\r
+       /* The one shot timer should no longer be active, while the auto reload\r
+       timer should still be active. */\r
+       if( xTimerIsTimerActive( xAutoReloadTimers[ configTIMER_QUEUE_LENGTH - 1 ] ) == pdFALSE )\r
+       {\r
+               xTestStatus = pdFAIL;\r
+       }\r
 \r
+       if( xTimerIsTimerActive( xOneShotTimer ) == pdTRUE )\r
+       {\r
+               xTestStatus = pdFAIL;\r
+       }\r
 \r
-               /* Start the timers again. */\r
-               for( ucTimer = 0; ucTimer < ( unsigned char ) configTIMER_QUEUE_LENGTH; ucTimer++ )\r
-               {\r
-                       /* The timer has not been started yet! */\r
-                       if( xTimerIsTimerActive( xFreeRunningTimers[ ucTimer ] ) != pdFALSE )\r
-                       {\r
-                               xTestStatus = pdFAIL;\r
-                       }\r
+       /* Stop the auto reload timer again. */\r
+       xTimerStop( xAutoReloadTimers[ configTIMER_QUEUE_LENGTH - 1 ], tmrdemoDONT_BLOCK );\r
 \r
-                       /* Now start the timer.  This will appear to happen immediately to \r
-                       this task because this task is running at a priority below the \r
-                       timer service task. */\r
-                       xTimerStart( xFreeRunningTimers[ ucTimer ], tmrdemoDONT_BLOCK );\r
+       if( xTimerIsTimerActive( xAutoReloadTimers[ configTIMER_QUEUE_LENGTH - 1 ] ) != pdFALSE )\r
+       {\r
+               xTestStatus = pdFAIL;\r
+       }\r
 \r
-                       /* The timer should now be active. */\r
-                       if( xTimerIsTimerActive( xFreeRunningTimers[ ucTimer ] ) == pdFALSE )\r
-                       {\r
-                               xTestStatus = pdFAIL;\r
-                       }\r
-               }\r
+       /* Clear the timer callback counts, ready for another iteration of these\r
+       tests. */\r
+       ucAutoReloadTimerCounters[ configTIMER_QUEUE_LENGTH - 1 ] = ( unsigned char ) 0;\r
+       ucOneShotTimerCounter = ( unsigned char ) 0;\r
 \r
-               if( xTestStatus == pdPASS )\r
-               {\r
-                       /* No errors have been reported so increment the loop counter so\r
-                       the check task knows this task is still running. */\r
-                       ulLoopCounter++;\r
-               }\r
+       if( xTestStatus == pdPASS )\r
+       {\r
+               /* No errors have been reported so increment the loop counter so the check \r
+               task knows this task is still running. */\r
+               ulLoopCounter++;\r
        }\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-/* This is called to check that the created task is still running and has not\r
-detected any errors. */\r
-portBASE_TYPE xAreTimerDemoTasksStillRunning( void )\r
+static void prvResetStartConditionsForNextIteration( void )\r
 {\r
-static unsigned portLONG ulLastLoopCounter = 0;\r
+unsigned char ucTimer;\r
 \r
-       /* If the demo task is still running then we expect the loopcounter to\r
-       have incremented since this function was last called. */\r
-       if( ulLastLoopCounter == ulLoopCounter )\r
+       /* Start the timers again to start all the tests over again. */\r
+\r
+       /* Start the timers again. */\r
+       for( ucTimer = 0; ucTimer < ( unsigned char ) configTIMER_QUEUE_LENGTH; ucTimer++ )\r
        {\r
-               xTestStatus = pdFAIL;\r
-       }\r
+               /* The timer has not been started yet! */\r
+               if( xTimerIsTimerActive( xAutoReloadTimers[ ucTimer ] ) != pdFALSE )\r
+               {\r
+                       xTestStatus = pdFAIL;\r
+               }\r
 \r
-       ulLastLoopCounter = ulLoopCounter;\r
+               /* Now start the timer.  This will appear to happen immediately to\r
+               this task because this task is running at a priority below the timer \r
+               service task. */\r
+               xTimerStart( xAutoReloadTimers[ ucTimer ], tmrdemoDONT_BLOCK );\r
 \r
-       /* Errors detected in the task itself will have latched xTestStatus\r
-       to pdFAIL. */\r
+               /* The timer should now be active. */\r
+               if( xTimerIsTimerActive( xAutoReloadTimers[ ucTimer ] ) == pdFALSE )\r
+               {\r
+                       xTestStatus = pdFAIL;\r
+               }\r
+       }\r
 \r
-       return xTestStatus;\r
+       if( xTestStatus == pdPASS )\r
+       {\r
+               /* No errors have been reported so increment the loop counter so the \r
+               check task knows this task is still running. */\r
+               ulLoopCounter++;\r
+       }\r
 }\r
+/*-----------------------------------------------------------*/\r
 \r