]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Source/timers.c
Update the method used to detect if a timer is active. Previously the timer was...
[freertos] / FreeRTOS / Source / timers.c
index 5b389c2cf527684d4bf4f720a41eaa962f444de2..a64565b4108a9fc8afe5ec5b90492c19f9623805 100644 (file)
@@ -1,67 +1,29 @@
 /*\r
-    FreeRTOS V7.6.0 - Copyright (C) 2013 Real Time Engineers Ltd.\r
-    All rights reserved\r
-\r
-    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
-\r
-    ***************************************************************************\r
-     *                                                                       *\r
-     *    FreeRTOS provides completely free yet professionally developed,    *\r
-     *    robust, strictly quality controlled, supported, and cross          *\r
-     *    platform software that has become a de facto standard.             *\r
-     *                                                                       *\r
-     *    Help yourself get started quickly and support the FreeRTOS         *\r
-     *    project by purchasing a FreeRTOS tutorial book, reference          *\r
-     *    manual, or both from: http://www.FreeRTOS.org/Documentation        *\r
-     *                                                                       *\r
-     *    Thank you!                                                         *\r
-     *                                                                       *\r
-    ***************************************************************************\r
-\r
-    This file is part of the FreeRTOS distribution.\r
-\r
-    FreeRTOS is free software; you can redistribute it and/or modify it under\r
-    the terms of the GNU General Public License (version 2) as published by the\r
-    Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.\r
-\r
-    >>! NOTE: The modification to the GPL is included to allow you to distribute\r
-    >>! a combined work that includes FreeRTOS without being obliged to provide\r
-    >>! the source code for proprietary components outside of the FreeRTOS\r
-    >>! kernel.\r
-\r
-    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
-    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
-    FOR A PARTICULAR PURPOSE.  Full license text is available from the following\r
-    link: http://www.freertos.org/a00114.html\r
-\r
-    1 tab == 4 spaces!\r
-\r
-    ***************************************************************************\r
-     *                                                                       *\r
-     *    Having a problem?  Start by reading the FAQ "My application does   *\r
-     *    not run, what could be wrong?"                                     *\r
-     *                                                                       *\r
-     *    http://www.FreeRTOS.org/FAQHelp.html                               *\r
-     *                                                                       *\r
-    ***************************************************************************\r
-\r
-    http://www.FreeRTOS.org - Documentation, books, training, latest versions,\r
-    license and Real Time Engineers Ltd. contact details.\r
-\r
-    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
-    including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
-    compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
-\r
-    http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High\r
-    Integrity Systems to sell under the OpenRTOS brand.  Low cost OpenRTOS\r
-    licenses offer ticketed support, indemnification and middleware.\r
-\r
-    http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
-    engineered and independently SIL3 certified version for use in safety and\r
-    mission critical applications that require provable dependability.\r
-\r
-    1 tab == 4 spaces!\r
-*/\r
+ * FreeRTOS Kernel V10.1.1\r
+ * Copyright (C) 2018 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
+ *\r
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+ * this software and associated documentation files (the "Software"), to deal in\r
+ * the Software without restriction, including without limitation the rights to\r
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+ * the Software, and to permit persons to whom the Software is furnished to do so,\r
+ * subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be included in all\r
+ * copies or substantial portions of the Software.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://aws.amazon.com/freertos\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ */\r
 \r
 /* Standard includes. */\r
 #include <stdlib.h>\r
@@ -76,15 +38,15 @@ task.h is included from an application file. */
 #include "queue.h"\r
 #include "timers.h"\r
 \r
-#if ( INCLUDE_xTimerPendCallbackFromISR == 1 ) && ( configUSE_TIMERS == 0 )\r
-       #error configUSE_TIMERS must be set to 1 to make the INCLUDE_xTimerPendCallbackFromISR() function available.\r
+#if ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 0 )\r
+       #error configUSE_TIMERS must be set to 1 to make the xTimerPendFunctionCall() function available.\r
 #endif\r
 \r
-/* Lint e961 and e750 are suppressed as a MISRA exception justified because the\r
-MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the\r
-header files above, but not in this file, in order to generate the correct\r
-privileged Vs unprivileged linkage and placement. */\r
-#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */\r
+/* Lint e9021, e961 and e750 are suppressed as a MISRA exception justified\r
+because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined\r
+for the header files above, but not in this file, in order to generate the\r
+correct privileged Vs unprivileged linkage and placement. */\r
+#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e9021 !e961 !e750. */\r
 \r
 \r
 /* This entire source file will be skipped if the application is not configured\r
@@ -94,19 +56,37 @@ configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */
 #if ( configUSE_TIMERS == 1 )\r
 \r
 /* Misc definitions. */\r
-#define tmrNO_DELAY            ( portTickType ) 0U\r
+#define tmrNO_DELAY            ( TickType_t ) 0U\r
+\r
+/* The name assigned to the timer service task.  This can be overridden by\r
+defining trmTIMER_SERVICE_TASK_NAME in FreeRTOSConfig.h. */\r
+#ifndef configTIMER_SERVICE_TASK_NAME\r
+       #define configTIMER_SERVICE_TASK_NAME "Tmr Svc"\r
+#endif\r
+\r
+/* Bit definitions used in the ucStatus member of a timer structure. */\r
+#define tmrSTATUS_IS_ACTIVE                                    ( ( uint8_t ) 0x01 )\r
+#define tmrSTATUS_IS_STATICALLY_ALLOCATED      ( ( uint8_t ) 0x02 )\r
+#define tmrSTATUS_IS_AUTORELOAD                                ( ( uint8_t ) 0x04 )\r
 \r
 /* The definition of the timers themselves. */\r
-typedef struct tmrTimerControl\r
+typedef struct tmrTimerControl /* The old naming convention is used to prevent breaking kernel aware debuggers. */\r
 {\r
-       const signed char               *pcTimerName;           /*<< Text name.  This is not used by the kernel, it is included simply to make debugging easier. */\r
-       xListItem                               xTimerListItem;         /*<< Standard linked list item as used by all kernel features for event management. */\r
-       portTickType                    xTimerPeriodInTicks;/*<< How quickly and often the timer expires. */\r
-       unsigned portBASE_TYPE  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. */\r
+       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
+       ListItem_t                              xTimerListItem;         /*<< Standard linked list item as used by all kernel features for event management. */\r
+       TickType_t                              xTimerPeriodInTicks;/*<< How quickly and often the timer expires. */\r
        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
-       tmrTIMER_CALLBACK               pxCallbackFunction;     /*<< The function that will be called when the timer expires. */\r
+       TimerCallbackFunction_t pxCallbackFunction;     /*<< The function that will be called when the timer expires. */\r
+       #if( configUSE_TRACE_FACILITY == 1 )\r
+               UBaseType_t                     uxTimerNumber;          /*<< An ID assigned by trace tools such as FreeRTOS+Trace */\r
+       #endif\r
+       uint8_t                                 ucStatus;                       /*<< Holds bits to say if the timer was statically allocated or not, and if it is active or not. */\r
 } xTIMER;\r
 \r
