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