SAM4S-EK_FreeRTOS+FAT-SL  1.0
An example project to test the functionality of FreeRTOS+FAT-SL using SD card as data storage medium
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Modules
timers.c
Go to the documentation of this file.
1 /*
2  FreeRTOS V8.0.1 - Copyright (C) 2014 Real Time Engineers Ltd.
3  All rights reserved
4 
5  VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
6 
7  ***************************************************************************
8  * *
9  * FreeRTOS provides completely free yet professionally developed, *
10  * robust, strictly quality controlled, supported, and cross *
11  * platform software that has become a de facto standard. *
12  * *
13  * Help yourself get started quickly and support the FreeRTOS *
14  * project by purchasing a FreeRTOS tutorial book, reference *
15  * manual, or both from: http://www.FreeRTOS.org/Documentation *
16  * *
17  * Thank you! *
18  * *
19  ***************************************************************************
20 
21  This file is part of the FreeRTOS distribution.
22 
23  FreeRTOS is free software; you can redistribute it and/or modify it under
24  the terms of the GNU General Public License (version 2) as published by the
25  Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
26 
27  >>! NOTE: The modification to the GPL is included to allow you to !<<
28  >>! distribute a combined work that includes FreeRTOS without being !<<
29  >>! obliged to provide the source code for proprietary components !<<
30  >>! outside of the FreeRTOS kernel. !<<
31 
32  FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
33  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
34  FOR A PARTICULAR PURPOSE. Full license text is available from the following
35  link: http://www.freertos.org/a00114.html
36 
37  1 tab == 4 spaces!
38 
39  ***************************************************************************
40  * *
41  * Having a problem? Start by reading the FAQ "My application does *
42  * not run, what could be wrong?" *
43  * *
44  * http://www.FreeRTOS.org/FAQHelp.html *
45  * *
46  ***************************************************************************
47 
48  http://www.FreeRTOS.org - Documentation, books, training, latest versions,
49  license and Real Time Engineers Ltd. contact details.
50 
51  http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
52  including FreeRTOS+Trace - an indispensable productivity tool, a DOS
53  compatible FAT file system, and our tiny thread aware UDP/IP stack.
54 
55  http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
56  Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
57  licenses offer ticketed support, indemnification and middleware.
58 
59  http://www.SafeRTOS.com - High Integrity Systems also provide a safety
60  engineered and independently SIL3 certified version for use in safety and
61  mission critical applications that require provable dependability.
62 
63  1 tab == 4 spaces!
64 */
65 
66 /* Standard includes. */
67 #include <stdlib.h>
68 
69 /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
70 all the API functions to use the MPU wrappers. That should only be done when
71 task.h is included from an application file. */
72 #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
73 
74 #include "FreeRTOS.h"
75 #include "task.h"
76 #include "queue.h"
77 #include "timers.h"
78 
79 #if ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 0 )
80  #error configUSE_TIMERS must be set to 1 to make the xTimerPendFunctionCall() function available.
81 #endif
82 
83 /* Lint e961 and e750 are suppressed as a MISRA exception justified because the
84 MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the
85 header files above, but not in this file, in order to generate the correct
86 privileged Vs unprivileged linkage and placement. */
87 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */
88 
89 
90 /* This entire source file will be skipped if the application is not configured
91 to include software timer functionality. This #if is closed at the very bottom
92 of this file. If you want to include software timer functionality then ensure
93 configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */
94 #if ( configUSE_TIMERS == 1 )
95 
96 /* Misc definitions. */
97 #define tmrNO_DELAY ( TickType_t ) 0U
98 
99 /* The definition of the timers themselves. */
100 typedef struct tmrTimerControl
101 {
102  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. */
103  ListItem_t xTimerListItem; /*<< Standard linked list item as used by all kernel features for event management. */
104  TickType_t xTimerPeriodInTicks;/*<< How quickly and often the timer expires. */
105  UBaseType_t uxAutoReload; /*<< Set to pdTRUE if the timer should be automatically restarted once expired. Set to pdFALSE if the timer is, in effect, a one-shot timer. */
106  void *pvTimerID; /*<< An ID to identify the timer. This allows the timer to be identified when the same callback is used for multiple timers. */
107  TimerCallbackFunction_t pxCallbackFunction; /*<< The function that will be called when the timer expires. */
108  #if( configUSE_TRACE_FACILITY == 1 )
109  UBaseType_t uxTimerNumber; /*<< An ID assigned by trace tools such as FreeRTOS+Trace */
110  #endif
111 } xTIMER;
112 
113 /* The old xTIMER name is maintained above then typedefed to the new Timer_t
114 name below to enable the use of older kernel aware debuggers. */
115 typedef xTIMER Timer_t;
116 
117 /* The definition of messages that can be sent and received on the timer queue.
118 Two types of message can be queued - messages that manipulate a software timer,
119 and messages that request the execution of a non-timer related callback. The
120 two message types are defined in two separate structures, xTimerParametersType
121 and xCallbackParametersType respectively. */
122 typedef struct tmrTimerParameters
123 {
124  TickType_t xMessageValue; /*<< An optional value used by a subset of commands, for example, when changing the period of a timer. */
125  Timer_t * pxTimer; /*<< The timer to which the command will be applied. */
126 } TimerParameter_t;
127 
128 
129 typedef struct tmrCallbackParameters
130 {
131  PendedFunction_t pxCallbackFunction; /* << The callback function to execute. */
132  void *pvParameter1; /* << The value that will be used as the callback functions first parameter. */
133  uint32_t ulParameter2; /* << The value that will be used as the callback functions second parameter. */
134 } CallbackParameters_t;
135 
136 /* The structure that contains the two message types, along with an identifier
137 that is used to determine which message type is valid. */
138 typedef struct tmrTimerQueueMessage
139 {
140  BaseType_t xMessageID; /*<< The command being sent to the timer service task. */
141  union
142  {
143  TimerParameter_t xTimerParameters;
144 
145  /* Don't include xCallbackParameters if it is not going to be used as
146  it makes the structure (and therefore the timer queue) larger. */
147  #if ( INCLUDE_xTimerPendFunctionCall == 1 )
148  CallbackParameters_t xCallbackParameters;
149  #endif /* INCLUDE_xTimerPendFunctionCall */
150  } u;
151 } DaemonTaskMessage_t;
152 
153 /*lint -e956 A manual analysis and inspection has been used to determine which
154 static variables must be declared volatile. */
155 
156 /* The list in which active timers are stored. Timers are referenced in expire
157 time order, with the nearest expiry time at the front of the list. Only the
158 timer service task is allowed to access these lists. */
159 PRIVILEGED_DATA static List_t xActiveTimerList1;
160 PRIVILEGED_DATA static List_t xActiveTimerList2;
161 PRIVILEGED_DATA static List_t *pxCurrentTimerList;
162 PRIVILEGED_DATA static List_t *pxOverflowTimerList;
163 
164 /* A queue that is used to send commands to the timer service task. */
165 PRIVILEGED_DATA static QueueHandle_t xTimerQueue = NULL;
166 
167 #if ( INCLUDE_xTimerGetTimerDaemonTaskHandle == 1 )
168 
169  PRIVILEGED_DATA static TaskHandle_t xTimerTaskHandle = NULL;
170 
171 #endif
172 
173 /*lint +e956 */
174 
175 /*-----------------------------------------------------------*/
176 
177 /*
178  * Initialise the infrastructure used by the timer service task if it has not
179  * been initialised already.
180  */
181 static void prvCheckForValidListAndQueue( void ) PRIVILEGED_FUNCTION;
182 
183 /*
184  * The timer service task (daemon). Timer functionality is controlled by this
185  * task. Other tasks communicate with the timer service task using the
186  * xTimerQueue queue.
187  */
188 static void prvTimerTask( void *pvParameters ) PRIVILEGED_FUNCTION;
189 
190 /*
191  * Called by the timer service task to interpret and process a command it
192  * received on the timer queue.
193  */
194 static void prvProcessReceivedCommands( void ) PRIVILEGED_FUNCTION;
195 
196 /*
197  * Insert the timer into either xActiveTimerList1, or xActiveTimerList2,
198  * depending on if the expire time causes a timer counter overflow.
199  */
200 static BaseType_t prvInsertTimerInActiveList( Timer_t * const pxTimer, const TickType_t xNextExpiryTime, const TickType_t xTimeNow, const TickType_t xCommandTime ) PRIVILEGED_FUNCTION;
201 
202 /*
203  * An active timer has reached its expire time. Reload the timer if it is an
204  * auto reload timer, then call its callback.
205  */
206 static void prvProcessExpiredTimer( const TickType_t xNextExpireTime, const TickType_t xTimeNow ) PRIVILEGED_FUNCTION;
207 
208 /*
209  * The tick count has overflowed. Switch the timer lists after ensuring the
210  * current timer list does not still reference some timers.
211  */
212 static void prvSwitchTimerLists( void ) PRIVILEGED_FUNCTION;
213 
214 /*
215  * Obtain the current tick count, setting *pxTimerListsWereSwitched to pdTRUE
216  * if a tick count overflow occurred since prvSampleTimeNow() was last called.
217  */
218 static TickType_t prvSampleTimeNow( BaseType_t * const pxTimerListsWereSwitched ) PRIVILEGED_FUNCTION;
219 
220 /*
221  * If the timer list contains any active timers then return the expire time of
222  * the timer that will expire first and set *pxListWasEmpty to false. If the
223  * timer list does not contain any timers then return 0 and set *pxListWasEmpty
224  * to pdTRUE.
225  */
226 static TickType_t prvGetNextExpireTime( BaseType_t * const pxListWasEmpty ) PRIVILEGED_FUNCTION;
227 
228 /*
229  * If a timer has expired, process it. Otherwise, block the timer service task
230  * until either a timer does expire or a command is received.
231  */
232 static void prvProcessTimerOrBlockTask( const TickType_t xNextExpireTime, const BaseType_t xListWasEmpty ) PRIVILEGED_FUNCTION;
233 
234 /*-----------------------------------------------------------*/
235 
237 {
238 BaseType_t xReturn = pdFAIL;
239 
240  /* This function is called when the scheduler is started if
241  configUSE_TIMERS is set to 1. Check that the infrastructure used by the
242  timer service task has been created/initialised. If timers have already
243  been created then the initialisation will already have been performed. */
244  prvCheckForValidListAndQueue();
245 
246  if( xTimerQueue != NULL )
247  {
248  #if ( INCLUDE_xTimerGetTimerDaemonTaskHandle == 1 )
249  {
250  /* Create the timer task, storing its handle in xTimerTaskHandle so
251  it can be returned by the xTimerGetTimerDaemonTaskHandle() function. */
252  xReturn = xTaskCreate( prvTimerTask, "Tmr Svc", ( uint16_t ) configTIMER_TASK_STACK_DEPTH, NULL, ( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT, &xTimerTaskHandle );
253  }
254  #else
255  {
256  /* Create the timer task without storing its handle. */
257  xReturn = xTaskCreate( prvTimerTask, "Tmr Svc", ( uint16_t ) configTIMER_TASK_STACK_DEPTH, NULL, ( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT, NULL);
258  }
259  #endif
260  }
261  else
262  {
264  }
265 
266  configASSERT( xReturn );
267  return xReturn;
268 }
269 /*-----------------------------------------------------------*/
270 
271 TimerHandle_t xTimerCreate( const char * const pcTimerName, const TickType_t xTimerPeriodInTicks, const UBaseType_t uxAutoReload, void * const pvTimerID, TimerCallbackFunction_t pxCallbackFunction ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
272 {
273 Timer_t *pxNewTimer;
274 
275  /* Allocate the timer structure. */
276  if( xTimerPeriodInTicks == ( TickType_t ) 0U )
277  {
278  pxNewTimer = NULL;
279  }
280  else
281  {
282  pxNewTimer = ( Timer_t * ) pvPortMalloc( sizeof( Timer_t ) );
283  if( pxNewTimer != NULL )
284  {
285  /* Ensure the infrastructure used by the timer service task has been
286  created/initialised. */
287  prvCheckForValidListAndQueue();
288 
289  /* Initialise the timer structure members using the function parameters. */
290  pxNewTimer->pcTimerName = pcTimerName;
291  pxNewTimer->xTimerPeriodInTicks = xTimerPeriodInTicks;
292  pxNewTimer->uxAutoReload = uxAutoReload;
293  pxNewTimer->pvTimerID = pvTimerID;
294  pxNewTimer->pxCallbackFunction = pxCallbackFunction;
295  vListInitialiseItem( &( pxNewTimer->xTimerListItem ) );
296 
297  traceTIMER_CREATE( pxNewTimer );
298  }
299  else
300  {
302  }
303  }
304 
305  /* 0 is not a valid value for xTimerPeriodInTicks. */
306  configASSERT( ( xTimerPeriodInTicks > 0 ) );
307 
308  return ( TimerHandle_t ) pxNewTimer;
309 }
310 /*-----------------------------------------------------------*/
311 
312 BaseType_t xTimerGenericCommand( TimerHandle_t xTimer, const BaseType_t xCommandID, const TickType_t xOptionalValue, BaseType_t * const pxHigherPriorityTaskWoken, const TickType_t xTicksToWait )
313 {
314 BaseType_t xReturn = pdFAIL;
315 DaemonTaskMessage_t xMessage;
316 
317  /* Send a message to the timer service task to perform a particular action
318  on a particular timer definition. */
319  if( xTimerQueue != NULL )
320  {
321  /* Send a command to the timer service task to start the xTimer timer. */
322  xMessage.xMessageID = xCommandID;
323  xMessage.u.xTimerParameters.xMessageValue = xOptionalValue;
324  xMessage.u.xTimerParameters.pxTimer = ( Timer_t * ) xTimer;
325 
326  if( xCommandID < tmrFIRST_FROM_ISR_COMMAND )
327  {
329  {
330  xReturn = xQueueSendToBack( xTimerQueue, &xMessage, xTicksToWait );
331  }
332  else
333  {
334  xReturn = xQueueSendToBack( xTimerQueue, &xMessage, tmrNO_DELAY );
335  }
336  }
337  else
338  {
339  xReturn = xQueueSendToBackFromISR( xTimerQueue, &xMessage, pxHigherPriorityTaskWoken );
340  }
341 
342  traceTIMER_COMMAND_SEND( xTimer, xCommandID, xOptionalValue, xReturn );
343  }
344  else
345  {
347  }
348 
349  return xReturn;
350 }
351 /*-----------------------------------------------------------*/
352 
353 #if ( INCLUDE_xTimerGetTimerDaemonTaskHandle == 1 )
354 
356  {
357  /* If xTimerGetTimerDaemonTaskHandle() is called before the scheduler has been
358  started, then xTimerTaskHandle will be NULL. */
359  configASSERT( ( xTimerTaskHandle != NULL ) );
360  return xTimerTaskHandle;
361  }
362 
363 #endif
364 /*-----------------------------------------------------------*/
365 
366 const char * pcTimerGetTimerName( TimerHandle_t xTimer )
367 {
368 Timer_t *pxTimer = ( Timer_t * ) xTimer;
369 
370  return pxTimer->pcTimerName;
371 }
372 /*-----------------------------------------------------------*/
373 
374 static void prvProcessExpiredTimer( const TickType_t xNextExpireTime, const TickType_t xTimeNow )
375 {
376 BaseType_t xResult;
377 Timer_t * const pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList );
378 
379  /* Remove the timer from the list of active timers. A check has already
380  been performed to ensure the list is not empty. */
381  ( void ) uxListRemove( &( pxTimer->xTimerListItem ) );
382  traceTIMER_EXPIRED( pxTimer );
383 
384  /* If the timer is an auto reload timer then calculate the next
385  expiry time and re-insert the timer in the list of active timers. */
386  if( pxTimer->uxAutoReload == ( UBaseType_t ) pdTRUE )
387  {
388  /* The timer is inserted into a list using a time relative to anything
389  other than the current time. It will therefore be inserted into the
390  correct list relative to the time this task thinks it is now. */
391  if( prvInsertTimerInActiveList( pxTimer, ( xNextExpireTime + pxTimer->xTimerPeriodInTicks ), xTimeNow, xNextExpireTime ) == pdTRUE )
392  {
393  /* The timer expired before it was added to the active timer
394  list. Reload it now. */
395  xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xNextExpireTime, NULL, tmrNO_DELAY );
396  configASSERT( xResult );
397  ( void ) xResult;
398  }
399  else
400  {
402  }
403  }
404  else
405  {
407  }
408 
409  /* Call the timer callback. */
410  pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer );
411 }
412 /*-----------------------------------------------------------*/
413 
414 static void prvTimerTask( void *pvParameters )
415 {
416 TickType_t xNextExpireTime;
417 BaseType_t xListWasEmpty;
418 
419  /* Just to avoid compiler warnings. */
420  ( void ) pvParameters;
421 
422  for( ;; )
423  {
424  /* Query the timers list to see if it contains any timers, and if so,
425  obtain the time at which the next timer will expire. */
426  xNextExpireTime = prvGetNextExpireTime( &xListWasEmpty );
427 
428  /* If a timer has expired, process it. Otherwise, block this task
429  until either a timer does expire, or a command is received. */
430  prvProcessTimerOrBlockTask( xNextExpireTime, xListWasEmpty );
431 
432  /* Empty the command queue. */
433  prvProcessReceivedCommands();
434  }
435 }
436 /*-----------------------------------------------------------*/
437 
438 static void prvProcessTimerOrBlockTask( const TickType_t xNextExpireTime, const BaseType_t xListWasEmpty )
439 {
440 TickType_t xTimeNow;
441 BaseType_t xTimerListsWereSwitched;
442 
443  vTaskSuspendAll();
444  {
445  /* Obtain the time now to make an assessment as to whether the timer
446  has expired or not. If obtaining the time causes the lists to switch
447  then don't process this timer as any timers that remained in the list
448  when the lists were switched will have been processed within the
449  prvSampleTimeNow() function. */
450  xTimeNow = prvSampleTimeNow( &xTimerListsWereSwitched );
451  if( xTimerListsWereSwitched == pdFALSE )
452  {
453  /* The tick count has not overflowed, has the timer expired? */
454  if( ( xListWasEmpty == pdFALSE ) && ( xNextExpireTime <= xTimeNow ) )
455  {
456  ( void ) xTaskResumeAll();
457  prvProcessExpiredTimer( xNextExpireTime, xTimeNow );
458  }
459  else
460  {
461  /* The tick count has not overflowed, and the next expire
462  time has not been reached yet. This task should therefore
463  block to wait for the next expire time or a command to be
464  received - whichever comes first. The following line cannot
465  be reached unless xNextExpireTime > xTimeNow, except in the
466  case when the current timer list is empty. */
467  vQueueWaitForMessageRestricted( xTimerQueue, ( xNextExpireTime - xTimeNow ) );
468 
469  if( xTaskResumeAll() == pdFALSE )
470  {
471  /* Yield to wait for either a command to arrive, or the block time
472  to expire. If a command arrived between the critical section being
473  exited and this yield then the yield will not cause the task
474  to block. */
476  }
477  else
478  {
480  }
481  }
482  }
483  else
484  {
485  ( void ) xTaskResumeAll();
486  }
487  }
488 }
489 /*-----------------------------------------------------------*/
490 
491 static TickType_t prvGetNextExpireTime( BaseType_t * const pxListWasEmpty )
492 {
493 TickType_t xNextExpireTime;
494 
495  /* Timers are listed in expiry time order, with the head of the list
496  referencing the task that will expire first. Obtain the time at which
497  the timer with the nearest expiry time will expire. If there are no
498  active timers then just set the next expire time to 0. That will cause
499  this task to unblock when the tick count overflows, at which point the
500  timer lists will be switched and the next expiry time can be
501  re-assessed. */
502  *pxListWasEmpty = listLIST_IS_EMPTY( pxCurrentTimerList );
503  if( *pxListWasEmpty == pdFALSE )
504  {
505  xNextExpireTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxCurrentTimerList );
506  }
507  else
508  {
509  /* Ensure the task unblocks when the tick count rolls over. */
510  xNextExpireTime = ( TickType_t ) 0U;
511  }
512 
513  return xNextExpireTime;
514 }
515 /*-----------------------------------------------------------*/
516 
517 static TickType_t prvSampleTimeNow( BaseType_t * const pxTimerListsWereSwitched )
518 {
519 TickType_t xTimeNow;
520 PRIVILEGED_DATA static TickType_t xLastTime = ( TickType_t ) 0U; /*lint !e956 Variable is only accessible to one task. */
521 
522  xTimeNow = xTaskGetTickCount();
523 
524  if( xTimeNow < xLastTime )
525  {
526  prvSwitchTimerLists();
527  *pxTimerListsWereSwitched = pdTRUE;
528  }
529  else
530  {
531  *pxTimerListsWereSwitched = pdFALSE;
532  }
533 
534  xLastTime = xTimeNow;
535 
536  return xTimeNow;
537 }
538 /*-----------------------------------------------------------*/
539 
540 static BaseType_t prvInsertTimerInActiveList( Timer_t * const pxTimer, const TickType_t xNextExpiryTime, const TickType_t xTimeNow, const TickType_t xCommandTime )
541 {
542 BaseType_t xProcessTimerNow = pdFALSE;
543 
544  listSET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ), xNextExpiryTime );
545  listSET_LIST_ITEM_OWNER( &( pxTimer->xTimerListItem ), pxTimer );
546 
547  if( xNextExpiryTime <= xTimeNow )
548  {
549  /* Has the expiry time elapsed between the command to start/reset a
550  timer was issued, and the time the command was processed? */
551  if( ( xTimeNow - xCommandTime ) >= pxTimer->xTimerPeriodInTicks )
552  {
553  /* The time between a command being issued and the command being
554  processed actually exceeds the timers period. */
555  xProcessTimerNow = pdTRUE;
556  }
557  else
558  {
559  vListInsert( pxOverflowTimerList, &( pxTimer->xTimerListItem ) );
560  }
561  }
562  else
563  {
564  if( ( xTimeNow < xCommandTime ) && ( xNextExpiryTime >= xCommandTime ) )
565  {
566  /* If, since the command was issued, the tick count has overflowed
567  but the expiry time has not, then the timer must have already passed
568  its expiry time and should be processed immediately. */
569  xProcessTimerNow = pdTRUE;
570  }
571  else
572  {
573  vListInsert( pxCurrentTimerList, &( pxTimer->xTimerListItem ) );
574  }
575  }
576 
577  return xProcessTimerNow;
578 }
579 /*-----------------------------------------------------------*/
580 
581 static void prvProcessReceivedCommands( void )
582 {
583 DaemonTaskMessage_t xMessage;
584 Timer_t *pxTimer;
585 BaseType_t xTimerListsWereSwitched, xResult;
586 TickType_t xTimeNow;
587 
588  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. */
589  {
590  #if ( INCLUDE_xTimerPendFunctionCall == 1 )
591  {
592  /* Negative commands are pended function calls rather than timer
593  commands. */
594  if( xMessage.xMessageID < 0 )
595  {
596  const CallbackParameters_t * const pxCallback = &( xMessage.u.xCallbackParameters );
597 
598  /* The timer uses the xCallbackParameters member to request a
599  callback be executed. Check the callback is not NULL. */
600  configASSERT( pxCallback );
601 
602  /* Call the function. */
603  pxCallback->pxCallbackFunction( pxCallback->pvParameter1, pxCallback->ulParameter2 );
604  }
605  else
606  {
608  }
609  }
610  #endif /* INCLUDE_xTimerPendFunctionCall */
611 
612  /* Commands that are positive are timer commands rather than pended
613  function calls. */
614  if( xMessage.xMessageID >= ( BaseType_t ) 0 )
615  {
616  /* The messages uses the xTimerParameters member to work on a
617  software timer. */
618  pxTimer = xMessage.u.xTimerParameters.pxTimer;
619 
620  if( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) == pdFALSE )
621  {
622  /* The timer is in a list, remove it. */
623  ( void ) uxListRemove( &( pxTimer->xTimerListItem ) );
624  }
625  else
626  {
628  }
629 
630  traceTIMER_COMMAND_RECEIVED( pxTimer, xMessage.xMessageID, xMessage.u.xTimerParameters.xMessageValue );
631 
632  /* In this case the xTimerListsWereSwitched parameter is not used, but
633  it must be present in the function call. prvSampleTimeNow() must be
634  called after the message is received from xTimerQueue so there is no
635  possibility of a higher priority task adding a message to the message
636  queue with a time that is ahead of the timer daemon task (because it
637  pre-empted the timer daemon task after the xTimeNow value was set). */
638  xTimeNow = prvSampleTimeNow( &xTimerListsWereSwitched );
639 
640  switch( xMessage.xMessageID )
641  {
642  case tmrCOMMAND_START :
644  case tmrCOMMAND_RESET :
647  /* Start or restart a timer. */
648  if( prvInsertTimerInActiveList( pxTimer, xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, xTimeNow, xMessage.u.xTimerParameters.xMessageValue ) == pdTRUE )
649  {
650  /* The timer expired before it was added to the active
651  timer list. Process it now. */
652  pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer );
653  traceTIMER_EXPIRED( pxTimer );
654 
655  if( pxTimer->uxAutoReload == ( UBaseType_t ) pdTRUE )
656  {
657  xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, NULL, tmrNO_DELAY );
658  configASSERT( xResult );
659  ( void ) xResult;
660  }
661  else
662  {
664  }
665  }
666  else
667  {
669  }
670  break;
671 
672  case tmrCOMMAND_STOP :
674  /* The timer has already been removed from the active list.
675  There is nothing to do here. */
676  break;
677 
680  pxTimer->xTimerPeriodInTicks = xMessage.u.xTimerParameters.xMessageValue;
681  configASSERT( ( pxTimer->xTimerPeriodInTicks > 0 ) );
682 
683  /* The new period does not really have a reference, and can be
684  longer or shorter than the old one. The command time is
685  therefore set to the current time, and as the period cannot be
686  zero the next expiry time can only be in the future, meaning
687  (unlike for the xTimerStart() case above) there is no fail case
688  that needs to be handled here. */
689  ( void ) prvInsertTimerInActiveList( pxTimer, ( xTimeNow + pxTimer->xTimerPeriodInTicks ), xTimeNow, xTimeNow );
690  break;
691 
692  case tmrCOMMAND_DELETE :
693  /* The timer has already been removed from the active list,
694  just free up the memory. */
695  vPortFree( pxTimer );
696  break;
697 
698  default :
699  /* Don't expect to get here. */
700  break;
701  }
702  }
703  }
704 }
705 /*-----------------------------------------------------------*/
706 
707 static void prvSwitchTimerLists( void )
708 {
709 TickType_t xNextExpireTime, xReloadTime;
710 List_t *pxTemp;
711 Timer_t *pxTimer;
712 BaseType_t xResult;
713 
714  /* The tick count has overflowed. The timer lists must be switched.
715  If there are any timers still referenced from the current timer list
716  then they must have expired and should be processed before the lists
717  are switched. */
718  while( listLIST_IS_EMPTY( pxCurrentTimerList ) == pdFALSE )
719  {
720  xNextExpireTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxCurrentTimerList );
721 
722  /* Remove the timer from the list. */
723  pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList );
724  ( void ) uxListRemove( &( pxTimer->xTimerListItem ) );
725  traceTIMER_EXPIRED( pxTimer );
726 
727  /* Execute its callback, then send a command to restart the timer if
728  it is an auto-reload timer. It cannot be restarted here as the lists
729  have not yet been switched. */
730  pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer );
731 
732  if( pxTimer->uxAutoReload == ( UBaseType_t ) pdTRUE )
733  {
734  /* Calculate the reload value, and if the reload value results in
735  the timer going into the same timer list then it has already expired
736  and the timer should be re-inserted into the current list so it is
737  processed again within this loop. Otherwise a command should be sent
738  to restart the timer to ensure it is only inserted into a list after
739  the lists have been swapped. */
740  xReloadTime = ( xNextExpireTime + pxTimer->xTimerPeriodInTicks );
741  if( xReloadTime > xNextExpireTime )
742  {
743  listSET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ), xReloadTime );
744  listSET_LIST_ITEM_OWNER( &( pxTimer->xTimerListItem ), pxTimer );
745  vListInsert( pxCurrentTimerList, &( pxTimer->xTimerListItem ) );
746  }
747  else
748  {
749  xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xNextExpireTime, NULL, tmrNO_DELAY );
750  configASSERT( xResult );
751  ( void ) xResult;
752  }
753  }
754  else
755  {
757  }
758  }
759 
760  pxTemp = pxCurrentTimerList;
761  pxCurrentTimerList = pxOverflowTimerList;
762  pxOverflowTimerList = pxTemp;
763 }
764 /*-----------------------------------------------------------*/
765 
766 static void prvCheckForValidListAndQueue( void )
767 {
768  /* Check that the list from which active timers are referenced, and the
769  queue used to communicate with the timer service, have been
770  initialised. */
772  {
773  if( xTimerQueue == NULL )
774  {
775  vListInitialise( &xActiveTimerList1 );
776  vListInitialise( &xActiveTimerList2 );
777  pxCurrentTimerList = &xActiveTimerList1;
778  pxOverflowTimerList = &xActiveTimerList2;
779  xTimerQueue = xQueueCreate( ( UBaseType_t ) configTIMER_QUEUE_LENGTH, sizeof( DaemonTaskMessage_t ) );
780  configASSERT( xTimerQueue );
781 
782  #if ( configQUEUE_REGISTRY_SIZE > 0 )
783  {
784  if( xTimerQueue != NULL )
785  {
786  vQueueAddToRegistry( xTimerQueue, "TmrQ" );
787  }
788  else
789  {
791  }
792  }
793  #endif /* configQUEUE_REGISTRY_SIZE */
794  }
795  else
796  {
798  }
799  }
801 }
802 /*-----------------------------------------------------------*/
803 
805 {
806 BaseType_t xTimerIsInActiveList;
807 Timer_t *pxTimer = ( Timer_t * ) xTimer;
808 
809  /* Is the timer in the list of active timers? */
811  {
812  /* Checking to see if it is in the NULL list in effect checks to see if
813  it is referenced from either the current or the overflow timer lists in
814  one go, but the logic has to be reversed, hence the '!'. */
815  xTimerIsInActiveList = ( BaseType_t ) !( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) );
816  }
818 
819  return xTimerIsInActiveList;
820 } /*lint !e818 Can't be pointer to const due to the typedef. */
821 /*-----------------------------------------------------------*/
822 
823 void *pvTimerGetTimerID( const TimerHandle_t xTimer )
824 {
825 Timer_t * const pxTimer = ( Timer_t * ) xTimer;
826 
827  return pxTimer->pvTimerID;
828 }
829 /*-----------------------------------------------------------*/
830 
831 #if( INCLUDE_xTimerPendFunctionCall == 1 )
832 
833  BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, BaseType_t *pxHigherPriorityTaskWoken )
834  {
835  DaemonTaskMessage_t xMessage;
836  BaseType_t xReturn;
837 
838  /* Complete the message with the function parameters and post it to the
839  daemon task. */
840  xMessage.xMessageID = tmrCOMMAND_EXECUTE_CALLBACK_FROM_ISR;
841  xMessage.u.xCallbackParameters.pxCallbackFunction = xFunctionToPend;
842  xMessage.u.xCallbackParameters.pvParameter1 = pvParameter1;
843  xMessage.u.xCallbackParameters.ulParameter2 = ulParameter2;
844 
845  xReturn = xQueueSendFromISR( xTimerQueue, &xMessage, pxHigherPriorityTaskWoken );
846 
847  tracePEND_FUNC_CALL_FROM_ISR( xFunctionToPend, pvParameter1, ulParameter2, xReturn );
848 
849  return xReturn;
850  }
851 
852 #endif /* INCLUDE_xTimerPendFunctionCall */
853 /*-----------------------------------------------------------*/
854 
855 #if( INCLUDE_xTimerPendFunctionCall == 1 )
856 
857  BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, TickType_t xTicksToWait )
858  {
859  DaemonTaskMessage_t xMessage;
860  BaseType_t xReturn;
861 
862  /* Complete the message with the function parameters and post it to the
863  daemon task. */
864  xMessage.xMessageID = tmrCOMMAND_EXECUTE_CALLBACK;
865  xMessage.u.xCallbackParameters.pxCallbackFunction = xFunctionToPend;
866  xMessage.u.xCallbackParameters.pvParameter1 = pvParameter1;
867  xMessage.u.xCallbackParameters.ulParameter2 = ulParameter2;
868 
869  xReturn = xQueueSendToBack( xTimerQueue, &xMessage, xTicksToWait );
870 
871  tracePEND_FUNC_CALL( xFunctionToPend, pvParameter1, ulParameter2, xReturn );
872 
873  return xReturn;
874  }
875 
876 #endif /* INCLUDE_xTimerPendFunctionCall */
877 /*-----------------------------------------------------------*/
878 
879 /* This entire source file will be skipped if the application is not configured
880 to include software timer functionality. If you want to include software timer
881 functionality then ensure configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */
882 #endif /* configUSE_TIMERS == 1 */
883 
884 
885 
#define pdTRUE
Definition: projdefs.h:76
#define tmrCOMMAND_RESET_FROM_ISR
Definition: timers.h:103
void vPortFree(void *pv) PRIVILEGED_FUNCTION
Definition: heap_4.c:294
#define configTIMER_QUEUE_LENGTH
const char * pcTimerGetTimerName(TimerHandle_t xTimer)
#define traceTIMER_COMMAND_RECEIVED(pxTimer, xMessageID, xMessageValue)
Definition: FreeRTOS.h:551
#define listIS_CONTAINED_WITHIN(pxList, pxListItem)
Definition: list.h:309
void(* TimerCallbackFunction_t)(TimerHandle_t xTimer)
Definition: timers.h:119
#define traceTIMER_CREATE(pxNewTimer)
Definition: FreeRTOS.h:535
#define mtCOVERAGE_TEST_MARKER()
Definition: FreeRTOS.h:717
#define tracePEND_FUNC_CALL(xFunctionToPend, pvParameter1, ulParameter2, ret)
Definition: FreeRTOS.h:607
#define listGET_ITEM_VALUE_OF_HEAD_ENTRY(pxList)
Definition: list.h:208
#define tmrCOMMAND_STOP_FROM_ISR
Definition: timers.h:104
#define taskEXIT_CRITICAL()
Definition: task.h:216
void vTaskSuspendAll(void) PRIVILEGED_FUNCTION
Definition: tasks.c:1543
#define vQueueAddToRegistry(xQueue, pcName)
Definition: FreeRTOS.h:314
#define configTIMER_TASK_PRIORITY
TimerHandle_t xTimerCreate(const char *const pcTimerName, const TickType_t xTimerPeriodInTicks, const UBaseType_t uxAutoReload, void *const pvTimerID, TimerCallbackFunction_t pxCallbackFunction) PRIVILEGED_FUNCTION
#define tmrCOMMAND_CHANGE_PERIOD
Definition: timers.h:98
#define configASSERT(x)
#define traceTIMER_CREATE_FAILED()
Definition: FreeRTOS.h:539
#define taskSCHEDULER_RUNNING
Definition: task.h:243
void * pvPortMalloc(size_t xSize) PRIVILEGED_FUNCTION
Definition: heap_4.c:147
#define listSET_LIST_ITEM_VALUE(pxListItem, xValue)
Definition: list.h:189
#define portYIELD_WITHIN_API
Definition: FreeRTOS.h:649
#define tmrCOMMAND_STOP
Definition: timers.h:97
#define tmrCOMMAND_DELETE
Definition: timers.h:99
#define listLIST_IS_EMPTY(pxList)
Definition: list.h:241
BaseType_t xTimerPendFunctionCall(PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, TickType_t xTicksToWait)
BaseType_t xTimerGenericCommand(TimerHandle_t xTimer, const BaseType_t xCommandID, const TickType_t xOptionalValue, BaseType_t *const pxHigherPriorityTaskWoken, const TickType_t xTicksToWait) PRIVILEGED_FUNCTION
#define xQueueReceive(xQueue, pvBuffer, xTicksToWait)
Definition: queue.h:810
unsigned long UBaseType_t
Definition: portmacro.h:95
uint32_t TickType_t
Definition: portmacro.h:101
#define xQueueSendToBackFromISR(xQueue, pvItemToQueue, pxHigherPriorityTaskWoken)
Definition: queue.h:1096
void(* PendedFunction_t)(void *, uint32_t)
Definition: timers.h:125
#define configTIMER_TASK_STACK_DEPTH
#define tmrCOMMAND_START
Definition: timers.h:95
#define listSET_LIST_ITEM_OWNER(pxListItem, pxOwner)
Definition: list.h:171
#define traceTIMER_COMMAND_SEND(xTimer, xMessageID, xMessageValueValue, xReturn)
Definition: FreeRTOS.h:543
TickType_t xTaskGetTickCount(void) PRIVILEGED_FUNCTION
Definition: tasks.c:1674
#define portPRIVILEGE_BIT
Definition: FreeRTOS.h:645
#define tracePEND_FUNC_CALL_FROM_ISR(xFunctionToPend, pvParameter1, ulParameter2, ret)
Definition: FreeRTOS.h:611
#define tmrCOMMAND_START_DONT_TRACE
Definition: timers.h:94
#define PRIVILEGED_DATA
Definition: mpu_wrappers.h:146
#define pdFAIL
Definition: projdefs.h:79
long BaseType_t
Definition: portmacro.h:94
#define tmrCOMMAND_CHANGE_PERIOD_FROM_ISR
Definition: timers.h:105
#define listGET_OWNER_OF_HEAD_ENTRY(pxList)
Definition: list.h:298
void * TaskHandle_t
Definition: task.h:99
void * QueueHandle_t
Definition: queue.h:84
#define tmrCOMMAND_START_FROM_ISR
Definition: timers.h:102
void vQueueWaitForMessageRestricted(QueueHandle_t xQueue, TickType_t xTicksToWait) PRIVILEGED_FUNCTION
void * pvTimerGetTimerID(TimerHandle_t xTimer) PRIVILEGED_FUNCTION
BaseType_t xTimerPendFunctionCallFromISR(PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, BaseType_t *pxHigherPriorityTaskWoken)
#define pdFALSE
Definition: projdefs.h:75
#define tmrCOMMAND_EXECUTE_CALLBACK
Definition: timers.h:93
#define tmrFIRST_FROM_ISR_COMMAND
Definition: timers.h:101
BaseType_t xTaskResumeAll(void) PRIVILEGED_FUNCTION
Definition: tasks.c:1581
BaseType_t xTaskGetSchedulerState(void) PRIVILEGED_FUNCTION
#define taskENTER_CRITICAL()
Definition: task.h:202
TaskHandle_t xTimerGetTimerDaemonTaskHandle(void)
#define tmrCOMMAND_RESET
Definition: timers.h:96
#define PRIVILEGED_FUNCTION
Definition: mpu_wrappers.h:145
BaseType_t xTimerCreateTimerTask(void) PRIVILEGED_FUNCTION
#define tmrCOMMAND_EXECUTE_CALLBACK_FROM_ISR
Definition: timers.h:92
#define xQueueCreate(uxQueueLength, uxItemSize)
Definition: queue.h:169
Definition: list.h:157
void vListInitialise(List_t *const pxList)
Definition: list.c:75
BaseType_t xTimerIsTimerActive(TimerHandle_t xTimer) PRIVILEGED_FUNCTION
#define xTaskCreate(pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask)
Definition: task.h:330
#define traceTIMER_EXPIRED(pxTimer)
Definition: FreeRTOS.h:547
void * TimerHandle_t
Definition: timers.h:114
#define xQueueSendFromISR(xQueue, pvItemToQueue, pxHigherPriorityTaskWoken)
Definition: queue.h:1257
#define xQueueSendToBack(xQueue, pvItemToQueue, xTicksToWait)
Definition: queue.h:333
void vListInitialiseItem(ListItem_t *const pxItem)
Definition: list.c:95
void vListInsert(List_t *const pxList, ListItem_t *const pxNewListItem)
Definition: list.c:121
UBaseType_t uxListRemove(ListItem_t *const pxItemToRemove)
Definition: list.c:179