+/* The old xTIMER name is maintained above then typedefed to the new Timer_t\r
+name below to enable the use of older kernel aware debuggers. */\r
+typedef xTIMER Timer_t;\r
+\r
 /* The definition of messages that can be sent and received on the timer queue.\r
 Two types of message can be queued - messages that manipulate a software timer,\r
 and messages that request the execution of a non-timer related callback.  The\r
@@ -114,58 +94,66 @@ two message types are defined in two separate structures, xTimerParametersType
 and xCallbackParametersType respectively. */\r
 typedef struct tmrTimerParameters\r
 {\r
-       portTickType                    xMessageValue;          /*<< An optional value used by a subset of commands, for example, when changing the period of a timer. */\r
-       xTIMER *                                pxTimer;                        /*<< The timer to which the command will be applied. */\r
-} xTimerParametersType;\r
+       TickType_t                      xMessageValue;          /*<< An optional value used by a subset of commands, for example, when changing the period of a timer. */\r
+       Timer_t *                       pxTimer;                        /*<< The timer to which the command will be applied. */\r
+} TimerParameter_t;\r
 \r
 \r
 typedef struct tmrCallbackParameters\r
 {\r
-       pdAPPLICATION_CALLBACK_CODE     pxCallbackFunction; /* << The callback function to execute. */\r
-       void *pvParameter1;                                                             /* << The value that will be used as the callback functions first parameter. */\r
-       unsigned long ulParameter2;                                             /* << The value that will be used as the callback functions second parameter. */\r
-} xCallbackParametersType;\r
+       PendedFunction_t        pxCallbackFunction;     /* << The callback function to execute. */\r
+       void *pvParameter1;                                             /* << The value that will be used as the callback functions first parameter. */\r
+       uint32_t ulParameter2;                                  /* << The value that will be used as the callback functions second parameter. */\r
+} CallbackParameters_t;\r
 \r
 /* The structure that contains the two message types, along with an identifier\r
 that is used to determine which message type is valid. */\r
 typedef struct tmrTimerQueueMessage\r
 {\r
-       portBASE_TYPE                   xMessageID;                     /*<< The command being sent to the timer service task. */\r
+       BaseType_t                      xMessageID;                     /*<< The command being sent to the timer service task. */\r
        union\r
        {\r
-               xTimerParametersType xTimerParameters;\r
+               TimerParameter_t xTimerParameters;\r
 \r
                /* Don't include xCallbackParameters if it is not going to be used as\r
                it makes the structure (and therefore the timer queue) larger. */\r
-               #if ( INCLUDE_xTimerPendCallbackFromISR == 1 )\r
-                       xCallbackParametersType xCallbackParameters;\r
-               #endif /* INCLUDE_xTimerPendCallbackFromISR */\r
+               #if ( INCLUDE_xTimerPendFunctionCall == 1 )\r
+                       CallbackParameters_t xCallbackParameters;\r
+               #endif /* INCLUDE_xTimerPendFunctionCall */\r
        } u;\r
-} xDAEMON_TASK_MESSAGE;\r
+} DaemonTaskMessage_t;\r
 \r
-/*lint -e956 A manual analysis and inspection has been used to determine which\r
-static variables must be declared volatile. */\r
+/*lint -save -e956 A manual analysis and inspection has been used to determine\r
+which static variables must be declared volatile. */\r
 \r
 /* The list in which active timers are stored.  Timers are referenced in expire\r
 time order, with the nearest expiry time at the front of the list.  Only the\r
-timer service task is allowed to access these lists. */\r
-PRIVILEGED_DATA static xList xActiveTimerList1;\r
-PRIVILEGED_DATA static xList xActiveTimerList2;\r
-PRIVILEGED_DATA static xList *pxCurrentTimerList;\r
-PRIVILEGED_DATA static xList *pxOverflowTimerList;\r
+timer service task is allowed to access these lists.\r
+xActiveTimerList1 and xActiveTimerList2 could be at function scope but that\r
+breaks some kernel aware debuggers, and debuggers that reply on removing the\r
+static qualifier. */\r
+PRIVILEGED_DATA static List_t xActiveTimerList1;\r
+PRIVILEGED_DATA static List_t xActiveTimerList2;\r
+PRIVILEGED_DATA static List_t *pxCurrentTimerList;\r
+PRIVILEGED_DATA static List_t *pxOverflowTimerList;\r
 \r
 /* A queue that is used to send commands to the timer service task. */\r
-PRIVILEGED_DATA static xQueueHandle xTimerQueue = NULL;\r
+PRIVILEGED_DATA static QueueHandle_t xTimerQueue = NULL;\r
+PRIVILEGED_DATA static TaskHandle_t xTimerTaskHandle = NULL;\r
 \r
-#if ( INCLUDE_xTimerGetTimerDaemonTaskHandle == 1 )\r
+/*lint -restore */\r
 \r
-       PRIVILEGED_DATA static xTaskHandle xTimerTaskHandle = NULL;\r
+/*-----------------------------------------------------------*/\r
 \r
-#endif\r
+#if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
 \r
-/*lint +e956 */\r
+       /* If static allocation is supported then the application must provide the\r
+       following callback function - which enables the application to optionally\r
+       provide the memory that will be used by the timer task as the task's stack\r
+       and TCB. */\r
+       extern void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize );\r
 \r
-/*-----------------------------------------------------------*/\r
+#endif\r
 \r
 /*\r
  * Initialise the infrastructure used by the timer service task if it has not\r
@@ -184,31 +172,31 @@ static void prvTimerTask( void *pvParameters ) PRIVILEGED_FUNCTION;
  * Called by the timer service task to interpret and process a command it\r
  * received on the timer queue.\r
  */\r
-static void    prvProcessReceivedCommands( void ) PRIVILEGED_FUNCTION;\r
+static void prvProcessReceivedCommands( void ) PRIVILEGED_FUNCTION;\r
 \r
 /*\r
  * Insert the timer into either xActiveTimerList1, or xActiveTimerList2,\r
  * depending on if the expire time causes a timer counter overflow.\r
  */\r
-static portBASE_TYPE prvInsertTimerInActiveList( xTIMER *pxTimer, portTickType xNextExpiryTime, portTickType xTimeNow, portTickType xCommandTime ) PRIVILEGED_FUNCTION;\r
+static BaseType_t prvInsertTimerInActiveList( Timer_t * const pxTimer, const TickType_t xNextExpiryTime, const TickType_t xTimeNow, const TickType_t xCommandTime ) PRIVILEGED_FUNCTION;\r
 \r
 /*\r
  * An active timer has reached its expire time.  Reload the timer if it is an\r
  * auto reload timer, then call its callback.\r
  */\r
-static void prvProcessExpiredTimer( portTickType xNextExpireTime, portTickType xTimeNow ) PRIVILEGED_FUNCTION;\r
+static void prvProcessExpiredTimer( const TickType_t xNextExpireTime, const TickType_t xTimeNow ) PRIVILEGED_FUNCTION;\r
 \r
 /*\r
  * The tick count has overflowed.  Switch the timer lists after ensuring the\r
  * current timer list does not still reference some timers.\r
  */\r
-static void prvSwitchTimerLists( portTickType xLastTime ) PRIVILEGED_FUNCTION;\r
+static void prvSwitchTimerLists( void ) PRIVILEGED_FUNCTION;\r
 \r
 /*\r
  * Obtain the current tick count, setting *pxTimerListsWereSwitched to pdTRUE\r
  * if a tick count overflow occurred since prvSampleTimeNow() was last called.\r
  */\r
