]> 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
     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
     by writing to Richard Barry, contact details for whom are available on the\r
     FreeRTOS WEB site.\r
 \r
 */\r
 \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
  * 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
 \r
 /* Scheduler include files. */\r
 #include "FreeRTOS.h"\r
 #endif\r
 \r
 #define tmrdemoDONT_BLOCK                              ( ( portTickType ) 0 )\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
 #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 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
 /*-----------------------------------------------------------*/\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
 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
 \r
-static portTickType xBaseFrequency = 0;\r
+static portTickType xBasePeriod = 0;\r
 \r
 /*-----------------------------------------------------------*/\r
 \r
 \r
 /*-----------------------------------------------------------*/\r
 \r
-void vStartTimerDemoTask( portTickType xBaseFrequencyIn )\r
+void vStartTimerDemoTask( portTickType xBasePeriodIn )\r
 {\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
 \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
 \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
        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
        (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
 }\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
 {\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
        }\r
        else\r
        {\r
@@ -196,16 +159,11 @@ static void prvOneShotTimerCallback( xTimerHandle pxExpiredTimer )
 \r
 static void prvTimerControlTask( void *pvParameters )\r
 {\r
 \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
        ( 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
                                                                        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
 \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
        depends on the timer service task having a higher priority than this task. */\r
+       prvTest2_CheckTaskAndTimersInitialState();\r
 \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
        {\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
 \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
        {\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
 \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
 \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
 \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
 \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
                {\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
-               /*-----------------------------------------------------------*/\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
                {\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
                                xTestStatus = pdFAIL;\r
                        }\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
 \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
 \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
 \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
 \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
                {\r
-                       if( ucFreeRunningTimerCounters[ ucTimer ] != ( unsigned char ) 0 )\r
-                       {\r
-                               xTestStatus = pdFAIL;\r
-                       }\r
+                       xTestStatus = pdFAIL;\r
                }\r
                }\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
 \r
+static void    prvTest3_CheckAutoReloadExpireRates( void )\r
+{\r
+unsigned char ucMaxAllowableValue, ucMinAllowableValue, ucTimer;\r
+portTickType xNextWakeTime;\r
 \r
 \r
+       /* Check the auto reload timers expire at the expcted rates. */\r
 \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
 \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
 \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
                        xTestStatus = pdFAIL;\r
                }\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
                {\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
 \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
                        xTestStatus = pdFAIL;\r
                }\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
                {\r
                        xTestStatus = pdFAIL;\r
                }\r
-               else\r
-               {\r
-                       /* Reset the one shot timer callback count. */\r
-                       ucOneShotTimerCounter = ( unsigned char ) 0;\r
-               }\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
                {\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
+       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
 \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
 \r
+       /* The one shot timer should not be active yet. */\r
+       if( xTimerIsTimerActive( xOneShotTimer ) != pdFALSE )\r
+       {\r
+               xTestStatus = pdFAIL;\r
+       }\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
 \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
 \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
 \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
 \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
 \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
 \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
 \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
 \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
 \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
 \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
 \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
                {\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
                {\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
                {\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
                {\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
 \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
                        the check task knows this task is still running. */\r
                        ulLoopCounter++;\r
                }\r
+       }\r
 \r
 \r
+       /* Finally delay long enough for both running timers to expire. */\r
+       vTaskDelay( ( ( portTickType ) configTIMER_QUEUE_LENGTH ) * xBasePeriod );\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
 \r
 \r
+       if( ucAutoReloadTimerCounters[ configTIMER_QUEUE_LENGTH - 1 ] == 0 )\r
+       {\r
+               xTestStatus = pdFAIL;\r
+       }\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
 \r
+       if( xTimerIsTimerActive( xOneShotTimer ) == pdTRUE )\r
+       {\r
+               xTestStatus = pdFAIL;\r
+       }\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
 \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
 \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
 \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
        }\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
 {\r
-static unsigned portLONG ulLastLoopCounter = 0;\r
+unsigned char ucTimer;\r
 \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
        {\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
 \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
 \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
 \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
 \r
 \r