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