-static portTickType prvSampleTimeNow( portBASE_TYPE *pxTimerListsWereSwitched ) PRIVILEGED_FUNCTION;\r
+static TickType_t prvSampleTimeNow( BaseType_t * const pxTimerListsWereSwitched ) PRIVILEGED_FUNCTION;\r
 \r
 /*\r
  * If the timer list contains any active timers then return the expire time of\r
@@ -216,19 +204,29 @@ static portTickType prvSampleTimeNow( portBASE_TYPE *pxTimerListsWereSwitched )
  * timer list does not contain any timers then return 0 and set *pxListWasEmpty\r
  * to pdTRUE.\r
  */\r
-static portTickType prvGetNextExpireTime( portBASE_TYPE *pxListWasEmpty ) PRIVILEGED_FUNCTION;\r
+static TickType_t prvGetNextExpireTime( BaseType_t * const pxListWasEmpty ) PRIVILEGED_FUNCTION;\r
 \r
 /*\r
  * If a timer has expired, process it.  Otherwise, block the timer service task\r
  * until either a timer does expire or a command is received.\r
  */\r
-static void prvProcessTimerOrBlockTask( portTickType xNextExpireTime, portBASE_TYPE xListWasEmpty ) PRIVILEGED_FUNCTION;\r
+static void prvProcessTimerOrBlockTask( const TickType_t xNextExpireTime, BaseType_t xListWasEmpty ) PRIVILEGED_FUNCTION;\r
 \r
+/*\r
+ * Called after a Timer_t structure has been allocated either statically or\r
+ * dynamically to fill in the structure's members.\r
+ */\r
+static void prvInitialiseNewTimer(     const char * const pcTimerName,                 /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
+                                                                       const TickType_t xTimerPeriodInTicks,\r
+                                                                       const UBaseType_t uxAutoReload,\r
+                                                                       void * const pvTimerID,\r
+                                                                       TimerCallbackFunction_t pxCallbackFunction,\r
+                                                                       Timer_t *pxNewTimer ) PRIVILEGED_FUNCTION;\r
 /*-----------------------------------------------------------*/\r
 \r
