]> git.sur5r.net Git - freertos/blob - Demo/Common/Minimal/TimerDemo.c
00a67c46f60762fc6a762b99ee92d6e4a5bed8e0
[freertos] / Demo / Common / Minimal / TimerDemo.c
1 /*\r
2     FreeRTOS V6.1.1 - Copyright (C) 2011 Real Time Engineers Ltd.\r
3 \r
4     ***************************************************************************\r
5     *                                                                         *\r
6     * If you are:                                                             *\r
7     *                                                                         *\r
8     *    + New to FreeRTOS,                                                   *\r
9     *    + Wanting to learn FreeRTOS or multitasking in general quickly       *\r
10     *    + Looking for basic training,                                        *\r
11     *    + Wanting to improve your FreeRTOS skills and productivity           *\r
12     *                                                                         *\r
13     * then take a look at the FreeRTOS books - available as PDF or paperback  *\r
14     *                                                                         *\r
15     *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *\r
16     *                  http://www.FreeRTOS.org/Documentation                  *\r
17     *                                                                         *\r
18     * A pdf reference manual is also available.  Both are usually delivered   *\r
19     * to your inbox within 20 minutes to two hours when purchased between 8am *\r
20     * and 8pm GMT (although please allow up to 24 hours in case of            *\r
21     * exceptional circumstances).  Thank you for your support!                *\r
22     *                                                                         *\r
23     ***************************************************************************\r
24 \r
25     This file is part of the FreeRTOS distribution.\r
26 \r
27     FreeRTOS is free software; you can redistribute it and/or modify it under\r
28     the terms of the GNU General Public License (version 2) as published by the\r
29     Free Software Foundation AND MODIFIED BY the FreeRTOS exception.\r
30     ***NOTE*** The exception to the GPL is included to allow you to distribute\r
31     a combined work that includes FreeRTOS without being obliged to provide the\r
32     source code for proprietary components outside of the FreeRTOS kernel.\r
33     FreeRTOS is distributed in the hope that it will be useful, but WITHOUT\r
34     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
35     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for\r
36     more details. You should have received a copy of the GNU General Public \r
37     License and the FreeRTOS license exception along with FreeRTOS; if not it \r
38     can be viewed here: http://www.freertos.org/a00114.html and also obtained \r
39     by writing to Richard Barry, contact details for whom are available on the\r
40     FreeRTOS WEB site.\r
41 \r
42     1 tab == 4 spaces!\r
43 \r
44     http://www.FreeRTOS.org - Documentation, latest information, license and\r
45     contact details.\r
46 \r
47     http://www.SafeRTOS.com - A version that is certified for use in safety\r
48     critical systems.\r
49 \r
50     http://www.OpenRTOS.com - Commercial support, development, porting,\r
51     licensing and training services.\r
52 */\r
53 \r
54 \r
55 /* \r
56  * Tests the behaviour of timers.  Some timers are created before hte scheudler\r
57  * is started, and some after.\r
58  */\r
59 \r
60 \r
61 /* Scheduler include files. */\r
62 #include "FreeRTOS.h"\r
63 #include "task.h"\r
64 #include "timers.h"\r
65 \r
66 /* Demo program include files. */\r
67 #include "TimerDemo.h"\r
68 \r
69 #if configTIMER_TASK_PRIORITY < 1\r
70         #error configTIMER_TASK_PRIORITY must be set to at least 1 for this test/demo to function correctly.\r
71 #endif\r
72 \r
73 #define tmrdemoDONT_BLOCK                               ( ( portTickType ) 0 )\r
74 #define tmrdemoONE_SHOT_TIMER_FREQUENCY ( xBaseFrequency * ( portTickType ) 3 )\r
75 #define trmdemoNUM_TIMER_RESETS                 ( ( unsigned char ) 10 )\r
76 \r
77 /*-----------------------------------------------------------*/\r
78 \r
79 static void prvFreeRunningTimerCallback( xTimerHandle pxExpiredTimer );\r
80 static void prvTimerControlTask( void *pvParameters );\r
81 \r
82 /*-----------------------------------------------------------*/\r
83 \r
84 /* Flag that will be latched to pdFAIL should any unexpected behaviour be\r
85 detected in any of the demo tests. */\r
86 static volatile portBASE_TYPE xTestStatus = pdPASS;\r
87 \r
88 /* Counter that is incremented on each cycle of a test.  This is used to\r
89 detect a stalled task - a test that is no longer running. */\r
90 static volatile unsigned portLONG ulLoopCounter = 0;\r
91 \r
92 xTimerHandle xFreeRunningTimers[ configTIMER_QUEUE_LENGTH + 1 ] = { 0 };\r
93 unsigned char ucFreeRunningTimerCounters[ configTIMER_QUEUE_LENGTH + 1 ] = { 0 };\r
94 unsigned char ucOneShotTimerCounter = ( unsigned char ) 0;\r
95 \r
96 static portTickType xBaseFrequency = 0;\r
97 \r
98 /*-----------------------------------------------------------*/\r
99 \r
100 void vStartTimerDemoTask( portTickType xBaseFrequencyIn )\r
101 {\r
102 portBASE_TYPE xTimer;\r
103 \r
104         xBaseFrequency = xBaseFrequencyIn;\r
105 \r
106         for( xTimer = 0; xTimer < configTIMER_QUEUE_LENGTH; xTimer++ )\r
107         {\r
108                 /* As the timer queue is not yet full, it should be possible to both create\r
109                 and start a timer.  These timers are being started before the scheduler has\r
110                 been started, so their block times should get set to zero within the timer\r
111                 API itself. */\r
112                 xFreeRunningTimers[ xTimer ] = xTimerCreate( "FR Timer",                                                /* Text name to facilitate debugging.  The kernel does not use this itself. */\r
113                                                                                                         ( ( xTimer + 1 ) * xBaseFrequency ),/* The period for the timer.  The plus 1 ensures a period of zero is not specified. */\r
114                                                                                                         pdTRUE,                                                         /* Autoreload is set to true. */\r
115                                                                                                         ( void * ) xTimer,                                      /* An identifier for the timer as all the free running timers use the same callback. */\r
116                                                                                                         prvFreeRunningTimerCallback );          /* The callback to be called when the timer expires. */\r
117 \r
118                 if( xFreeRunningTimers[ xTimer ] == NULL )\r
119                 {\r
120                         xTestStatus = pdFAIL;\r
121                 }\r
122                 else\r
123                 {\r
124                         /* The scheduler has not yet started, so the block period of \r
125                         portMAX_DELAY should just get set to zero in xTimerStart().  Also,\r
126                         the timer queue is not yet full so xTimerStart() should return\r
127                         pdPASS. */\r
128                         if( xTimerStart( xFreeRunningTimers[ xTimer ], portMAX_DELAY ) != pdPASS )\r
129                         {\r
130                                 xTestStatus = pdFAIL;\r
131                         }\r
132                 }\r
133         }\r
134 \r
135         /* The timers queue should now be full, so it should be possible to create\r
136         another timer, but not possible to start it (the timer queue will not get\r
137         drained until the scheduler has been started. */\r
138         xFreeRunningTimers[ configTIMER_QUEUE_LENGTH ] = xTimerCreate( "FR Timer",              /* Text name to facilitate debugging.  The kernel does not use this itself. */\r
139                                                                                                         ( configTIMER_QUEUE_LENGTH * xBaseFrequency ),  /* The period for the timer. */\r
140                                                                                                         pdTRUE,                                                 /* Autoreload is set to true. */\r
141                                                                                                         ( void * ) xTimer,                              /* An identifier for the timer as all the free running timers use the same callback. */\r
142                                                                                                         prvFreeRunningTimerCallback );  /* The callback to be called when the timer expires. */\r
143 \r
144         if( xFreeRunningTimers[ configTIMER_QUEUE_LENGTH ] == NULL )\r
145         {\r
146                 xTestStatus = pdFAIL;\r
147         }\r
148         else\r
149         {\r
150                 if( xTimerStart( xFreeRunningTimers[ xTimer ], portMAX_DELAY ) == pdPASS )\r
151                 {\r
152                         /* This time it would not be expected that the timer could be\r
153                         started at this point. */\r
154                         xTestStatus = pdFAIL;\r
155                 }\r
156         }\r
157 \r
158         /* Create the task that will control and monitor the timers.  This is \r
159         created at a lower priority than the timer service task to ensure, as\r
160         far as it is concerned, commands on timers are actioned immediately \r
161         (sending a command to the timer service task will unblock the timer service\r
162         task, which will then preempt this task). */\r
163         if( xTestStatus != pdFAIL )\r
164         {\r
165                 xTaskCreate( prvTimerControlTask, ( signed portCHAR * ) "Tmr Ctl", configMINIMAL_STACK_SIZE, NULL, configTIMER_TASK_PRIORITY - 1, NULL );\r
166         }\r
167 }\r
168 /*-----------------------------------------------------------*/\r
169 \r
170 static void prvFreeRunningTimerCallback( xTimerHandle pxExpiredTimer )\r
171 {\r
172 portBASE_TYPE xTimerID;\r
173 \r
174         xTimerID = ( portBASE_TYPE ) pvTimerGetTimerID( pxExpiredTimer );\r
175         if( xTimerID <= ( configTIMER_QUEUE_LENGTH + 1 ) )\r
176         {\r
177                 ( ucFreeRunningTimerCounters[ xTimerID ] )++;\r
178         }\r
179         else\r
180         {\r
181                 /* The timer ID appears to be unexpected (invalid). */\r
182                 xTestStatus = pdFAIL;\r
183         }\r
184 }\r
185 /*-----------------------------------------------------------*/\r
186 \r
187 static void prvOneShotTimerCallback( xTimerHandle pxExpiredTimer )\r
188 {\r
189         /* The parameter is not used in this case as only one timer uses this\r
190         callback function. */\r
191         ( void ) pxExpiredTimer;\r
192 \r
193         ucOneShotTimerCounter++;\r
194 }\r
195 /*-----------------------------------------------------------*/\r
196 \r
197 static void prvTimerControlTask( void *pvParameters )\r
198 {\r
199 portTickType xNextWakeTime;\r
200 unsigned char ucTimer;\r
201 unsigned char ucMaxAllowableValue, ucMinAllowableValue;\r
202 xTimerHandle xOneShotTimer = NULL;\r
203 \r
204         ( void ) pvParameters;\r
205 \r
206         /* Create a one-shot timer for use later on in this test. */\r
207         xOneShotTimer = xTimerCreate(   "Oneshot Timer",                                /* Text name to facilitate debugging.  The kernel does not use this itself. */\r
208                                                                         tmrdemoONE_SHOT_TIMER_FREQUENCY,/* The period for the timer. */\r
209                                                                         pdFALSE,                                                /* Don't autoreload - hence a one shot timer. */\r
210                                                                         ( void * ) 0,                                   /* The timer identifier.  In this case this is not used as the timer has its own callback. */\r
211                                                                         prvOneShotTimerCallback );              /* The callback to be called when the timer expires. */\r
212 \r
213         if( xOneShotTimer == NULL )\r
214         {\r
215                 xTestStatus = pdFAIL;\r
216         }\r
217 \r
218 \r
219         /*-----------------------------------------------------------*/\r
220         /* Test 1 - ensure all the timers are in their expected initial state.  This\r
221         depends on the timer service task having a higher priority than this task. */\r
222 \r
223         /* Free running timers 0 to ( configTIMER_QUEUE_LENGTH - 1 ) should now\r
224         be active, and free running timer configTIMER_QUEUE_LENGTH should not\r
225         yet be active (it could not be started prior to the scheduler being\r
226         started. */\r
227         for( ucTimer = 0; ucTimer < ( unsigned char ) configTIMER_QUEUE_LENGTH; ucTimer++ )\r
228         {\r
229                 if( xTimerIsTimerActive( xFreeRunningTimers[ ucTimer ] ) == pdFALSE )\r
230                 {\r
231                         xTestStatus = pdFAIL;\r
232                 }\r
233         }\r
234 \r
235         if( xTimerIsTimerActive( xFreeRunningTimers[ configTIMER_QUEUE_LENGTH ] ) != pdFALSE )\r
236         {\r
237                 xTestStatus = pdFAIL;\r
238         }\r
239 \r
240         for( ;; )\r
241         {\r
242                 /*-----------------------------------------------------------*/\r
243                 /* Test 2 - Check the free running timers expire at the expcted rates. */\r
244 \r
245                 /* Initialise the next wake time value before the call to \r
246                 vTaskDelayUntil() as this is not really a periodic task. */\r
247                 xNextWakeTime = xTaskGetTickCount();\r
248 \r
249                 /* Delaying for configTIMER_QUEUE_LENGTH * xBaseFrequency ticks \r
250                 should allow all the free running timers to expire at least once. */\r
251                 vTaskDelayUntil( &xNextWakeTime, ( ( portTickType ) configTIMER_QUEUE_LENGTH ) * xBaseFrequency );\r
252 \r
253                 /* Check that all the free running timers have called their callback \r
254                 function the expected number of times. */\r
255                 for( ucTimer = 0; ucTimer < ( unsigned char ) configTIMER_QUEUE_LENGTH; ucTimer++ )\r
256                 {\r
257                         /* The timer in array position 0 should elapse every xBaseFrequency \r
258                         ticks, the timer in array position 1 should elapse every\r
259                         ( 2 * xBaseFrequency ) ticks, etc.  This task blocked for \r
260                         configTIMER_QUEUE_LENGTH * xBaseFrequency, so the timer in array\r
261                         position 0 should have elapsed configTIMER_QUEUE_LENGTH times, the\r
262                         timer in array possition 1 should have elapsed \r
263                         ( configTIMER_QUEUE_LENGTH - 1 ) times, etc. */\r
264                         ucMaxAllowableValue = ( ( ( unsigned char ) configTIMER_QUEUE_LENGTH ) - ucTimer );\r
265                         ucMinAllowableValue = ( ( ( unsigned char ) configTIMER_QUEUE_LENGTH ) - ucTimer ) - 1;\r
266 \r
267                         if( ( ucFreeRunningTimerCounters[ ucTimer ] < ucMinAllowableValue ) ||\r
268                                 ( ucFreeRunningTimerCounters[ ucTimer ] > ucMaxAllowableValue )\r
269                           )\r
270                         {\r
271                                 xTestStatus = pdFAIL;\r
272                         }\r
273                 }\r
274 \r
275                 if( xTestStatus == pdPASS )\r
276                 {\r
277                         /* No errors have been reported so increment the loop counter so\r
278                         the check task knows this task is still running. */\r
279                         ulLoopCounter++;\r
280                 }\r
281 \r
282 \r
283 \r
284 \r
285                 /*-----------------------------------------------------------*/\r
286                 /* Test 3 - Check the free running timers can be stopped correctly, and\r
287                 correctly report their state. */\r
288 \r
289                 /* Stop all the active timers. */\r
290                 for( ucTimer = 0; ucTimer < ( unsigned char ) configTIMER_QUEUE_LENGTH; ucTimer++ )\r
291                 {\r
292                         /* The timer has not been stopped yet! */\r
293                         if( xTimerIsTimerActive( xFreeRunningTimers[ ucTimer ] ) == pdFALSE )\r
294                         {\r
295                                 xTestStatus = pdFAIL;\r
296                         }\r
297 \r
298                         /* Now stop the timer.  This will appear to happen immediately to \r
299                         this task because this task is running at a priority below the \r
300                         timer service task. */\r
301                         xTimerStop( xFreeRunningTimers[ ucTimer ], tmrdemoDONT_BLOCK );\r
302 \r
303                         /* The timer should now be inactive. */\r
304                         if( xTimerIsTimerActive( xFreeRunningTimers[ ucTimer ] ) != pdFALSE )\r
305                         {\r
306                                 xTestStatus = pdFAIL;\r
307                         }\r
308                 }\r
309 \r
310                 taskENTER_CRITICAL();\r
311                 {\r
312                         /* The timer in array position configTIMER_QUEUE_LENGTH should not \r
313                         be active.  The critical section is used to ensure the timer does \r
314                         not call its callback between the next line running and the array \r
315                         being cleared back to zero, as that would mask an error condition. */\r
316                         if( ucFreeRunningTimerCounters[ configTIMER_QUEUE_LENGTH ] != ( unsigned char ) 0 )\r
317                         {\r
318                                 xTestStatus = pdFAIL;\r
319                         }\r
320 \r
321                         /* Clear the timer callback count. */\r
322                         memset( ( void * ) ucFreeRunningTimerCounters, 0, sizeof( ucFreeRunningTimerCounters ) );\r
323                 }\r
324                 taskEXIT_CRITICAL();\r
325 \r
326                 /* The timers are now all inactive, so this time, after delaying, none\r
327                 of the callback counters should have incremented. */\r
328                 vTaskDelay( ( ( portTickType ) configTIMER_QUEUE_LENGTH ) * xBaseFrequency );\r
329                 for( ucTimer = 0; ucTimer < ( unsigned char ) configTIMER_QUEUE_LENGTH; ucTimer++ )\r
330                 {\r
331                         if( ucFreeRunningTimerCounters[ ucTimer ] != ( unsigned char ) 0 )\r
332                         {\r
333                                 xTestStatus = pdFAIL;\r
334                         }\r
335                 }\r
336 \r
337                 if( xTestStatus == pdPASS )\r
338                 {\r
339                         /* No errors have been reported so increment the loop counter so\r
340                         the check task knows this task is still running. */\r
341                         ulLoopCounter++;\r
342                 }\r
343 \r
344 \r
345 \r
346                 /*-----------------------------------------------------------*/\r
347                 /* Test 4 - Check the one shot timer only calls its callback once after\r
348                 it has been started, and that it reports its state correctly. */\r
349 \r
350                 /* The one shot timer should not be active yet. */\r
351                 if( xTimerIsTimerActive( xOneShotTimer ) != pdFALSE )\r
352                 {\r
353                         xTestStatus = pdFAIL;\r
354                 }\r
355 \r
356                 if( ucOneShotTimerCounter != ( unsigned char ) 0 )\r
357                 {\r
358                         xTestStatus = pdFAIL;\r
359                 }\r
360 \r
361                 /* Start the one shot timer and check that it reports its state\r
362                 correctly. */\r
363                 xTimerStart( xOneShotTimer, tmrdemoDONT_BLOCK );\r
364                 if( xTimerIsTimerActive( xOneShotTimer ) == pdFALSE )\r
365                 {\r
366                         xTestStatus = pdFAIL;\r
367                 }\r
368 \r
369                 /* Delay for three times as long as the one shot timer period, then\r
370                 check to ensure it has only called its callback once, and is now\r
371                 not in the active state. */\r
372                 vTaskDelay( tmrdemoONE_SHOT_TIMER_FREQUENCY * ( portTickType ) 3 );\r
373 \r
374                 if( xTimerIsTimerActive( xOneShotTimer ) != pdFALSE )\r
375                 {\r
376                         xTestStatus = pdFAIL;\r
377                 }\r
378 \r
379                 if( ucOneShotTimerCounter != ( unsigned char ) 1 )\r
380                 {\r
381                         xTestStatus = pdFAIL;\r
382                 }\r
383                 else\r
384                 {\r
385                         /* Reset the one shot timer callback count. */\r
386                         ucOneShotTimerCounter = ( unsigned char ) 0;\r
387                 }\r
388 \r
389                 if( xTestStatus == pdPASS )\r
390                 {\r
391                         /* No errors have been reported so increment the loop counter so\r
392                         the check task knows this task is still running. */\r
393                         ulLoopCounter++;\r
394                 }\r
395 \r
396 \r
397 \r
398 \r
399                 /*-----------------------------------------------------------*/\r
400                 /* Test 5 - Check all the timers can be reset while they are running. */\r
401 \r
402                 /* Restart the one shot timer and check it reports its status \r
403                 correctly. */\r
404                 xTimerStart( xOneShotTimer, tmrdemoDONT_BLOCK );\r
405                 if( xTimerIsTimerActive( xOneShotTimer ) == pdFALSE )\r
406                 {\r
407                         xTestStatus = pdFAIL;\r
408                 }\r
409 \r
410                 /* Restart one of the free running timers and check that it reports its\r
411                 status correctly. */\r
412                 xTimerStart( xFreeRunningTimers[ configTIMER_QUEUE_LENGTH - 1 ], tmrdemoDONT_BLOCK );\r
413                 if( xTimerIsTimerActive( xFreeRunningTimers[ configTIMER_QUEUE_LENGTH - 1 ] ) == pdFALSE )\r
414                 {\r
415                         xTestStatus = pdFAIL;\r
416                 }\r
417 \r
418                 for( ucTimer = 0; ucTimer < trmdemoNUM_TIMER_RESETS; ucTimer++ )\r
419                 {\r
420                         /* Delay for half as long as the one shot timer period, then\r
421                         reset it.  It should never expire while this is done, so its callback\r
422                         count should never increment. */\r
423                         vTaskDelay( tmrdemoONE_SHOT_TIMER_FREQUENCY / 2 );\r
424 \r
425                         /* Check both running timers are still active, but have not called their\r
426                         callback functions. */\r
427                         if( xTimerIsTimerActive( xOneShotTimer ) != pdFALSE )\r
428                         {\r
429                                 xTestStatus = pdFAIL;\r
430                         }\r
431 \r
432                         if( ucOneShotTimerCounter != ( unsigned char ) 0 )\r
433                         {\r
434                                 xTestStatus = pdFAIL;\r
435                         }\r
436 \r
437                         if( xTimerIsTimerActive( xFreeRunningTimers[ configTIMER_QUEUE_LENGTH - 1 ] ) != pdFALSE )\r
438                         {\r
439                                 xTestStatus = pdFAIL;\r
440                         }\r
441 \r
442                         if( ucFreeRunningTimerCounters[ configTIMER_QUEUE_LENGTH - 1 ] != ( unsigned char ) 0 )\r
443                         {\r
444                                 xTestStatus = pdFAIL;\r
445                         }\r
446 \r
447                         /* Reset both running timers. */\r
448                         xTimerReset( xOneShotTimer, tmrdemoDONT_BLOCK );\r
449                         xTimerReset( xFreeRunningTimers[ configTIMER_QUEUE_LENGTH - 1 ], tmrdemoDONT_BLOCK );\r
450 \r
451                         if( xTestStatus == pdPASS )\r
452                         {\r
453                                 /* No errors have been reported so increment the loop counter so\r
454                                 the check task knows this task is still running. */\r
455                                 ulLoopCounter++;\r
456                         }\r
457                 }\r
458 \r
459                 /* Finally delay long enough for both running timers to expire. */\r
460                 vTaskDelay( ( ( portTickType ) configTIMER_QUEUE_LENGTH ) * xBaseFrequency );\r
461 \r
462                 /* The timers were not reset during the above delay period so should now\r
463                 both have called their callback functions. */\r
464                 if( ucOneShotTimerCounter != ( unsigned char ) 1 )\r
465                 {\r
466                         xTestStatus = pdFAIL;\r
467                 }\r
468 \r
469                 if( ucFreeRunningTimerCounters[ configTIMER_QUEUE_LENGTH - 1 ] == 0 )\r
470                 {\r
471                         xTestStatus = pdFAIL;\r
472                 }\r
473 \r
474                 /* The one shot timer should no longer be active, while the free running\r
475                 timer should still be active. */\r
476                 if( xTimerIsTimerActive( xFreeRunningTimers[ configTIMER_QUEUE_LENGTH - 1 ] ) == pdFALSE )\r
477                 {\r
478                         xTestStatus = pdFAIL;\r
479                 }\r
480 \r
481                 if( xTimerIsTimerActive( xOneShotTimer ) == pdTRUE )\r
482                 {\r
483                         xTestStatus = pdFAIL;\r
484                 }\r
485 \r
486                 /* Stop the free running timer again. */\r
487                 xTimerStop( xFreeRunningTimers[ configTIMER_QUEUE_LENGTH - 1 ], tmrdemoDONT_BLOCK );\r
488 \r
489                 if( xTimerIsTimerActive( xFreeRunningTimers[ configTIMER_QUEUE_LENGTH - 1 ] ) != pdFALSE )\r
490                 {\r
491                         xTestStatus = pdFAIL;\r
492                 }\r
493 \r
494                 /* Clear the timer callback counts, ready for another iteration of these\r
495                 tests. */\r
496                 ucFreeRunningTimerCounters[ configTIMER_QUEUE_LENGTH - 1 ] = ( unsigned char ) 0;\r
497                 ucOneShotTimerCounter = ( unsigned char ) 0;\r
498 \r
499                 if( xTestStatus == pdPASS )\r
500                 {\r
501                         /* No errors have been reported so increment the loop counter so\r
502                         the check task knows this task is still running. */\r
503                         ulLoopCounter++;\r
504                 }\r
505 \r
506 \r
507 \r
508 \r
509                 /*-----------------------------------------------------------*/\r
510                 /* Start the timers again to start all the tests over again. */\r
511 \r
512 \r
513                 /* Start the timers again. */\r
514                 for( ucTimer = 0; ucTimer < ( unsigned char ) configTIMER_QUEUE_LENGTH; ucTimer++ )\r
515                 {\r
516                         /* The timer has not been started yet! */\r
517                         if( xTimerIsTimerActive( xFreeRunningTimers[ ucTimer ] ) != pdFALSE )\r
518                         {\r
519                                 xTestStatus = pdFAIL;\r
520                         }\r
521 \r
522                         /* Now start the timer.  This will appear to happen immediately to \r
523                         this task because this task is running at a priority below the \r
524                         timer service task. */\r
525                         xTimerStart( xFreeRunningTimers[ ucTimer ], tmrdemoDONT_BLOCK );\r
526 \r
527                         /* The timer should now be active. */\r
528                         if( xTimerIsTimerActive( xFreeRunningTimers[ ucTimer ] ) == pdFALSE )\r
529                         {\r
530                                 xTestStatus = pdFAIL;\r
531                         }\r
532                 }\r
533 \r
534                 if( xTestStatus == pdPASS )\r
535                 {\r
536                         /* No errors have been reported so increment the loop counter so\r
537                         the check task knows this task is still running. */\r
538                         ulLoopCounter++;\r
539                 }\r
540         }\r
541 }\r
542 /*-----------------------------------------------------------*/\r
543 \r
544 /* This is called to check that the created task is still running and has not\r
545 detected any errors. */\r
546 portBASE_TYPE xAreTimerDemoTasksStillRunning( void )\r
547 {\r
548 static unsigned portLONG ulLastLoopCounter = 0;\r
549 \r
550         /* If the demo task is still running then we expect the loopcounter to\r
551         have incremented since this function was last called. */\r
552         if( ulLastLoopCounter == ulLoopCounter )\r
553         {\r
554                 xTestStatus = pdFAIL;\r
555         }\r
556 \r
557         ulLastLoopCounter = ulLoopCounter;\r
558 \r
559         /* Errors detected in the task itself will have latched xTestStatus\r
560         to pdFAIL. */\r
561 \r
562         return xTestStatus;\r
563 }\r
564 \r