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