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