]> git.sur5r.net Git - freertos/blob - FreeRTOS/Source/timers.c
Updates to support FreeRTOS MPU in FreeRTOS V9.0.0 - including a GCC project that...
[freertos] / FreeRTOS / Source / timers.c
1 /*\r
2     FreeRTOS V9.0.0rc2 - Copyright (C) 2016 Real Time Engineers Ltd.\r
3     All rights reserved\r
4 \r
5     VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
6 \r
7     This file is part of the FreeRTOS distribution.\r
8 \r
9     FreeRTOS is free software; you can redistribute it and/or modify it under\r
10     the terms of the GNU General Public License (version 2) as published by the\r
11     Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.\r
12 \r
13     ***************************************************************************\r
14     >>!   NOTE: The modification to the GPL is included to allow you to     !<<\r
15     >>!   distribute a combined work that includes FreeRTOS without being   !<<\r
16     >>!   obliged to provide the source code for proprietary components     !<<\r
17     >>!   outside of the FreeRTOS kernel.                                   !<<\r
18     ***************************************************************************\r
19 \r
20     FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
21     WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
22     FOR A PARTICULAR PURPOSE.  Full license text is available on the following\r
23     link: http://www.freertos.org/a00114.html\r
24 \r
25     ***************************************************************************\r
26      *                                                                       *\r
27      *    FreeRTOS provides completely free yet professionally developed,    *\r
28      *    robust, strictly quality controlled, supported, and cross          *\r
29      *    platform software that is more than just the market leader, it     *\r
30      *    is the industry's de facto standard.                               *\r
31      *                                                                       *\r
32      *    Help yourself get started quickly while simultaneously helping     *\r
33      *    to support the FreeRTOS project by purchasing a FreeRTOS           *\r
34      *    tutorial book, reference manual, or both:                          *\r
35      *    http://www.FreeRTOS.org/Documentation                              *\r
36      *                                                                       *\r
37     ***************************************************************************\r
38 \r
39     http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading\r
40     the FAQ page "My application does not run, what could be wrong?".  Have you\r
41     defined configASSERT()?\r
42 \r
43     http://www.FreeRTOS.org/support - In return for receiving this top quality\r
44     embedded software for free we request you assist our global community by\r
45     participating in the support forum.\r
46 \r
47     http://www.FreeRTOS.org/training - Investing in training allows your team to\r
48     be as productive as possible as early as possible.  Now you can receive\r
49     FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers\r
50     Ltd, and the world's leading authority on the world's leading RTOS.\r
51 \r
52     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
53     including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
54     compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
55 \r
56     http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.\r
57     Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.\r
58 \r
59     http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High\r
60     Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS\r
61     licenses offer ticketed support, indemnification and commercial middleware.\r
62 \r
63     http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
64     engineered and independently SIL3 certified version for use in safety and\r
65     mission critical applications that require provable dependability.\r
66 \r
67     1 tab == 4 spaces!\r
68 */\r
69 \r
70 /* Standard includes. */\r
71 #include <stdlib.h>\r
72 \r
73 /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining\r
74 all the API functions to use the MPU wrappers.  That should only be done when\r
75 task.h is included from an application file. */\r
76 #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE\r
77 \r
78 #include "FreeRTOS.h"\r
79 #include "task.h"\r
80 #include "queue.h"\r
81 #include "timers.h"\r
82 \r
83 #if ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 0 )\r
84         #error configUSE_TIMERS must be set to 1 to make the xTimerPendFunctionCall() function available.\r
85 #endif\r
86 \r
87 /* Lint e961 and e750 are suppressed as a MISRA exception justified because the\r
88 MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the\r
89 header files above, but not in this file, in order to generate the correct\r
90 privileged Vs unprivileged linkage and placement. */\r
91 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */\r
92 \r
93 \r
94 /* This entire source file will be skipped if the application is not configured\r
95 to include software timer functionality.  This #if is closed at the very bottom\r
96 of this file.  If you want to include software timer functionality then ensure\r
97 configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */\r
98 #if ( configUSE_TIMERS == 1 )\r
99 \r
100 /* Misc definitions. */\r
101 #define tmrNO_DELAY             ( TickType_t ) 0U\r
102 \r
103 /* The definition of the timers themselves. */\r
104 typedef struct tmrTimerControl\r
105 {\r
106         const char                              *pcTimerName;           /*<< Text name.  This is not used by the kernel, it is included simply to make debugging easier. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
107         ListItem_t                              xTimerListItem;         /*<< Standard linked list item as used by all kernel features for event management. */\r
108         TickType_t                              xTimerPeriodInTicks;/*<< How quickly and often the timer expires. */\r
109         UBaseType_t                             uxAutoReload;           /*<< Set to pdTRUE if the timer should be automatically restarted once expired.  Set to pdFALSE if the timer is, in effect, a one-shot timer. */\r
110         void                                    *pvTimerID;                     /*<< An ID to identify the timer.  This allows the timer to be identified when the same callback is used for multiple timers. */\r
111         TimerCallbackFunction_t pxCallbackFunction;     /*<< The function that will be called when the timer expires. */\r
112         #if( configUSE_TRACE_FACILITY == 1 )\r
113                 UBaseType_t                     uxTimerNumber;          /*<< An ID assigned by trace tools such as FreeRTOS+Trace */\r
114         #endif\r
115 \r
116         #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )\r
117                 uint8_t                         ucStaticallyAllocated; /*<< Set to pdTRUE if the timer was created statically so no attempt is made to free the memory again if the timer is later deleted. */\r
118         #endif\r
119 } xTIMER;\r
120 \r
121 /* The old xTIMER name is maintained above then typedefed to the new Timer_t\r
122 name below to enable the use of older kernel aware debuggers. */\r
123 typedef xTIMER Timer_t;\r
124 \r
125 /* The definition of messages that can be sent and received on the timer queue.\r
126 Two types of message can be queued - messages that manipulate a software timer,\r
127 and messages that request the execution of a non-timer related callback.  The\r
128 two message types are defined in two separate structures, xTimerParametersType\r
129 and xCallbackParametersType respectively. */\r
130 typedef struct tmrTimerParameters\r
131 {\r
132         TickType_t                      xMessageValue;          /*<< An optional value used by a subset of commands, for example, when changing the period of a timer. */\r
133         Timer_t *                       pxTimer;                        /*<< The timer to which the command will be applied. */\r
134 } TimerParameter_t;\r
135 \r
136 \r
137 typedef struct tmrCallbackParameters\r
138 {\r
139         PendedFunction_t        pxCallbackFunction;     /* << The callback function to execute. */\r
140         void *pvParameter1;                                             /* << The value that will be used as the callback functions first parameter. */\r
141         uint32_t ulParameter2;                                  /* << The value that will be used as the callback functions second parameter. */\r
142 } CallbackParameters_t;\r
143 \r
144 /* The structure that contains the two message types, along with an identifier\r
145 that is used to determine which message type is valid. */\r
146 typedef struct tmrTimerQueueMessage\r
147 {\r
148         BaseType_t                      xMessageID;                     /*<< The command being sent to the timer service task. */\r
149         union\r
150         {\r
151                 TimerParameter_t xTimerParameters;\r
152 \r
153                 /* Don't include xCallbackParameters if it is not going to be used as\r
154                 it makes the structure (and therefore the timer queue) larger. */\r
155                 #if ( INCLUDE_xTimerPendFunctionCall == 1 )\r
156                         CallbackParameters_t xCallbackParameters;\r
157                 #endif /* INCLUDE_xTimerPendFunctionCall */\r
158         } u;\r
159 } DaemonTaskMessage_t;\r
160 \r
161 /*lint -e956 A manual analysis and inspection has been used to determine which\r
162 static variables must be declared volatile. */\r
163 \r
164 /* The list in which active timers are stored.  Timers are referenced in expire\r
165 time order, with the nearest expiry time at the front of the list.  Only the\r
166 timer service task is allowed to access these lists. */\r
167 PRIVILEGED_DATA static List_t xActiveTimerList1;\r
168 PRIVILEGED_DATA static List_t xActiveTimerList2;\r
169 PRIVILEGED_DATA static List_t *pxCurrentTimerList;\r
170 PRIVILEGED_DATA static List_t *pxOverflowTimerList;\r
171 \r
172 /* A queue that is used to send commands to the timer service task. */\r
173 PRIVILEGED_DATA static QueueHandle_t xTimerQueue = NULL;\r
174 PRIVILEGED_DATA static TaskHandle_t xTimerTaskHandle = NULL;\r
175 \r
176 /*lint +e956 */\r
177 \r
178 /*-----------------------------------------------------------*/\r
179 \r
180 #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
181 \r
182         /* If static allocation is supported then the application must provide the\r
183         following callback function - which enables the application to optionally\r
184         provide the memory that will be used by the timer task as the task's stack\r
185         and TCB. */\r
186         extern void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize );\r
187 \r
188 #endif\r
189 \r
190 /*\r
191  * Initialise the infrastructure used by the timer service task if it has not\r
192  * been initialised already.\r
193  */\r
194 static void prvCheckForValidListAndQueue( void ) PRIVILEGED_FUNCTION;\r
195 \r
196 /*\r
197  * The timer service task (daemon).  Timer functionality is controlled by this\r
198  * task.  Other tasks communicate with the timer service task using the\r
199  * xTimerQueue queue.\r
200  */\r
201 static void prvTimerTask( void *pvParameters ) PRIVILEGED_FUNCTION;\r
202 \r
203 /*\r
204  * Called by the timer service task to interpret and process a command it\r
205  * received on the timer queue.\r
206  */\r
207 static void prvProcessReceivedCommands( void ) PRIVILEGED_FUNCTION;\r
208 \r
209 /*\r
210  * Insert the timer into either xActiveTimerList1, or xActiveTimerList2,\r
211  * depending on if the expire time causes a timer counter overflow.\r
212  */\r
213 static BaseType_t prvInsertTimerInActiveList( Timer_t * const pxTimer, const TickType_t xNextExpiryTime, const TickType_t xTimeNow, const TickType_t xCommandTime ) PRIVILEGED_FUNCTION;\r
214 \r
215 /*\r
216  * An active timer has reached its expire time.  Reload the timer if it is an\r
217  * auto reload timer, then call its callback.\r
218  */\r
219 static void prvProcessExpiredTimer( const TickType_t xNextExpireTime, const TickType_t xTimeNow ) PRIVILEGED_FUNCTION;\r
220 \r
221 /*\r
222  * The tick count has overflowed.  Switch the timer lists after ensuring the\r
223  * current timer list does not still reference some timers.\r
224  */\r
225 static void prvSwitchTimerLists( void ) PRIVILEGED_FUNCTION;\r
226 \r
227 /*\r
228  * Obtain the current tick count, setting *pxTimerListsWereSwitched to pdTRUE\r
229  * if a tick count overflow occurred since prvSampleTimeNow() was last called.\r
230  */\r
231 static TickType_t prvSampleTimeNow( BaseType_t * const pxTimerListsWereSwitched ) PRIVILEGED_FUNCTION;\r
232 \r
233 /*\r
234  * If the timer list contains any active timers then return the expire time of\r
235  * the timer that will expire first and set *pxListWasEmpty to false.  If the\r
236  * timer list does not contain any timers then return 0 and set *pxListWasEmpty\r
237  * to pdTRUE.\r
238  */\r
239 static TickType_t prvGetNextExpireTime( BaseType_t * const pxListWasEmpty ) PRIVILEGED_FUNCTION;\r
240 \r
241 /*\r
242  * If a timer has expired, process it.  Otherwise, block the timer service task\r
243  * until either a timer does expire or a command is received.\r
244  */\r
245 static void prvProcessTimerOrBlockTask( const TickType_t xNextExpireTime, BaseType_t xListWasEmpty ) PRIVILEGED_FUNCTION;\r
246 \r
247 /*\r
248  * Called after a Timer_t structure has been allocated either statically or\r
249  * dynamically to fill in the structure's members.\r
250  */\r
251 static void prvInitialiseNewTimer(      const char * const pcTimerName,\r
252                                                                         const TickType_t xTimerPeriodInTicks,\r
253                                                                         const UBaseType_t uxAutoReload,\r
254                                                                         void * const pvTimerID,\r
255                                                                         TimerCallbackFunction_t pxCallbackFunction,\r
256                                                                         Timer_t *pxNewTimer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
257 /*-----------------------------------------------------------*/\r
258 \r
259 BaseType_t xTimerCreateTimerTask( void )\r
260 {\r
261 BaseType_t xReturn = pdFAIL;\r
262 \r
263         /* This function is called when the scheduler is started if\r
264         configUSE_TIMERS is set to 1.  Check that the infrastructure used by the\r
265         timer service task has been created/initialised.  If timers have already\r
266         been created then the initialisation will already have been performed. */\r
267         prvCheckForValidListAndQueue();\r
268 \r
269         if( xTimerQueue != NULL )\r
270         {\r
271 \r
272                 #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
273                 {\r
274                         StaticTask_t *pxTimerTaskTCBBuffer = NULL;\r
275                         StackType_t *pxTimerTaskStackBuffer = NULL;\r
276                         uint32_t ulTimerTaskStackSize;\r
277 \r
278                         vApplicationGetTimerTaskMemory( &pxTimerTaskTCBBuffer, &pxTimerTaskStackBuffer, &ulTimerTaskStackSize );\r
279                         xTimerTaskHandle = xTaskCreateStatic(   prvTimerTask,\r
280                                                                                                         "Tmr Svc",\r
281                                                                                                         ulTimerTaskStackSize,\r
282                                                                                                         NULL,\r
283                                                                                                         ( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT,\r
284                                                                                                         pxTimerTaskStackBuffer,\r
285                                                                                                         pxTimerTaskTCBBuffer );\r
286 \r
287                         if( xTimerTaskHandle != NULL )\r
288                         {\r
289                                 xReturn = pdPASS;\r
290                         }\r
291                 }\r
292                 #else\r
293                 {\r
294                         xReturn = xTaskCreate(  prvTimerTask,\r
295                                                                         "Tmr Svc",\r
296                                                                         configTIMER_TASK_STACK_DEPTH,\r
297                                                                         NULL,\r
298                                                                         ( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT,\r
299                                                                         &xTimerTaskHandle );\r
300                 }\r
301                 #endif /* configSUPPORT_STATIC_ALLOCATION */\r
302         }\r
303         else\r
304         {\r
305                 mtCOVERAGE_TEST_MARKER();\r
306         }\r
307 \r
308         configASSERT( xReturn );\r
309         return xReturn;\r
310 }\r
311 /*-----------------------------------------------------------*/\r
312 \r
313 #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )\r
314 \r
315         TimerHandle_t xTimerCreate(     const char * const pcTimerName,\r
316                                                                 const TickType_t xTimerPeriodInTicks,\r
317                                                                 const UBaseType_t uxAutoReload,\r
318                                                                 void * const pvTimerID,\r
319                                                                 TimerCallbackFunction_t pxCallbackFunction ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
320         {\r
321         Timer_t *pxNewTimer;\r
322 \r
323                 pxNewTimer = ( Timer_t * ) pvPortMalloc( sizeof( Timer_t ) );\r
324 \r
325                 if( pxNewTimer != NULL )\r
326                 {\r
327                         prvInitialiseNewTimer( pcTimerName, xTimerPeriodInTicks, uxAutoReload, pvTimerID, pxCallbackFunction, pxNewTimer );\r
328 \r
329                         #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
330                         {\r
331                                 /* Timers can be created statically or dynamically, so note this\r
332                                 timer was created dynamically in case the timer is later\r
333                                 deleted. */\r
334                                 pxNewTimer->ucStaticallyAllocated = pdFALSE;\r
335                         }\r
336                         #endif /* configSUPPORT_STATIC_ALLOCATION */\r
337                 }\r
338 \r
339                 return pxNewTimer;\r
340         }\r
341 \r
342 #endif /* configSUPPORT_STATIC_ALLOCATION */\r
343 /*-----------------------------------------------------------*/\r
344 \r
345 #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
346 \r
347         TimerHandle_t xTimerCreateStatic(       const char * const pcTimerName,\r
348                                                                                 const TickType_t xTimerPeriodInTicks,\r
349                                                                                 const UBaseType_t uxAutoReload,\r
350                                                                                 void * const pvTimerID,\r
351                                                                                 TimerCallbackFunction_t pxCallbackFunction,\r
352                                                                                 StaticTimer_t *pxTimerBuffer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
353         {\r
354         Timer_t *pxNewTimer;\r
355 \r
356                 #if( configASSERT_DEFINED == 1 )\r
357                 {\r
358                         /* Sanity check that the size of the structure used to declare a\r
359                         variable of type StaticTimer_t equals the size of the real timer\r
360                         structures. */\r
361                         volatile size_t xSize = sizeof( StaticTimer_t );\r
362                         configASSERT( xSize == sizeof( Timer_t ) );\r
363                 }\r
364                 #endif /* configASSERT_DEFINED */\r
365 \r
366                 /* A pointer to a StaticTimer_t structure MUST be provided, use it. */\r
367                 configASSERT( pxTimerBuffer );\r
368                 pxNewTimer = ( Timer_t * ) pxTimerBuffer; /*lint !e740 Unusual cast is ok as the structures are designed to have the same alignment, and the size is checked by an assert. */\r
369 \r
370                 if( pxNewTimer != NULL )\r
371                 {\r
372                         prvInitialiseNewTimer( pcTimerName, xTimerPeriodInTicks, uxAutoReload, pvTimerID, pxCallbackFunction, pxNewTimer );\r
373 \r
374                         #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )\r
375                         {\r
376                                 /* Timers can be created statically or dynamically so note this\r
377                                 timer was created statically in case it is later deleted. */\r
378                                 pxNewTimer->ucStaticallyAllocated = pdTRUE;\r
379                         }\r
380                         #endif /* configSUPPORT_DYNAMIC_ALLOCATION */\r
381                 }\r
382 \r
383                 return pxNewTimer;\r
384         }\r
385 \r
386 #endif /* configSUPPORT_STATIC_ALLOCATION */\r
387 /*-----------------------------------------------------------*/\r
388 \r
389 static void prvInitialiseNewTimer(      const char * const pcTimerName,\r
390                                                                         const TickType_t xTimerPeriodInTicks,\r
391                                                                         const UBaseType_t uxAutoReload,\r
392                                                                         void * const pvTimerID,\r
393                                                                         TimerCallbackFunction_t pxCallbackFunction,\r
394                                                                         Timer_t *pxNewTimer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
395 {\r
396         /* 0 is not a valid value for xTimerPeriodInTicks. */\r
397         configASSERT( ( xTimerPeriodInTicks > 0 ) );\r
398 \r
399         if( pxNewTimer != NULL )\r
400         {\r
401                 /* Ensure the infrastructure used by the timer service task has been\r
402                 created/initialised. */\r
403                 prvCheckForValidListAndQueue();\r
404 \r
405                 /* Initialise the timer structure members using the function\r
406                 parameters. */\r
407                 pxNewTimer->pcTimerName = pcTimerName;\r
408                 pxNewTimer->xTimerPeriodInTicks = xTimerPeriodInTicks;\r
409                 pxNewTimer->uxAutoReload = uxAutoReload;\r
410                 pxNewTimer->pvTimerID = pvTimerID;\r
411                 pxNewTimer->pxCallbackFunction = pxCallbackFunction;\r
412                 vListInitialiseItem( &( pxNewTimer->xTimerListItem ) );\r
413                 traceTIMER_CREATE( pxNewTimer );\r
414         }\r
415 }\r
416 /*-----------------------------------------------------------*/\r
417 \r
418 BaseType_t xTimerGenericCommand( TimerHandle_t xTimer, const BaseType_t xCommandID, const TickType_t xOptionalValue, BaseType_t * const pxHigherPriorityTaskWoken, const TickType_t xTicksToWait )\r
419 {\r
420 BaseType_t xReturn = pdFAIL;\r
421 DaemonTaskMessage_t xMessage;\r
422 \r
423         configASSERT( xTimer );\r
424 \r
425         /* Send a message to the timer service task to perform a particular action\r
426         on a particular timer definition. */\r
427         if( xTimerQueue != NULL )\r
428         {\r
429                 /* Send a command to the timer service task to start the xTimer timer. */\r
430                 xMessage.xMessageID = xCommandID;\r
431                 xMessage.u.xTimerParameters.xMessageValue = xOptionalValue;\r
432                 xMessage.u.xTimerParameters.pxTimer = ( Timer_t * ) xTimer;\r
433 \r
434                 if( xCommandID < tmrFIRST_FROM_ISR_COMMAND )\r
435                 {\r
436                         if( xTaskGetSchedulerState() == taskSCHEDULER_RUNNING )\r
437                         {\r
438                                 xReturn = xQueueSendToBack( xTimerQueue, &xMessage, xTicksToWait );\r
439                         }\r
440                         else\r
441                         {\r
442                                 xReturn = xQueueSendToBack( xTimerQueue, &xMessage, tmrNO_DELAY );\r
443                         }\r
444                 }\r
445                 else\r
446                 {\r
447                         xReturn = xQueueSendToBackFromISR( xTimerQueue, &xMessage, pxHigherPriorityTaskWoken );\r
448                 }\r
449 \r
450                 traceTIMER_COMMAND_SEND( xTimer, xCommandID, xOptionalValue, xReturn );\r
451         }\r
452         else\r
453         {\r
454                 mtCOVERAGE_TEST_MARKER();\r
455         }\r
456 \r
457         return xReturn;\r
458 }\r
459 /*-----------------------------------------------------------*/\r
460 \r
461 TaskHandle_t xTimerGetTimerDaemonTaskHandle( void )\r
462 {\r
463         /* If xTimerGetTimerDaemonTaskHandle() is called before the scheduler has been\r
464         started, then xTimerTaskHandle will be NULL. */\r
465         configASSERT( ( xTimerTaskHandle != NULL ) );\r
466         return xTimerTaskHandle;\r
467 }\r
468 /*-----------------------------------------------------------*/\r
469 \r
470 TickType_t xTimerGetPeriod( TimerHandle_t xTimer )\r
471 {\r
472 Timer_t *pxTimer = ( Timer_t * ) xTimer;\r
473 \r
474         configASSERT( xTimer );\r
475         return pxTimer->xTimerPeriodInTicks;\r
476 }\r
477 /*-----------------------------------------------------------*/\r
478 \r
479 TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer )\r
480 {\r
481 Timer_t * pxTimer = ( Timer_t * ) xTimer;\r
482 TickType_t xReturn;\r
483 \r
484         configASSERT( xTimer );\r
485         xReturn = listGET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ) );\r
486         return xReturn;\r
487 }\r
488 /*-----------------------------------------------------------*/\r
489 \r
490 const char * pcTimerGetName( TimerHandle_t xTimer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
491 {\r
492 Timer_t *pxTimer = ( Timer_t * ) xTimer;\r
493 \r
494         configASSERT( xTimer );\r
495         return pxTimer->pcTimerName;\r
496 }\r
497 /*-----------------------------------------------------------*/\r
498 \r
499 static void prvProcessExpiredTimer( const TickType_t xNextExpireTime, const TickType_t xTimeNow )\r
500 {\r
501 BaseType_t xResult;\r
502 Timer_t * const pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList );\r
503 \r
504         /* Remove the timer from the list of active timers.  A check has already\r
505         been performed to ensure the list is not empty. */\r
506         ( void ) uxListRemove( &( pxTimer->xTimerListItem ) );\r
507         traceTIMER_EXPIRED( pxTimer );\r
508 \r
509         /* If the timer is an auto reload timer then calculate the next\r
510         expiry time and re-insert the timer in the list of active timers. */\r
511         if( pxTimer->uxAutoReload == ( UBaseType_t ) pdTRUE )\r
512         {\r
513                 /* The timer is inserted into a list using a time relative to anything\r
514                 other than the current time.  It will therefore be inserted into the\r
515                 correct list relative to the time this task thinks it is now. */\r
516                 if( prvInsertTimerInActiveList( pxTimer, ( xNextExpireTime + pxTimer->xTimerPeriodInTicks ), xTimeNow, xNextExpireTime ) != pdFALSE )\r
517                 {\r
518                         /* The timer expired before it was added to the active timer\r
519                         list.  Reload it now.  */\r
520                         xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xNextExpireTime, NULL, tmrNO_DELAY );\r
521                         configASSERT( xResult );\r
522                         ( void ) xResult;\r
523                 }\r
524                 else\r
525                 {\r
526                         mtCOVERAGE_TEST_MARKER();\r
527                 }\r
528         }\r
529         else\r
530         {\r
531                 mtCOVERAGE_TEST_MARKER();\r
532         }\r
533 \r
534         /* Call the timer callback. */\r
535         pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer );\r
536 }\r
537 /*-----------------------------------------------------------*/\r
538 \r
539 static void prvTimerTask( void *pvParameters )\r
540 {\r
541 TickType_t xNextExpireTime;\r
542 BaseType_t xListWasEmpty;\r
543 \r
544         /* Just to avoid compiler warnings. */\r
545         ( void ) pvParameters;\r
546 \r
547         #if( configUSE_DAEMON_TASK_STARTUP_HOOK == 1 )\r
548         {\r
549                 extern void vApplicationDaemonTaskStartupHook( void );\r
550 \r
551                 /* Allow the application writer to execute some code in the context of\r
552                 this task at the point the task starts executing.  This is useful if the\r
553                 application includes initialisation code that would benefit from\r
554                 executing after the scheduler has been started. */\r
555                 vApplicationDaemonTaskStartupHook();\r
556         }\r
557         #endif /* configUSE_DAEMON_TASK_STARTUP_HOOK */\r
558 \r
559         for( ;; )\r
560         {\r
561                 /* Query the timers list to see if it contains any timers, and if so,\r
562                 obtain the time at which the next timer will expire. */\r
563                 xNextExpireTime = prvGetNextExpireTime( &xListWasEmpty );\r
564 \r
565                 /* If a timer has expired, process it.  Otherwise, block this task\r
566                 until either a timer does expire, or a command is received. */\r
567                 prvProcessTimerOrBlockTask( xNextExpireTime, xListWasEmpty );\r
568 \r
569                 /* Empty the command queue. */\r
570                 prvProcessReceivedCommands();\r
571         }\r
572 }\r
573 /*-----------------------------------------------------------*/\r
574 \r
575 static void prvProcessTimerOrBlockTask( const TickType_t xNextExpireTime, BaseType_t xListWasEmpty )\r
576 {\r
577 TickType_t xTimeNow;\r
578 BaseType_t xTimerListsWereSwitched;\r
579 \r
580         vTaskSuspendAll();\r
581         {\r
582                 /* Obtain the time now to make an assessment as to whether the timer\r
583                 has expired or not.  If obtaining the time causes the lists to switch\r
584                 then don't process this timer as any timers that remained in the list\r
585                 when the lists were switched will have been processed within the\r
586                 prvSampleTimeNow() function. */\r
587                 xTimeNow = prvSampleTimeNow( &xTimerListsWereSwitched );\r
588                 if( xTimerListsWereSwitched == pdFALSE )\r
589                 {\r
590                         /* The tick count has not overflowed, has the timer expired? */\r
591                         if( ( xListWasEmpty == pdFALSE ) && ( xNextExpireTime <= xTimeNow ) )\r
592                         {\r
593                                 ( void ) xTaskResumeAll();\r
594                                 prvProcessExpiredTimer( xNextExpireTime, xTimeNow );\r
595                         }\r
596                         else\r
597                         {\r
598                                 /* The tick count has not overflowed, and the next expire\r
599                                 time has not been reached yet.  This task should therefore\r
600                                 block to wait for the next expire time or a command to be\r
601                                 received - whichever comes first.  The following line cannot\r
602                                 be reached unless xNextExpireTime > xTimeNow, except in the\r
603                                 case when the current timer list is empty. */\r
604                                 if( xListWasEmpty != pdFALSE )\r
605                                 {\r
606                                         /* The current timer list is empty - is the overflow list\r
607                                         also empty? */\r
608                                         xListWasEmpty = listLIST_IS_EMPTY( pxOverflowTimerList );\r
609                                 }\r
610 \r
611                                 vQueueWaitForMessageRestricted( xTimerQueue, ( xNextExpireTime - xTimeNow ), xListWasEmpty );\r
612 \r
613                                 if( xTaskResumeAll() == pdFALSE )\r
614                                 {\r
615                                         /* Yield to wait for either a command to arrive, or the\r
616                                         block time to expire.  If a command arrived between the\r
617                                         critical section being exited and this yield then the yield\r
618                                         will not cause the task to block. */\r
619                                         portYIELD_WITHIN_API();\r
620                                 }\r
621                                 else\r
622                                 {\r
623                                         mtCOVERAGE_TEST_MARKER();\r
624                                 }\r
625                         }\r
626                 }\r
627                 else\r
628                 {\r
629                         ( void ) xTaskResumeAll();\r
630                 }\r
631         }\r
632 }\r
633 /*-----------------------------------------------------------*/\r
634 \r
635 static TickType_t prvGetNextExpireTime( BaseType_t * const pxListWasEmpty )\r
636 {\r
637 TickType_t xNextExpireTime;\r
638 \r
639         /* Timers are listed in expiry time order, with the head of the list\r
640         referencing the task that will expire first.  Obtain the time at which\r
641         the timer with the nearest expiry time will expire.  If there are no\r
642         active timers then just set the next expire time to 0.  That will cause\r
643         this task to unblock when the tick count overflows, at which point the\r
644         timer lists will be switched and the next expiry time can be\r
645         re-assessed.  */\r
646         *pxListWasEmpty = listLIST_IS_EMPTY( pxCurrentTimerList );\r
647         if( *pxListWasEmpty == pdFALSE )\r
648         {\r
649                 xNextExpireTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxCurrentTimerList );\r
650         }\r
651         else\r
652         {\r
653                 /* Ensure the task unblocks when the tick count rolls over. */\r
654                 xNextExpireTime = ( TickType_t ) 0U;\r
655         }\r
656 \r
657         return xNextExpireTime;\r
658 }\r
659 /*-----------------------------------------------------------*/\r
660 \r
661 static TickType_t prvSampleTimeNow( BaseType_t * const pxTimerListsWereSwitched )\r
662 {\r
663 TickType_t xTimeNow;\r
664 PRIVILEGED_DATA static TickType_t xLastTime = ( TickType_t ) 0U; /*lint !e956 Variable is only accessible to one task. */\r
665 \r
666         xTimeNow = xTaskGetTickCount();\r
667 \r
668         if( xTimeNow < xLastTime )\r
669         {\r
670                 prvSwitchTimerLists();\r
671                 *pxTimerListsWereSwitched = pdTRUE;\r
672         }\r
673         else\r
674         {\r
675                 *pxTimerListsWereSwitched = pdFALSE;\r
676         }\r
677 \r
678         xLastTime = xTimeNow;\r
679 \r
680         return xTimeNow;\r
681 }\r
682 /*-----------------------------------------------------------*/\r
683 \r
684 static BaseType_t prvInsertTimerInActiveList( Timer_t * const pxTimer, const TickType_t xNextExpiryTime, const TickType_t xTimeNow, const TickType_t xCommandTime )\r
685 {\r
686 BaseType_t xProcessTimerNow = pdFALSE;\r
687 \r
688         listSET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ), xNextExpiryTime );\r
689         listSET_LIST_ITEM_OWNER( &( pxTimer->xTimerListItem ), pxTimer );\r
690 \r
691         if( xNextExpiryTime <= xTimeNow )\r
692         {\r
693                 /* Has the expiry time elapsed between the command to start/reset a\r
694                 timer was issued, and the time the command was processed? */\r
695                 if( ( ( TickType_t ) ( xTimeNow - xCommandTime ) ) >= pxTimer->xTimerPeriodInTicks ) /*lint !e961 MISRA exception as the casts are only redundant for some ports. */\r
696                 {\r
697                         /* The time between a command being issued and the command being\r
698                         processed actually exceeds the timers period.  */\r
699                         xProcessTimerNow = pdTRUE;\r
700                 }\r
701                 else\r
702                 {\r
703                         vListInsert( pxOverflowTimerList, &( pxTimer->xTimerListItem ) );\r
704                 }\r
705         }\r
706         else\r
707         {\r
708                 if( ( xTimeNow < xCommandTime ) && ( xNextExpiryTime >= xCommandTime ) )\r
709                 {\r
710                         /* If, since the command was issued, the tick count has overflowed\r
711                         but the expiry time has not, then the timer must have already passed\r
712                         its expiry time and should be processed immediately. */\r
713                         xProcessTimerNow = pdTRUE;\r
714                 }\r
715                 else\r
716                 {\r
717                         vListInsert( pxCurrentTimerList, &( pxTimer->xTimerListItem ) );\r
718                 }\r
719         }\r
720 \r
721         return xProcessTimerNow;\r
722 }\r
723 /*-----------------------------------------------------------*/\r
724 \r
725 static void     prvProcessReceivedCommands( void )\r
726 {\r
727 DaemonTaskMessage_t xMessage;\r
728 Timer_t *pxTimer;\r
729 BaseType_t xTimerListsWereSwitched, xResult;\r
730 TickType_t xTimeNow;\r
731 \r
732         while( xQueueReceive( xTimerQueue, &xMessage, tmrNO_DELAY ) != pdFAIL ) /*lint !e603 xMessage does not have to be initialised as it is passed out, not in, and it is not used unless xQueueReceive() returns pdTRUE. */\r
733         {\r
734                 #if ( INCLUDE_xTimerPendFunctionCall == 1 )\r
735                 {\r
736                         /* Negative commands are pended function calls rather than timer\r
737                         commands. */\r
738                         if( xMessage.xMessageID < ( BaseType_t ) 0 )\r
739                         {\r
740                                 const CallbackParameters_t * const pxCallback = &( xMessage.u.xCallbackParameters );\r
741 \r
742                                 /* The timer uses the xCallbackParameters member to request a\r
743                                 callback be executed.  Check the callback is not NULL. */\r
744                                 configASSERT( pxCallback );\r
745 \r
746                                 /* Call the function. */\r
747                                 pxCallback->pxCallbackFunction( pxCallback->pvParameter1, pxCallback->ulParameter2 );\r
748                         }\r
749                         else\r
750                         {\r
751                                 mtCOVERAGE_TEST_MARKER();\r
752                         }\r
753                 }\r
754                 #endif /* INCLUDE_xTimerPendFunctionCall */\r
755 \r
756                 /* Commands that are positive are timer commands rather than pended\r
757                 function calls. */\r
758                 if( xMessage.xMessageID >= ( BaseType_t ) 0 )\r
759                 {\r
760                         /* The messages uses the xTimerParameters member to work on a\r
761                         software timer. */\r
762                         pxTimer = xMessage.u.xTimerParameters.pxTimer;\r
763 \r
764                         if( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) == pdFALSE )\r
765                         {\r
766                                 /* The timer is in a list, remove it. */\r
767                                 ( void ) uxListRemove( &( pxTimer->xTimerListItem ) );\r
768                         }\r
769                         else\r
770                         {\r
771                                 mtCOVERAGE_TEST_MARKER();\r
772                         }\r
773 \r
774                         traceTIMER_COMMAND_RECEIVED( pxTimer, xMessage.xMessageID, xMessage.u.xTimerParameters.xMessageValue );\r
775 \r
776                         /* In this case the xTimerListsWereSwitched parameter is not used, but\r
777                         it must be present in the function call.  prvSampleTimeNow() must be\r
778                         called after the message is received from xTimerQueue so there is no\r
779                         possibility of a higher priority task adding a message to the message\r
780                         queue with a time that is ahead of the timer daemon task (because it\r
781                         pre-empted the timer daemon task after the xTimeNow value was set). */\r
782                         xTimeNow = prvSampleTimeNow( &xTimerListsWereSwitched );\r
783 \r
784                         switch( xMessage.xMessageID )\r
785                         {\r
786                                 case tmrCOMMAND_START :\r
787                             case tmrCOMMAND_START_FROM_ISR :\r
788                             case tmrCOMMAND_RESET :\r
789                             case tmrCOMMAND_RESET_FROM_ISR :\r
790                                 case tmrCOMMAND_START_DONT_TRACE :\r
791                                         /* Start or restart a timer. */\r
792                                         if( prvInsertTimerInActiveList( pxTimer,  xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, xTimeNow, xMessage.u.xTimerParameters.xMessageValue ) != pdFALSE )\r
793                                         {\r
794                                                 /* The timer expired before it was added to the active\r
795                                                 timer list.  Process it now. */\r
796                                                 pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer );\r
797                                                 traceTIMER_EXPIRED( pxTimer );\r
798 \r
799                                                 if( pxTimer->uxAutoReload == ( UBaseType_t ) pdTRUE )\r
800                                                 {\r
801                                                         xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, NULL, tmrNO_DELAY );\r
802                                                         configASSERT( xResult );\r
803                                                         ( void ) xResult;\r
804                                                 }\r
805                                                 else\r
806                                                 {\r
807                                                         mtCOVERAGE_TEST_MARKER();\r
808                                                 }\r
809                                         }\r
810                                         else\r
811                                         {\r
812                                                 mtCOVERAGE_TEST_MARKER();\r
813                                         }\r
814                                         break;\r
815 \r
816                                 case tmrCOMMAND_STOP :\r
817                                 case tmrCOMMAND_STOP_FROM_ISR :\r
818                                         /* The timer has already been removed from the active list.\r
819                                         There is nothing to do here. */\r
820                                         break;\r
821 \r
822                                 case tmrCOMMAND_CHANGE_PERIOD :\r
823                                 case tmrCOMMAND_CHANGE_PERIOD_FROM_ISR :\r
824                                         pxTimer->xTimerPeriodInTicks = xMessage.u.xTimerParameters.xMessageValue;\r
825                                         configASSERT( ( pxTimer->xTimerPeriodInTicks > 0 ) );\r
826 \r
827                                         /* The new period does not really have a reference, and can\r
828                                         be longer or shorter than the old one.  The command time is\r
829                                         therefore set to the current time, and as the period cannot\r
830                                         be zero the next expiry time can only be in the future,\r
831                                         meaning (unlike for the xTimerStart() case above) there is\r
832                                         no fail case that needs to be handled here. */\r
833                                         ( void ) prvInsertTimerInActiveList( pxTimer, ( xTimeNow + pxTimer->xTimerPeriodInTicks ), xTimeNow, xTimeNow );\r
834                                         break;\r
835 \r
836                                 case tmrCOMMAND_DELETE :\r
837                                         /* The timer has already been removed from the active list,\r
838                                         just free up the memory if the memory was dynamically\r
839                                         allocated. */\r
840                                         #if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) )\r
841                                         {\r
842                                                 /* The timer can only have been allocated dynamically -\r
843                                                 free it again. */\r
844                                                 vPortFree( pxTimer );\r
845                                         }\r
846                                         #elif( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )\r
847                                         {\r
848                                                 /* The timer could have been allocated statically or\r
849                                                 dynamically, so check before attempting to free the\r
850                                                 memory. */\r
851                                                 if( pxTimer->ucStaticallyAllocated == ( uint8_t ) pdFALSE )\r
852                                                 {\r
853                                                         vPortFree( pxTimer );\r
854                                                 }\r
855                                                 else\r
856                                                 {\r
857                                                         mtCOVERAGE_TEST_MARKER();\r
858                                                 }\r
859                                         }\r
860                                         #endif /* configSUPPORT_DYNAMIC_ALLOCATION */\r
861                                         break;\r
862 \r
863                                 default :\r
864                                         /* Don't expect to get here. */\r
865                                         break;\r
866                         }\r
867                 }\r
868         }\r
869 }\r
870 /*-----------------------------------------------------------*/\r
871 \r
872 static void prvSwitchTimerLists( void )\r
873 {\r
874 TickType_t xNextExpireTime, xReloadTime;\r
875 List_t *pxTemp;\r
876 Timer_t *pxTimer;\r
877 BaseType_t xResult;\r
878 \r
879         /* The tick count has overflowed.  The timer lists must be switched.\r
880         If there are any timers still referenced from the current timer list\r
881         then they must have expired and should be processed before the lists\r
882         are switched. */\r
883         while( listLIST_IS_EMPTY( pxCurrentTimerList ) == pdFALSE )\r
884         {\r
885                 xNextExpireTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxCurrentTimerList );\r
886 \r
887                 /* Remove the timer from the list. */\r
888                 pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList );\r
889                 ( void ) uxListRemove( &( pxTimer->xTimerListItem ) );\r
890                 traceTIMER_EXPIRED( pxTimer );\r
891 \r
892                 /* Execute its callback, then send a command to restart the timer if\r
893                 it is an auto-reload timer.  It cannot be restarted here as the lists\r
894                 have not yet been switched. */\r
895                 pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer );\r
896 \r
897                 if( pxTimer->uxAutoReload == ( UBaseType_t ) pdTRUE )\r
898                 {\r
899                         /* Calculate the reload value, and if the reload value results in\r
900                         the timer going into the same timer list then it has already expired\r
901                         and the timer should be re-inserted into the current list so it is\r
902                         processed again within this loop.  Otherwise a command should be sent\r
903                         to restart the timer to ensure it is only inserted into a list after\r
904                         the lists have been swapped. */\r
905                         xReloadTime = ( xNextExpireTime + pxTimer->xTimerPeriodInTicks );\r
906                         if( xReloadTime > xNextExpireTime )\r
907                         {\r
908                                 listSET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ), xReloadTime );\r
909                                 listSET_LIST_ITEM_OWNER( &( pxTimer->xTimerListItem ), pxTimer );\r
910                                 vListInsert( pxCurrentTimerList, &( pxTimer->xTimerListItem ) );\r
911                         }\r
912                         else\r
913                         {\r
914                                 xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xNextExpireTime, NULL, tmrNO_DELAY );\r
915                                 configASSERT( xResult );\r
916                                 ( void ) xResult;\r
917                         }\r
918                 }\r
919                 else\r
920                 {\r
921                         mtCOVERAGE_TEST_MARKER();\r
922                 }\r
923         }\r
924 \r
925         pxTemp = pxCurrentTimerList;\r
926         pxCurrentTimerList = pxOverflowTimerList;\r
927         pxOverflowTimerList = pxTemp;\r
928 }\r
929 /*-----------------------------------------------------------*/\r
930 \r
931 static void prvCheckForValidListAndQueue( void )\r
932 {\r
933         /* Check that the list from which active timers are referenced, and the\r
934         queue used to communicate with the timer service, have been\r
935         initialised. */\r
936         taskENTER_CRITICAL();\r
937         {\r
938                 if( xTimerQueue == NULL )\r
939                 {\r
940                         vListInitialise( &xActiveTimerList1 );\r
941                         vListInitialise( &xActiveTimerList2 );\r
942                         pxCurrentTimerList = &xActiveTimerList1;\r
943                         pxOverflowTimerList = &xActiveTimerList2;\r
944 \r
945                         #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
946                         {\r
947                                 /* The timer queue is allocated statically in case\r
948                                 configSUPPORT_DYNAMIC_ALLOCATION is 0. */\r
949                                 static StaticQueue_t xStaticTimerQueue;\r
950                                 static uint8_t ucStaticTimerQueueStorage[ configTIMER_QUEUE_LENGTH * sizeof( DaemonTaskMessage_t ) ];\r
951 \r
952                                 xTimerQueue = xQueueCreateStatic( ( UBaseType_t ) configTIMER_QUEUE_LENGTH, sizeof( DaemonTaskMessage_t ), &( ucStaticTimerQueueStorage[ 0 ] ), &xStaticTimerQueue );\r
953                         }\r
954                         #else\r
955                         {\r
956                                 xTimerQueue = xQueueCreate( ( UBaseType_t ) configTIMER_QUEUE_LENGTH, sizeof( DaemonTaskMessage_t ) );\r
957                         }\r
958                         #endif\r
959 \r
960                         #if ( configQUEUE_REGISTRY_SIZE > 0 )\r
961                         {\r
962                                 if( xTimerQueue != NULL )\r
963                                 {\r
964                                         vQueueAddToRegistry( xTimerQueue, "TmrQ" );\r
965                                 }\r
966                                 else\r
967                                 {\r
968                                         mtCOVERAGE_TEST_MARKER();\r
969                                 }\r
970                         }\r
971                         #endif /* configQUEUE_REGISTRY_SIZE */\r
972                 }\r
973                 else\r
974                 {\r
975                         mtCOVERAGE_TEST_MARKER();\r
976                 }\r
977         }\r
978         taskEXIT_CRITICAL();\r
979 }\r
980 /*-----------------------------------------------------------*/\r
981 \r
982 BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer )\r
983 {\r
984 BaseType_t xTimerIsInActiveList;\r
985 Timer_t *pxTimer = ( Timer_t * ) xTimer;\r
986 \r
987         configASSERT( xTimer );\r
988 \r
989         /* Is the timer in the list of active timers? */\r
990         taskENTER_CRITICAL();\r
991         {\r
992                 /* Checking to see if it is in the NULL list in effect checks to see if\r
993                 it is referenced from either the current or the overflow timer lists in\r
994                 one go, but the logic has to be reversed, hence the '!'. */\r
995                 xTimerIsInActiveList = ( BaseType_t ) !( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) );\r
996         }\r
997         taskEXIT_CRITICAL();\r
998 \r
999         return xTimerIsInActiveList;\r
1000 } /*lint !e818 Can't be pointer to const due to the typedef. */\r
1001 /*-----------------------------------------------------------*/\r
1002 \r
1003 void *pvTimerGetTimerID( const TimerHandle_t xTimer )\r
1004 {\r
1005 Timer_t * const pxTimer = ( Timer_t * ) xTimer;\r
1006 void *pvReturn;\r
1007 \r
1008         configASSERT( xTimer );\r
1009 \r
1010         taskENTER_CRITICAL();\r
1011         {\r
1012                 pvReturn = pxTimer->pvTimerID;\r
1013         }\r
1014         taskEXIT_CRITICAL();\r
1015 \r
1016         return pvReturn;\r
1017 }\r
1018 /*-----------------------------------------------------------*/\r
1019 \r
1020 void vTimerSetTimerID( TimerHandle_t xTimer, void *pvNewID )\r
1021 {\r
1022 Timer_t * const pxTimer = ( Timer_t * ) xTimer;\r
1023 \r
1024         configASSERT( xTimer );\r
1025 \r
1026         taskENTER_CRITICAL();\r
1027         {\r
1028                 pxTimer->pvTimerID = pvNewID;\r
1029         }\r
1030         taskEXIT_CRITICAL();\r
1031 }\r
1032 /*-----------------------------------------------------------*/\r
1033 \r
1034 #if( INCLUDE_xTimerPendFunctionCall == 1 )\r
1035 \r
1036         BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, BaseType_t *pxHigherPriorityTaskWoken )\r
1037         {\r
1038         DaemonTaskMessage_t xMessage;\r
1039         BaseType_t xReturn;\r
1040 \r
1041                 /* Complete the message with the function parameters and post it to the\r
1042                 daemon task. */\r
1043                 xMessage.xMessageID = tmrCOMMAND_EXECUTE_CALLBACK_FROM_ISR;\r
1044                 xMessage.u.xCallbackParameters.pxCallbackFunction = xFunctionToPend;\r
1045                 xMessage.u.xCallbackParameters.pvParameter1 = pvParameter1;\r
1046                 xMessage.u.xCallbackParameters.ulParameter2 = ulParameter2;\r
1047 \r
1048                 xReturn = xQueueSendFromISR( xTimerQueue, &xMessage, pxHigherPriorityTaskWoken );\r
1049 \r
1050                 tracePEND_FUNC_CALL_FROM_ISR( xFunctionToPend, pvParameter1, ulParameter2, xReturn );\r
1051 \r
1052                 return xReturn;\r
1053         }\r
1054 \r
1055 #endif /* INCLUDE_xTimerPendFunctionCall */\r
1056 /*-----------------------------------------------------------*/\r
1057 \r
1058 #if( INCLUDE_xTimerPendFunctionCall == 1 )\r
1059 \r
1060         BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, TickType_t xTicksToWait )\r
1061         {\r
1062         DaemonTaskMessage_t xMessage;\r
1063         BaseType_t xReturn;\r
1064 \r
1065                 /* This function can only be called after a timer has been created or\r
1066                 after the scheduler has been started because, until then, the timer\r
1067                 queue does not exist. */\r
1068                 configASSERT( xTimerQueue );\r
1069 \r
1070                 /* Complete the message with the function parameters and post it to the\r
1071                 daemon task. */\r
1072                 xMessage.xMessageID = tmrCOMMAND_EXECUTE_CALLBACK;\r
1073                 xMessage.u.xCallbackParameters.pxCallbackFunction = xFunctionToPend;\r
1074                 xMessage.u.xCallbackParameters.pvParameter1 = pvParameter1;\r
1075                 xMessage.u.xCallbackParameters.ulParameter2 = ulParameter2;\r
1076 \r
1077                 xReturn = xQueueSendToBack( xTimerQueue, &xMessage, xTicksToWait );\r
1078 \r
1079                 tracePEND_FUNC_CALL( xFunctionToPend, pvParameter1, ulParameter2, xReturn );\r
1080 \r
1081                 return xReturn;\r
1082         }\r
1083 \r
1084 #endif /* INCLUDE_xTimerPendFunctionCall */\r
1085 /*-----------------------------------------------------------*/\r
1086 \r
1087 /* This entire source file will be skipped if the application is not configured\r
1088 to include software timer functionality.  If you want to include software timer\r
1089 functionality then ensure configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */\r
1090 #endif /* configUSE_TIMERS == 1 */\r
1091 \r
1092 \r
1093 \r