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
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
}\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
\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
}\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