-portBASE_TYPE xTimerCreateTimerTask( void )\r
+BaseType_t xTimerCreateTimerTask( void )\r
 {\r
-portBASE_TYPE xReturn = pdFAIL;\r
+BaseType_t xReturn = pdFAIL;\r
 \r
        /* This function is called when the scheduler is started if\r
        configUSE_TIMERS is set to 1.  Check that the infrastructure used by the\r
@@ -238,18 +236,40 @@ portBASE_TYPE xReturn = pdFAIL;
 \r
        if( xTimerQueue != NULL )\r
        {\r
-               #if ( INCLUDE_xTimerGetTimerDaemonTaskHandle == 1 )\r
+               #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
                {\r
-                       /* Create the timer task, storing its handle in xTimerTaskHandle so\r
-                       it can be returned by the xTimerGetTimerDaemonTaskHandle() function. */\r
-                       xReturn = xTaskCreate( prvTimerTask, ( signed char * ) "Tmr Svc", ( unsigned short ) configTIMER_TASK_STACK_DEPTH, NULL, ( ( unsigned portBASE_TYPE ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT, &xTimerTaskHandle );\r
+                       StaticTask_t *pxTimerTaskTCBBuffer = NULL;\r
+                       StackType_t *pxTimerTaskStackBuffer = NULL;\r
+                       uint32_t ulTimerTaskStackSize;\r
+\r
+                       vApplicationGetTimerTaskMemory( &pxTimerTaskTCBBuffer, &pxTimerTaskStackBuffer, &ulTimerTaskStackSize );\r
+                       xTimerTaskHandle = xTaskCreateStatic(   prvTimerTask,\r
+                                                                                                       configTIMER_SERVICE_TASK_NAME,\r
+                                                                                                       ulTimerTaskStackSize,\r
+                                                                                                       NULL,\r
+                                                                                                       ( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT,\r
+                                                                                                       pxTimerTaskStackBuffer,\r
+                                                                                                       pxTimerTaskTCBBuffer );\r
+\r
+                       if( xTimerTaskHandle != NULL )\r
+                       {\r
+                               xReturn = pdPASS;\r
+                       }\r
                }\r
                #else\r
                {\r
-                       /* Create the timer task without storing its handle. */\r
-                       xReturn = xTaskCreate( prvTimerTask, ( signed char * ) "Tmr Svc", ( unsigned short ) configTIMER_TASK_STACK_DEPTH, NULL, ( ( unsigned portBASE_TYPE ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT, NULL);\r
+                       xReturn = xTaskCreate(  prvTimerTask,\r
+                                                                       configTIMER_SERVICE_TASK_NAME,\r
+                                                                       configTIMER_TASK_STACK_DEPTH,\r
+                                                                       NULL,\r
+                                                                       ( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT,\r
+                                                                       &xTimerTaskHandle );\r
                }\r
-               #endif\r
+               #endif /* configSUPPORT_STATIC_ALLOCATION */\r
+       }\r
+       else\r
+       {\r
+               mtCOVERAGE_TEST_MARKER();\r
        }\r
 \r
        configASSERT( xReturn );\r
@@ -257,51 +277,113 @@ portBASE_TYPE xReturn = pdFAIL;
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-xTimerHandle xTimerCreate( const signed char * const pcTimerName, portTickType xTimerPeriodInTicks, unsigned portBASE_TYPE uxAutoReload, void *pvTimerID, tmrTIMER_CALLBACK pxCallbackFunction )\r
-{\r
-xTIMER *pxNewTimer;\r
+#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )\r
 \r
-       /* Allocate the timer structure. */\r
-       if( xTimerPeriodInTicks == ( portTickType ) 0U )\r
+       TimerHandle_t xTimerCreate(     const char * const pcTimerName,                 /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
+                                                               const TickType_t xTimerPeriodInTicks,\r
+                                                               const UBaseType_t uxAutoReload,\r
+                                                               void * const pvTimerID,\r
+                                                               TimerCallbackFunction_t pxCallbackFunction )\r
        {\r
-               pxNewTimer = NULL;\r
+       Timer_t *pxNewTimer;\r
+\r
+               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
+\r
+               if( pxNewTimer != NULL )\r
+               {\r
+                       /* Status is thus far zero as the timer is not created statically\r
+                       and has not been started.  The autoreload bit may get set in\r
+                       prvInitialiseNewTimer. */\r
+                       pxNewTimer->ucStatus = 0x00;\r
+                       prvInitialiseNewTimer( pcTimerName, xTimerPeriodInTicks, uxAutoReload, pvTimerID, pxCallbackFunction, pxNewTimer );\r
+               }\r
+\r
+               return pxNewTimer;\r
        }\r
-       else\r
+\r
+#endif /* configSUPPORT_STATIC_ALLOCATION */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
+\r
+       TimerHandle_t xTimerCreateStatic(       const char * const pcTimerName,         /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
+                                                                               const TickType_t xTimerPeriodInTicks,\r
+                                                                               const UBaseType_t uxAutoReload,\r
+                                                                               void * const pvTimerID,\r
+                                                                               TimerCallbackFunction_t pxCallbackFunction,\r
+                                                                               StaticTimer_t *pxTimerBuffer )\r
        {\r
-               pxNewTimer = ( xTIMER * ) pvPortMalloc( sizeof( xTIMER ) );\r
-               if( pxNewTimer != NULL )\r
+       Timer_t *pxNewTimer;\r
+\r
+               #if( configASSERT_DEFINED == 1 )\r
                {\r
-                       /* Ensure the infrastructure used by the timer service task has been\r
-                       created/initialised. */\r
-                       prvCheckForValidListAndQueue();\r
-\r
-                       /* Initialise the timer structure members using the function parameters. */\r
-                       pxNewTimer->pcTimerName = pcTimerName;\r
-                       pxNewTimer->xTimerPeriodInTicks = xTimerPeriodInTicks;\r
-                       pxNewTimer->uxAutoReload = uxAutoReload;\r
-                       pxNewTimer->pvTimerID = pvTimerID;\r
-                       pxNewTimer->pxCallbackFunction = pxCallbackFunction;\r
-                       vListInitialiseItem( &( pxNewTimer->xTimerListItem ) );\r
-\r
-                       traceTIMER_CREATE( pxNewTimer );\r
+                       /* Sanity check that the size of the structure used to declare a\r
+                       variable of type StaticTimer_t equals the size of the real timer\r
+                       structure. */\r
+                       volatile size_t xSize = sizeof( StaticTimer_t );\r
+                       configASSERT( xSize == sizeof( Timer_t ) );\r
+                       ( void ) xSize; /* Keeps lint quiet when configASSERT() is not defined. */\r
                }\r
-               else\r
+               #endif /* configASSERT_DEFINED */\r
+\r
+               /* A pointer to a StaticTimer_t structure MUST be provided, use it. */\r
+               configASSERT( pxTimerBuffer );\r
+               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
+\r
+               if( pxNewTimer != NULL )\r
                {\r
-                       traceTIMER_CREATE_FAILED();\r
+                       /* Timers can be created statically or dynamically so note this\r
+                       timer was created statically in case it is later deleted.  The\r
+                       autoreload bit may get set in prvInitialiseNewTimer(). */\r
+                       pxNewTimer->ucStatus = tmrSTATUS_IS_STATICALLY_ALLOCATED;\r
+\r
+                       prvInitialiseNewTimer( pcTimerName, xTimerPeriodInTicks, uxAutoReload, pvTimerID, pxCallbackFunction, pxNewTimer );\r
                }\r
+\r
+               return pxNewTimer;\r
        }\r
 \r
+#endif /* configSUPPORT_STATIC_ALLOCATION */\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvInitialiseNewTimer(     const char * const pcTimerName,                 /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
+                                                                       const TickType_t xTimerPeriodInTicks,\r
+                                                                       const UBaseType_t uxAutoReload,\r
+                                                                       void * const pvTimerID,\r
+                                                                       TimerCallbackFunction_t pxCallbackFunction,\r
+                                                                       Timer_t *pxNewTimer )\r
+{\r
        /* 0 is not a valid value for xTimerPeriodInTicks. */\r
        configASSERT( ( xTimerPeriodInTicks > 0 ) );\r
 \r
-       return ( xTimerHandle ) pxNewTimer;\r
+       if( pxNewTimer != NULL )\r
+       {\r
+               /* Ensure the infrastructure used by the timer service task has been\r
+               created/initialised. */\r
+               prvCheckForValidListAndQueue();\r
+\r
+               /* Initialise the timer structure members using the function\r
+               parameters. */\r
+               pxNewTimer->pcTimerName = pcTimerName;\r
+               pxNewTimer->xTimerPeriodInTicks = xTimerPeriodInTicks;\r
+               pxNewTimer->pvTimerID = pvTimerID;\r
+               pxNewTimer->pxCallbackFunction = pxCallbackFunction;\r
+               vListInitialiseItem( &( pxNewTimer->xTimerListItem ) );\r
+               if( uxAutoReload != pdFALSE )\r
+               {\r
+                       pxNewTimer->ucStatus |= tmrSTATUS_IS_AUTORELOAD;\r
+               }\r
+               traceTIMER_CREATE( pxNewTimer );\r
+       }\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-portBASE_TYPE xTimerGenericCommand( xTimerHandle xTimer, portBASE_TYPE xCommandID, portTickType xOptionalValue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portTickType xBlockTime )\r
+BaseType_t xTimerGenericCommand( TimerHandle_t xTimer, const BaseType_t xCommandID, const TickType_t xOptionalValue, BaseType_t * const pxHigherPriorityTaskWoken, const TickType_t xTicksToWait )\r
 {\r
-portBASE_TYPE xReturn = pdFAIL;\r
-xDAEMON_TASK_MESSAGE xMessage;\r
+BaseType_t xReturn = pdFAIL;\r
+DaemonTaskMessage_t xMessage;\r
+\r
+       configASSERT( xTimer );\r
 \r
        /* Send a message to the timer service task to perform a particular action\r
        on a particular timer definition. */\r
@@ -310,13 +392,13 @@ xDAEMON_TASK_MESSAGE xMessage;
                /* Send a command to the timer service task to start the xTimer timer. */\r
                xMessage.xMessageID = xCommandID;\r
                xMessage.u.xTimerParameters.xMessageValue = xOptionalValue;\r
-               xMessage.u.xTimerParameters.pxTimer = ( xTIMER * ) xTimer;\r
+               xMessage.u.xTimerParameters.pxTimer = xTimer;\r
 \r
-               if( pxHigherPriorityTaskWoken == NULL )\r
+               if( xCommandID < tmrFIRST_FROM_ISR_COMMAND )\r
                {\r
                        if( xTaskGetSchedulerState() == taskSCHEDULER_RUNNING )\r
                        {\r
-                               xReturn = xQueueSendToBack( xTimerQueue, &xMessage, xBlockTime );\r
+                               xReturn = xQueueSendToBack( xTimerQueue, &xMessage, xTicksToWait );\r
                        }\r
                        else\r
                        {\r
@@ -330,68 +412,114 @@ xDAEMON_TASK_MESSAGE xMessage;
 \r
                traceTIMER_COMMAND_SEND( xTimer, xCommandID, xOptionalValue, xReturn );\r
        }\r
+       else\r
+       {\r
+               mtCOVERAGE_TEST_MARKER();\r
+       }\r
 \r
        return xReturn;\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-#if ( INCLUDE_xTimerGetTimerDaemonTaskHandle == 1 )\r
+TaskHandle_t xTimerGetTimerDaemonTaskHandle( void )\r
+{\r
+       /* If xTimerGetTimerDaemonTaskHandle() is called before the scheduler has been\r
+       started, then xTimerTaskHandle will be NULL. */\r
+       configASSERT( ( xTimerTaskHandle != NULL ) );\r
+       return xTimerTaskHandle;\r
+}\r
+/*-----------------------------------------------------------*/\r
 \r
-       xTaskHandle xTimerGetTimerDaemonTaskHandle( void )\r
-       {\r
-               /* If xTimerGetTimerDaemonTaskHandle() is called before the scheduler has been\r
-               started, then xTimerTaskHandle will be NULL. */\r
-               configASSERT( ( xTimerTaskHandle != NULL ) );\r
-               return xTimerTaskHandle;\r
-       }\r
+TickType_t xTimerGetPeriod( TimerHandle_t xTimer )\r
+{\r
+Timer_t *pxTimer = xTimer;\r
 \r
-#endif\r
+       configASSERT( xTimer );\r
+       return pxTimer->xTimerPeriodInTicks;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer )\r
+{\r
+Timer_t * pxTimer =  xTimer;\r
+TickType_t xReturn;\r
+\r
+       configASSERT( xTimer );\r
+       xReturn = listGET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ) );\r
+       return xReturn;\r
+}\r
 /*-----------------------------------------------------------*/\r
 \r
-static void prvProcessExpiredTimer( portTickType xNextExpireTime, portTickType xTimeNow )\r
+const char * pcTimerGetName( TimerHandle_t xTimer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
 {\r
-xTIMER *pxTimer;\r
-portBASE_TYPE xResult;\r
+Timer_t *pxTimer = xTimer;\r
+\r
+       configASSERT( xTimer );\r
+       return pxTimer->pcTimerName;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvProcessExpiredTimer( const TickType_t xNextExpireTime, const TickType_t xTimeNow )\r
+{\r
+BaseType_t xResult;\r
+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
 \r
        /* Remove the timer from the list of active timers.  A check has already\r
        been performed to ensure the list is not empty. */\r
-       pxTimer = ( xTIMER * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList );\r
        ( void ) uxListRemove( &( pxTimer->xTimerListItem ) );\r
        traceTIMER_EXPIRED( pxTimer );\r
 \r
        /* If the timer is an auto reload timer then calculate the next\r
        expiry time and re-insert the timer in the list of active timers. */\r
-       if( pxTimer->uxAutoReload == ( unsigned portBASE_TYPE ) pdTRUE )\r
+       if( ( pxTimer->ucStatus & tmrSTATUS_IS_AUTORELOAD ) != 0 )\r
        {\r
-               /* This is the only time a timer is inserted into a list using\r
-               a time relative to anything other than the current time.  It\r
-               will therefore be inserted into the correct list relative to\r
-               the time this task thinks it is now, even if a command to\r
-               switch lists due to a tick count overflow is already waiting in\r
-               the timer queue. */\r
-               if( prvInsertTimerInActiveList( pxTimer, ( xNextExpireTime + pxTimer->xTimerPeriodInTicks ), xTimeNow, xNextExpireTime ) == pdTRUE )\r
+               /* The timer is inserted into a list using a time relative to anything\r
+               other than the current time.  It will therefore be inserted into the\r
+               correct list relative to the time this task thinks it is now. */\r
+               if( prvInsertTimerInActiveList( pxTimer, ( xNextExpireTime + pxTimer->xTimerPeriodInTicks ), xTimeNow, xNextExpireTime ) != pdFALSE )\r
                {\r
                        /* The timer expired before it was added to the active timer\r
                        list.  Reload it now.  */\r
-                       xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START, xNextExpireTime, NULL, tmrNO_DELAY );\r
+                       xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xNextExpireTime, NULL, tmrNO_DELAY );\r
                        configASSERT( xResult );\r
                        ( void ) xResult;\r
                }\r
+               else\r
+               {\r
+                       mtCOVERAGE_TEST_MARKER();\r
+               }\r
+       }\r
+       else\r
+       {\r
+               pxTimer->ucStatus &= ~tmrSTATUS_IS_ACTIVE;\r
+               mtCOVERAGE_TEST_MARKER();\r
        }\r
 \r
        /* Call the timer callback. */\r
-       pxTimer->pxCallbackFunction( ( xTimerHandle ) pxTimer );\r
+       pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer );\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
 static void prvTimerTask( void *pvParameters )\r
 {\r
-portTickType xNextExpireTime;\r
-portBASE_TYPE xListWasEmpty;\r
+TickType_t xNextExpireTime;\r
+BaseType_t xListWasEmpty;\r
 \r
        /* Just to avoid compiler warnings. */\r
        ( void ) pvParameters;\r
 \r
+       #if( configUSE_DAEMON_TASK_STARTUP_HOOK == 1 )\r
+       {\r
+               extern void vApplicationDaemonTaskStartupHook( void );\r
+\r
+               /* Allow the application writer to execute some code in the context of\r
+               this task at the point the task starts executing.  This is useful if the\r
+               application includes initialisation code that would benefit from\r
+               executing after the scheduler has been started. */\r
+               vApplicationDaemonTaskStartupHook();\r
+       }\r
+       #endif /* configUSE_DAEMON_TASK_STARTUP_HOOK */\r
+\r
        for( ;; )\r
        {\r
                /* Query the timers list to see if it contains any timers, and if so,\r
@@ -408,10 +536,10 @@ portBASE_TYPE xListWasEmpty;
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-static void prvProcessTimerOrBlockTask( portTickType xNextExpireTime, portBASE_TYPE xListWasEmpty )\r
+static void prvProcessTimerOrBlockTask( const TickType_t xNextExpireTime, BaseType_t xListWasEmpty )\r
 {\r
-portTickType xTimeNow;\r
-portBASE_TYPE xTimerListsWereSwitched;\r
+TickType_t xTimeNow;\r
+BaseType_t xTimerListsWereSwitched;\r
 \r
        vTaskSuspendAll();\r
        {\r
@@ -437,16 +565,27 @@ portBASE_TYPE xTimerListsWereSwitched;
                                received - whichever comes first.  The following line cannot\r
                                be reached unless xNextExpireTime > xTimeNow, except in the\r
                                case when the current timer list is empty. */\r
-                               vQueueWaitForMessageRestricted( xTimerQueue, ( xNextExpireTime - xTimeNow ) );\r
+                               if( xListWasEmpty != pdFALSE )\r
+                               {\r
+                                       /* The current timer list is empty - is the overflow list\r
+                                       also empty? */\r
+                                       xListWasEmpty = listLIST_IS_EMPTY( pxOverflowTimerList );\r
+                               }\r
+\r
+                               vQueueWaitForMessageRestricted( xTimerQueue, ( xNextExpireTime - xTimeNow ), xListWasEmpty );\r
 \r
                                if( xTaskResumeAll() == pdFALSE )\r
                                {\r
-                                       /* Yield to wait for either a command to arrive, or the block time\r
-                                       to expire.  If a command arrived between the critical section being\r
-                                       exited and this yield then the yield will not cause the task\r
-                                       to block. */\r
+                                       /* Yield to wait for either a command to arrive, or the\r
+                                       block time to expire.  If a command arrived between the\r
+                                       critical section being exited and this yield then the yield\r
+                                       will not cause the task to block. */\r
                                        portYIELD_WITHIN_API();\r
                                }\r
+                               else\r
+                               {\r
+                                       mtCOVERAGE_TEST_MARKER();\r
+                               }\r
                        }\r
                }\r
                else\r
@@ -457,9 +596,9 @@ portBASE_TYPE xTimerListsWereSwitched;
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-static portTickType prvGetNextExpireTime( portBASE_TYPE *pxListWasEmpty )\r
+static TickType_t prvGetNextExpireTime( BaseType_t * const pxListWasEmpty )\r
 {\r
-portTickType xNextExpireTime;\r
+TickType_t xNextExpireTime;\r
 \r
        /* Timers are listed in expiry time order, with the head of the list\r
        referencing the task that will expire first.  Obtain the time at which\r
@@ -476,23 +615,23 @@ portTickType xNextExpireTime;
        else\r
        {\r
                /* Ensure the task unblocks when the tick count rolls over. */\r
-               xNextExpireTime = ( portTickType ) 0U;\r
+               xNextExpireTime = ( TickType_t ) 0U;\r
        }\r
 \r
        return xNextExpireTime;\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-static portTickType prvSampleTimeNow( portBASE_TYPE *pxTimerListsWereSwitched )\r
+static TickType_t prvSampleTimeNow( BaseType_t * const pxTimerListsWereSwitched )\r
 {\r
-portTickType xTimeNow;\r
-PRIVILEGED_DATA static portTickType xLastTime = ( portTickType ) 0U; /*lint !e956 Variable is only accessible to one task. */\r
+TickType_t xTimeNow;\r
+PRIVILEGED_DATA static TickType_t xLastTime = ( TickType_t ) 0U; /*lint !e956 Variable is only accessible to one task. */\r
 \r
        xTimeNow = xTaskGetTickCount();\r
 \r
        if( xTimeNow < xLastTime )\r
        {\r
-               prvSwitchTimerLists( xLastTime );\r
+               prvSwitchTimerLists();\r
                *pxTimerListsWereSwitched = pdTRUE;\r
        }\r
        else\r
@@ -506,9 +645,9 @@ PRIVILEGED_DATA static portTickType xLastTime = ( portTickType ) 0U; /*lint !e95
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-static portBASE_TYPE prvInsertTimerInActiveList( xTIMER *pxTimer, portTickType xNextExpiryTime, portTickType xTimeNow, portTickType xCommandTime )\r
+static BaseType_t prvInsertTimerInActiveList( Timer_t * const pxTimer, const TickType_t xNextExpiryTime, const TickType_t xTimeNow, const TickType_t xCommandTime )\r
 {\r
-portBASE_TYPE xProcessTimerNow = pdFALSE;\r
+BaseType_t xProcessTimerNow = pdFALSE;\r
 \r
        listSET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ), xNextExpiryTime );\r
        listSET_LIST_ITEM_OWNER( &( pxTimer->xTimerListItem ), pxTimer );\r
@@ -517,7 +656,7 @@ portBASE_TYPE xProcessTimerNow = pdFALSE;
        {\r
                /* Has the expiry time elapsed between the command to start/reset a\r
                timer was issued, and the time the command was processed? */\r
-               if( ( xTimeNow - xCommandTime ) >= pxTimer->xTimerPeriodInTicks )\r
+               if( ( ( TickType_t ) ( xTimeNow - xCommandTime ) ) >= pxTimer->xTimerPeriodInTicks ) /*lint !e961 MISRA exception as the casts are only redundant for some ports. */\r
                {\r
                        /* The time between a command being issued and the command being\r
                        processed actually exceeds the timers period.  */\r
@@ -549,18 +688,20 @@ portBASE_TYPE xProcessTimerNow = pdFALSE;
 \r
 static void    prvProcessReceivedCommands( void )\r
 {\r
-xDAEMON_TASK_MESSAGE xMessage;\r
-xTIMER *pxTimer;\r
-portBASE_TYPE xTimerListsWereSwitched, xResult;\r
-portTickType xTimeNow;\r
+DaemonTaskMessage_t xMessage;\r
+Timer_t *pxTimer;\r
+BaseType_t xTimerListsWereSwitched, xResult;\r
+TickType_t xTimeNow;\r
 \r
        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
        {\r
-               #if ( INCLUDE_xTimerPendCallbackFromISR == 1 )\r
+               #if ( INCLUDE_xTimerPendFunctionCall == 1 )\r
                {\r
-                       if( xMessage.xMessageID == tmrCOMMAND_EXECUTE_CALLBACK )\r
+                       /* Negative commands are pended function calls rather than timer\r
+                       commands. */\r
+                       if( xMessage.xMessageID < ( BaseType_t ) 0 )\r
                        {\r
-                               const xCallbackParametersType * const pxCallback = &( xMessage.u.xCallbackParameters );\r
+                               const CallbackParameters_t * const pxCallback = &( xMessage.u.xCallbackParameters );\r
 \r
                                /* The timer uses the xCallbackParameters member to request a\r
                                callback be executed.  Check the callback is not NULL. */\r
@@ -569,20 +710,30 @@ portTickType xTimeNow;
                                /* Call the function. */\r
                                pxCallback->pxCallbackFunction( pxCallback->pvParameter1, pxCallback->ulParameter2 );\r
                        }\r
+                       else\r
+                       {\r
+                               mtCOVERAGE_TEST_MARKER();\r
+                       }\r
                }\r
-               #endif /* INCLUDE_xTimerPendCallbackFromISR */\r
+               #endif /* INCLUDE_xTimerPendFunctionCall */\r
 \r
-               if( xMessage.xMessageID != tmrCOMMAND_EXECUTE_CALLBACK )\r
+               /* Commands that are positive are timer commands rather than pended\r
+               function calls. */\r
+               if( xMessage.xMessageID >= ( BaseType_t ) 0 )\r
                {\r
                        /* The messages uses the xTimerParameters member to work on a\r
                        software timer. */\r
                        pxTimer = xMessage.u.xTimerParameters.pxTimer;\r
 \r
-                       if( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) == pdFALSE )\r
+                       if( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) == pdFALSE ) /*lint !e961. The cast is only redundant when NULL is passed into the macro. */\r
                        {\r
                                /* The timer is in a list, remove it. */\r
                                ( void ) uxListRemove( &( pxTimer->xTimerListItem ) );\r
                        }\r
+                       else\r
+                       {\r
+                               mtCOVERAGE_TEST_MARKER();\r
+                       }\r
 \r
                        traceTIMER_COMMAND_RECEIVED( pxTimer, xMessage.xMessageID, xMessage.u.xTimerParameters.xMessageValue );\r
 \r
@@ -597,44 +748,69 @@ portTickType xTimeNow;
                        switch( xMessage.xMessageID )\r
                        {\r
                                case tmrCOMMAND_START :\r
+                           case tmrCOMMAND_START_FROM_ISR :\r
+                           case tmrCOMMAND_RESET :\r
+                           case tmrCOMMAND_RESET_FROM_ISR :\r
+                               case tmrCOMMAND_START_DONT_TRACE :\r
                                        /* Start or restart a timer. */\r
-                                       if( prvInsertTimerInActiveList( pxTimer,  xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, xTimeNow, xMessage.u.xTimerParameters.xMessageValue ) == pdTRUE )\r
+                                       pxTimer->ucStatus |= tmrSTATUS_IS_ACTIVE;\r
+                                       if( prvInsertTimerInActiveList( pxTimer,  xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, xTimeNow, xMessage.u.xTimerParameters.xMessageValue ) != pdFALSE )\r
                                        {\r
-                                               /* The timer expired before it was added to the active timer\r
-                                               list.  Process it now. */\r
-                                               pxTimer->pxCallbackFunction( ( xTimerHandle ) pxTimer );\r
+                                               /* The timer expired before it was added to the active\r
+                                               timer list.  Process it now. */\r
+                                               pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer );\r
+                                               traceTIMER_EXPIRED( pxTimer );\r
 \r
-                                               if( pxTimer->uxAutoReload == ( unsigned portBASE_TYPE ) pdTRUE )\r
+                                               if( ( pxTimer->ucStatus & tmrSTATUS_IS_AUTORELOAD ) != 0 )\r
                                                {\r
-                                                       xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START, xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, NULL, tmrNO_DELAY );\r
+                                                       xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, NULL, tmrNO_DELAY );\r
                                                        configASSERT( xResult );\r
                                                        ( void ) xResult;\r
                                                }\r
+                                               else\r
+                                               {\r
+                                                       mtCOVERAGE_TEST_MARKER();\r
+                                               }\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               mtCOVERAGE_TEST_MARKER();\r
                                        }\r
                                        break;\r
 \r
                                case tmrCOMMAND_STOP :\r
-                                       /* The timer has already been removed from the active list.\r
-                                       There is nothing to do here. */\r
+                               case tmrCOMMAND_STOP_FROM_ISR :\r
+                                       /* The timer has already been removed from the active list. */\r
+                                       pxTimer->ucStatus &= ~tmrSTATUS_IS_ACTIVE;\r
                                        break;\r
 \r
                                case tmrCOMMAND_CHANGE_PERIOD :\r
+                               case tmrCOMMAND_CHANGE_PERIOD_FROM_ISR :\r
+                                       pxTimer->ucStatus |= tmrSTATUS_IS_ACTIVE;\r
                                        pxTimer->xTimerPeriodInTicks = xMessage.u.xTimerParameters.xMessageValue;\r
                                        configASSERT( ( pxTimer->xTimerPeriodInTicks > 0 ) );\r
 \r
-                                       /* The new period does not really have a reference, and can be\r
-                                       longer or shorter than the old one.  The command time is\r
-                                       therefore set to the current time, and as the period cannot be\r
-                                       zero the next expiry time can only be in the future, meaning\r
-                                       (unlike for the xTimerStart() case above) there is no fail case\r
-                                       that needs to be handled here. */\r
+                                       /* The new period does not really have a reference, and can\r
+                                       be longer or shorter than the old one.  The command time is\r
+                                       therefore set to the current time, and as the period cannot\r
+                                       be zero the next expiry time can only be in the future,\r
+                                       meaning (unlike for the xTimerStart() case above) there is\r
+                                       no fail case that needs to be handled here. */\r
                                        ( void ) prvInsertTimerInActiveList( pxTimer, ( xTimeNow + pxTimer->xTimerPeriodInTicks ), xTimeNow, xTimeNow );\r
                                        break;\r
 \r
                                case tmrCOMMAND_DELETE :\r
                                        /* The timer has already been removed from the active list,\r
-                                       just free up the memory. */\r
-                                       vPortFree( pxTimer );\r
+                                       just free up the memory if the memory was dynamically\r
+                                       allocated. */\r
+                                       if( ( pxTimer->ucStatus & tmrSTATUS_IS_STATICALLY_ALLOCATED ) == ( uint8_t ) 0 )\r
+                                       {\r
+                                               vPortFree( pxTimer );\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               pxTimer->ucStatus &= ~tmrSTATUS_IS_ACTIVE;\r
+                                       }\r
                                        break;\r
 \r
                                default :\r
@@ -646,15 +822,12 @@ portTickType xTimeNow;
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-static void prvSwitchTimerLists( portTickType xLastTime )\r
+static void prvSwitchTimerLists( void )\r
 {\r
-portTickType xNextExpireTime, xReloadTime;\r
-xList *pxTemp;\r
-xTIMER *pxTimer;\r
-portBASE_TYPE xResult;\r
-\r
-       /* Remove compiler warnings if configASSERT() is not defined. */\r
-       ( void ) xLastTime;\r
+TickType_t xNextExpireTime, xReloadTime;\r
+List_t *pxTemp;\r
+Timer_t *pxTimer;\r
+BaseType_t xResult;\r
 \r
        /* The tick count has overflowed.  The timer lists must be switched.\r
        If there are any timers still referenced from the current timer list\r
@@ -665,15 +838,16 @@ portBASE_TYPE xResult;
                xNextExpireTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxCurrentTimerList );\r
 \r
                /* Remove the timer from the list. */\r
-               pxTimer = ( xTIMER * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList );\r
+               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
                ( void ) uxListRemove( &( pxTimer->xTimerListItem ) );\r
+               traceTIMER_EXPIRED( pxTimer );\r
 \r
                /* Execute its callback, then send a command to restart the timer if\r
                it is an auto-reload timer.  It cannot be restarted here as the lists\r
                have not yet been switched. */\r
-               pxTimer->pxCallbackFunction( ( xTimerHandle ) pxTimer );\r
+               pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer );\r
 \r
-               if( pxTimer->uxAutoReload == ( unsigned portBASE_TYPE ) pdTRUE )\r
+               if( ( pxTimer->ucStatus & tmrSTATUS_IS_AUTORELOAD ) != 0 )\r
                {\r
                        /* Calculate the reload value, and if the reload value results in\r
                        the timer going into the same timer list then it has already expired\r
@@ -690,11 +864,15 @@ portBASE_TYPE xResult;
                        }\r
                        else\r
                        {\r
-                               xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START, xNextExpireTime, NULL, tmrNO_DELAY );\r
+                               xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xNextExpireTime, NULL, tmrNO_DELAY );\r
                                configASSERT( xResult );\r
                                ( void ) xResult;\r
                        }\r
                }\r
+               else\r
+               {\r
+                       mtCOVERAGE_TEST_MARKER();\r
+               }\r
        }\r
 \r
        pxTemp = pxCurrentTimerList;\r
@@ -716,70 +894,171 @@ static void prvCheckForValidListAndQueue( void )
                        vListInitialise( &xActiveTimerList2 );\r
                        pxCurrentTimerList = &xActiveTimerList1;\r
                        pxOverflowTimerList = &xActiveTimerList2;\r
-                       xTimerQueue = xQueueCreate( ( unsigned portBASE_TYPE ) configTIMER_QUEUE_LENGTH, sizeof( xDAEMON_TASK_MESSAGE ) );\r
-                       configASSERT( xTimerQueue );\r
+\r
+                       #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
+                       {\r
+                               /* The timer queue is allocated statically in case\r
+                               configSUPPORT_DYNAMIC_ALLOCATION is 0. */\r
+                               static StaticQueue_t xStaticTimerQueue; /*lint !e956 Ok to declare in this manner to prevent additional conditional compilation guards in other locations. */\r
+                               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
+\r
+                               xTimerQueue = xQueueCreateStatic( ( UBaseType_t ) configTIMER_QUEUE_LENGTH, ( UBaseType_t ) sizeof( DaemonTaskMessage_t ), &( ucStaticTimerQueueStorage[ 0 ] ), &xStaticTimerQueue );\r
+                       }\r
+                       #else\r
+                       {\r
+                               xTimerQueue = xQueueCreate( ( UBaseType_t ) configTIMER_QUEUE_LENGTH, sizeof( DaemonTaskMessage_t ) );\r
+                       }\r
+                       #endif\r
 \r
                        #if ( configQUEUE_REGISTRY_SIZE > 0 )\r
                        {\r
                                if( xTimerQueue != NULL )\r
                                {\r
-                                       vQueueAddToRegistry( xTimerQueue, ( signed char * ) "TmrQ" );\r
+                                       vQueueAddToRegistry( xTimerQueue, "TmrQ" );\r
+                               }\r
+                               else\r
+                               {\r
+                                       mtCOVERAGE_TEST_MARKER();\r
                                }\r
                        }\r
                        #endif /* configQUEUE_REGISTRY_SIZE */\r
                }\r
+               else\r
+               {\r
+                       mtCOVERAGE_TEST_MARKER();\r
+               }\r
        }\r
        taskEXIT_CRITICAL();\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-portBASE_TYPE xTimerIsTimerActive( xTimerHandle xTimer )\r
+BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer )\r
 {\r
-portBASE_TYPE xTimerIsInActiveList;\r
-xTIMER *pxTimer = ( xTIMER * ) xTimer;\r
+BaseType_t xReturn;\r
+Timer_t *pxTimer = xTimer;\r
+\r
+       configASSERT( xTimer );\r
 \r
        /* Is the timer in the list of active timers? */\r
        taskENTER_CRITICAL();\r
        {\r
-               /* Checking to see if it is in the NULL list in effect checks to see if\r
-               it is referenced from either the current or the overflow timer lists in\r
-               one go, but the logic has to be reversed, hence the '!'. */\r
-               xTimerIsInActiveList = !( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) );\r
+               if( ( pxTimer->ucStatus & tmrSTATUS_IS_ACTIVE ) == 0 )\r
+               {\r
+                       xReturn = pdFALSE;\r
+               }\r
+               else\r
+               {\r
+                       xReturn = pdTRUE;\r
+               }\r
        }\r
        taskEXIT_CRITICAL();\r
 \r
-       return xTimerIsInActiveList;\r
+       return xReturn;\r
+} /*lint !e818 Can't be pointer to const due to the typedef. */\r
+/*-----------------------------------------------------------*/\r
+\r
+void *pvTimerGetTimerID( const TimerHandle_t xTimer )\r
+{\r
+Timer_t * const pxTimer = xTimer;\r
+void *pvReturn;\r
+\r
+       configASSERT( xTimer );\r
+\r
+       taskENTER_CRITICAL();\r
+       {\r
+               pvReturn = pxTimer->pvTimerID;\r
+       }\r
+       taskEXIT_CRITICAL();\r
+\r
+       return pvReturn;\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-void *pvTimerGetTimerID( xTimerHandle xTimer )\r
+void vTimerSetTimerID( TimerHandle_t xTimer, void *pvNewID )\r
 {\r
-xTIMER *pxTimer = ( xTIMER * ) xTimer;\r
+Timer_t * const pxTimer = xTimer;\r
+\r
+       configASSERT( xTimer );\r
 \r
-       return pxTimer->pvTimerID;\r
+       taskENTER_CRITICAL();\r
+       {\r
+               pxTimer->pvTimerID = pvNewID;\r
+       }\r
+       taskEXIT_CRITICAL();\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-#if( INCLUDE_xTimerPendCallbackFromISR == 1 )\r
+#if( INCLUDE_xTimerPendFunctionCall == 1 )\r
 \r
-       portBASE_TYPE xTimerPendCallbackFromISR( pdAPPLICATION_CALLBACK_CODE pvCallbackFunction, void *pvParameter1, unsigned long ulParameter2, portBASE_TYPE *pxHigherPriorityTaskWoken )\r
+       BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, BaseType_t *pxHigherPriorityTaskWoken )\r
        {\r
-       xDAEMON_TASK_MESSAGE xMessage;\r
-       portBASE_TYPE xReturn;\r
+       DaemonTaskMessage_t xMessage;\r
+       BaseType_t xReturn;\r
 \r
                /* Complete the message with the function parameters and post it to the\r
                daemon task. */\r
-               xMessage.xMessageID = tmrCOMMAND_EXECUTE_CALLBACK;\r
-               xMessage.u.xCallbackParameters.pxCallbackFunction = pvCallbackFunction;\r
+               xMessage.xMessageID = tmrCOMMAND_EXECUTE_CALLBACK_FROM_ISR;\r
+               xMessage.u.xCallbackParameters.pxCallbackFunction = xFunctionToPend;\r
                xMessage.u.xCallbackParameters.pvParameter1 = pvParameter1;\r
                xMessage.u.xCallbackParameters.ulParameter2 = ulParameter2;\r
 \r
                xReturn = xQueueSendFromISR( xTimerQueue, &xMessage, pxHigherPriorityTaskWoken );\r
 \r
+               tracePEND_FUNC_CALL_FROM_ISR( xFunctionToPend, pvParameter1, ulParameter2, xReturn );\r
+\r
+               return xReturn;\r
+       }\r
+\r
+#endif /* INCLUDE_xTimerPendFunctionCall */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( INCLUDE_xTimerPendFunctionCall == 1 )\r
+\r
+       BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, TickType_t xTicksToWait )\r
+       {\r
+       DaemonTaskMessage_t xMessage;\r
+       BaseType_t xReturn;\r
+\r
+               /* This function can only be called after a timer has been created or\r
+               after the scheduler has been started because, until then, the timer\r
+               queue does not exist. */\r
+               configASSERT( xTimerQueue );\r
+\r
+               /* Complete the message with the function parameters and post it to the\r
+               daemon task. */\r
+               xMessage.xMessageID = tmrCOMMAND_EXECUTE_CALLBACK;\r
+               xMessage.u.xCallbackParameters.pxCallbackFunction = xFunctionToPend;\r
+               xMessage.u.xCallbackParameters.pvParameter1 = pvParameter1;\r
+               xMessage.u.xCallbackParameters.ulParameter2 = ulParameter2;\r
+\r
+               xReturn = xQueueSendToBack( xTimerQueue, &xMessage, xTicksToWait );\r
+\r
+               tracePEND_FUNC_CALL( xFunctionToPend, pvParameter1, ulParameter2, xReturn );\r
+\r
                return xReturn;\r
        }\r
 \r
-#endif /* INCLUDE_xTimerPendCallbackFromISR */\r
+#endif /* INCLUDE_xTimerPendFunctionCall */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if ( configUSE_TRACE_FACILITY == 1 )\r
+\r
+       UBaseType_t uxTimerGetTimerNumber( TimerHandle_t xTimer )\r
+       {\r
+               return ( ( Timer_t * ) xTimer )->uxTimerNumber;\r
+       }\r
+\r
+#endif /* configUSE_TRACE_FACILITY */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if ( configUSE_TRACE_FACILITY == 1 )\r
+\r
+       void vTimerSetTimerNumber( TimerHandle_t xTimer, UBaseType_t uxTimerNumber )\r
+       {\r
+               ( ( Timer_t * ) xTimer )->uxTimerNumber = uxTimerNumber;\r
+       }\r
+\r
+#endif /* configUSE_TRACE_FACILITY */\r
 /*-----------------------------------------------------------*/\r
 \r
 /* This entire source file will be skipped if the application is not configured\r