]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Source/timers.c
Prepare for V9.0.0 release:
[freertos] / FreeRTOS / Source / timers.c
index f9d3fa1169ee5231edcc16949cb2294418c5ac1d..e49587f5115dbbe2e23a7ecfb53752783fb98911 100644 (file)
@@ -1,60 +1,64 @@
 /*\r
-    FreeRTOS V8.0.0 - Copyright (C) 2014 Real Time Engineers Ltd.\r
+    FreeRTOS V9.0.0 - Copyright (C) 2016 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
+    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
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<\r
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<\r
+    >>!   obliged to provide the source code for proprietary components     !<<\r
+    >>!   outside of the FreeRTOS kernel.                                   !<<\r
+    ***************************************************************************\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
+    FOR A PARTICULAR PURPOSE.  Full license text is available on 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
+     *    FreeRTOS provides completely free yet professionally developed,    *\r
+     *    robust, strictly quality controlled, supported, and cross          *\r
+     *    platform software that is more than just the market leader, it     *\r
+     *    is the industry's de facto standard.                               *\r
      *                                                                       *\r
-     *    http://www.FreeRTOS.org/FAQHelp.html                               *\r
+     *    Help yourself get started quickly while simultaneously helping     *\r
+     *    to support the FreeRTOS project by purchasing a FreeRTOS           *\r
+     *    tutorial book, reference manual, or both:                          *\r
+     *    http://www.FreeRTOS.org/Documentation                              *\r
      *                                                                       *\r
     ***************************************************************************\r
 \r
-    http://www.FreeRTOS.org - Documentation, books, training, latest versions,\r
-    license and Real Time Engineers Ltd. contact details.\r
+    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading\r
+    the FAQ page "My application does not run, what could be wrong?".  Have you\r
+    defined configASSERT()?\r
+\r
+    http://www.FreeRTOS.org/support - In return for receiving this top quality\r
+    embedded software for free we request you assist our global community by\r
+    participating in the support forum.\r
+\r
+    http://www.FreeRTOS.org/training - Investing in training allows your team to\r
+    be as productive as possible as early as possible.  Now you can receive\r
+    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers\r
+    Ltd, and the world's leading authority on the world's leading RTOS.\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
+    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.\r
+    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.\r
+\r
+    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High\r
+    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS\r
+    licenses offer ticketed support, indemnification and commercial 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
@@ -108,6 +112,10 @@ typedef struct tmrTimerControl
        #if( configUSE_TRACE_FACILITY == 1 )\r
                UBaseType_t                     uxTimerNumber;          /*<< An ID assigned by trace tools such as FreeRTOS+Trace */\r
        #endif\r
+\r
+       #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )\r
+               uint8_t                         ucStaticallyAllocated; /*<< Set to pdTRUE if the timer was created statically so no attempt is made to free the memory again if the timer is later deleted. */\r
+       #endif\r
 } xTIMER;\r
 \r
 /* The old xTIMER name is maintained above then typedefed to the new Timer_t\r
@@ -163,16 +171,21 @@ PRIVILEGED_DATA static List_t *pxOverflowTimerList;
 \r
 /* A queue that is used to send commands to the timer service task. */\r
 PRIVILEGED_DATA static QueueHandle_t xTimerQueue = NULL;\r
+PRIVILEGED_DATA static TaskHandle_t xTimerTaskHandle = NULL;\r
 \r
-#if ( INCLUDE_xTimerGetTimerDaemonTaskHandle == 1 )\r
+/*lint +e956 */\r
 \r
-       PRIVILEGED_DATA static TaskHandle_t 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
@@ -191,7 +204,7 @@ 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
@@ -229,8 +242,18 @@ static TickType_t prvGetNextExpireTime( BaseType_t * const pxListWasEmpty ) PRIV
  * 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( const TickType_t xNextExpireTime, const BaseType_t 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,\r
+                                                                       const TickType_t xTimerPeriodInTicks,\r
+                                                                       const UBaseType_t uxAutoReload,\r
+                                                                       void * const pvTimerID,\r
+                                                                       TimerCallbackFunction_t pxCallbackFunction,\r
+                                                                       Timer_t *pxNewTimer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
 /*-----------------------------------------------------------*/\r
 \r
 BaseType_t xTimerCreateTimerTask( void )\r
@@ -245,18 +268,36 @@ BaseType_t 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, "Tmr Svc", ( uint16_t ) configTIMER_TASK_STACK_DEPTH, NULL, ( ( UBaseType_t ) 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
+                                                                                                       "Tmr Svc",\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, "Tmr Svc", ( uint16_t ) configTIMER_TASK_STACK_DEPTH, NULL, ( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT, NULL);\r
+                       xReturn = xTaskCreate(  prvTimerTask,\r
+                                                                       "Tmr Svc",\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
@@ -268,44 +309,108 @@ BaseType_t xReturn = pdFAIL;
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-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. */\r
-{\r
-Timer_t *pxNewTimer;\r
+#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )\r
 \r
-       /* Allocate the timer structure. */\r
-       if( xTimerPeriodInTicks == ( TickType_t ) 0U )\r
-       {\r
-               pxNewTimer = NULL;\r
-       }\r
-       else\r
+       TimerHandle_t xTimerCreate(     const char * const pcTimerName,\r
+                                                               const TickType_t xTimerPeriodInTicks,\r
+                                                               const UBaseType_t uxAutoReload,\r
+                                                               void * const pvTimerID,\r
+                                                               TimerCallbackFunction_t pxCallbackFunction ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
        {\r
+       Timer_t *pxNewTimer;\r
+\r
                pxNewTimer = ( Timer_t * ) pvPortMalloc( sizeof( Timer_t ) );\r
+\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 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
+                       prvInitialiseNewTimer( pcTimerName, xTimerPeriodInTicks, uxAutoReload, pvTimerID, pxCallbackFunction, pxNewTimer );\r
+\r
+                       #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
+                       {\r
+                               /* Timers can be created statically or dynamically, so note this\r
+                               timer was created dynamically in case the timer is later\r
+                               deleted. */\r
+                               pxNewTimer->ucStaticallyAllocated = pdFALSE;\r
+                       }\r
+                       #endif /* configSUPPORT_STATIC_ALLOCATION */\r
                }\r
-               else\r
+\r
+               return pxNewTimer;\r
+       }\r
+\r
+#endif /* configSUPPORT_STATIC_ALLOCATION */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
+\r
+       TimerHandle_t xTimerCreateStatic(       const char * const pcTimerName,\r
+                                                                               const TickType_t xTimerPeriodInTicks,\r
+                                                                               const UBaseType_t uxAutoReload,\r
+                                                                               void * const pvTimerID,\r
+                                                                               TimerCallbackFunction_t pxCallbackFunction,\r
+                                                                               StaticTimer_t *pxTimerBuffer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
+       {\r
+       Timer_t *pxNewTimer;\r
+\r
+               #if( configASSERT_DEFINED == 1 )\r
                {\r
-                       traceTIMER_CREATE_FAILED();\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
+                       structures. */\r
+                       volatile size_t xSize = sizeof( StaticTimer_t );\r
+                       configASSERT( xSize == sizeof( Timer_t ) );\r
                }\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 Unusual cast is ok as the structures are designed to have the same alignment, and the size is checked by an assert. */\r
+\r
+               if( pxNewTimer != NULL )\r
+               {\r
+                       prvInitialiseNewTimer( pcTimerName, xTimerPeriodInTicks, uxAutoReload, pvTimerID, pxCallbackFunction, pxNewTimer );\r
+\r
+                       #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )\r
+                       {\r
+                               /* Timers can be created statically or dynamically so note this\r
+                               timer was created statically in case it is later deleted. */\r
+                               pxNewTimer->ucStaticallyAllocated = pdTRUE;\r
+                       }\r
+                       #endif /* configSUPPORT_DYNAMIC_ALLOCATION */\r
+               }\r
+\r
+               return pxNewTimer;\r
        }\r
 \r
+#endif /* configSUPPORT_STATIC_ALLOCATION */\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvInitialiseNewTimer(     const char * const pcTimerName,\r
+                                                                       const TickType_t xTimerPeriodInTicks,\r
+                                                                       const UBaseType_t uxAutoReload,\r
+                                                                       void * const pvTimerID,\r
+                                                                       TimerCallbackFunction_t pxCallbackFunction,\r
+                                                                       Timer_t *pxNewTimer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
+{\r
        /* 0 is not a valid value for xTimerPeriodInTicks. */\r
        configASSERT( ( xTimerPeriodInTicks > 0 ) );\r
 \r
-       return ( TimerHandle_t ) 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->uxAutoReload = uxAutoReload;\r
+               pxNewTimer->pvTimerID = pvTimerID;\r
+               pxNewTimer->pxCallbackFunction = pxCallbackFunction;\r
+               vListInitialiseItem( &( pxNewTimer->xTimerListItem ) );\r
+               traceTIMER_CREATE( pxNewTimer );\r
+       }\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
@@ -314,6 +419,8 @@ BaseType_t xTimerGenericCommand( TimerHandle_t xTimer, const BaseType_t xCommand
 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
        if( xTimerQueue != NULL )\r
@@ -350,23 +457,40 @@ DaemonTaskMessage_t xMessage;
 }\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
-       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
+TickType_t xTimerGetPeriod( TimerHandle_t xTimer )\r
+{\r
+Timer_t *pxTimer = ( Timer_t * ) xTimer;\r
 \r
-#endif\r
+       configASSERT( xTimer );\r
+       return pxTimer->xTimerPeriodInTicks;\r
+}\r
 /*-----------------------------------------------------------*/\r
 \r
-const char * pcTimerGetTimerName( TimerHandle_t xTimer )\r
+TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer )\r
+{\r
+Timer_t * pxTimer = ( Timer_t * ) xTimer;\r
+TickType_t xReturn;\r
+\r
+       configASSERT( xTimer );\r
+       xReturn = listGET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ) );\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+const char * pcTimerGetName( TimerHandle_t xTimer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
 {\r
 Timer_t *pxTimer = ( Timer_t * ) xTimer;\r
 \r
+       configASSERT( xTimer );\r
        return pxTimer->pcTimerName;\r
 }\r
 /*-----------------------------------------------------------*/\r
@@ -388,7 +512,7 @@ Timer_t * const pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTi
                /* 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 ) == pdTRUE )\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
@@ -419,6 +543,18 @@ BaseType_t xListWasEmpty;
        /* 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
@@ -435,7 +571,7 @@ BaseType_t xListWasEmpty;
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-static void prvProcessTimerOrBlockTask( const TickType_t xNextExpireTime, const BaseType_t xListWasEmpty )\r
+static void prvProcessTimerOrBlockTask( const TickType_t xNextExpireTime, BaseType_t xListWasEmpty )\r
 {\r
 TickType_t xTimeNow;\r
 BaseType_t xTimerListsWereSwitched;\r
@@ -464,14 +600,21 @@ BaseType_t 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
@@ -548,7 +691,7 @@ BaseType_t 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
@@ -591,7 +734,7 @@ TickType_t xTimeNow;
                {\r
                        /* Negative commands are pended function calls rather than timer\r
                        commands. */\r
-                       if( xMessage.xMessageID < 0 )\r
+                       if( xMessage.xMessageID < ( BaseType_t ) 0 )\r
                        {\r
                                const CallbackParameters_t * const pxCallback = &( xMessage.u.xCallbackParameters );\r
 \r
@@ -645,7 +788,7 @@ TickType_t xTimeNow;
                            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
+                                       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\r
                                                timer list.  Process it now. */\r
@@ -680,19 +823,40 @@ TickType_t xTimeNow;
                                        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( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) )\r
+                                       {\r
+                                               /* The timer can only have been allocated dynamically -\r
+                                               free it again. */\r
+                                               vPortFree( pxTimer );\r
+                                       }\r
+                                       #elif( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )\r
+                                       {\r
+                                               /* The timer could have been allocated statically or\r
+                                               dynamically, so check before attempting to free the\r
+                                               memory. */\r
+                                               if( pxTimer->ucStaticallyAllocated == ( uint8_t ) pdFALSE )\r
+                                               {\r
+                                                       vPortFree( pxTimer );\r
+                                               }\r
+                                               else\r
+                                               {\r
+                                                       mtCOVERAGE_TEST_MARKER();\r
+                                               }\r
+                                       }\r
+                                       #endif /* configSUPPORT_DYNAMIC_ALLOCATION */\r
                                        break;\r
 \r
                                default :\r
@@ -776,8 +940,21 @@ static void prvCheckForValidListAndQueue( void )
                        vListInitialise( &xActiveTimerList2 );\r
                        pxCurrentTimerList = &xActiveTimerList1;\r
                        pxOverflowTimerList = &xActiveTimerList2;\r
-                       xTimerQueue = xQueueCreate( ( UBaseType_t ) configTIMER_QUEUE_LENGTH, sizeof( DaemonTaskMessage_t ) );\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;\r
+                               static uint8_t ucStaticTimerQueueStorage[ configTIMER_QUEUE_LENGTH * sizeof( DaemonTaskMessage_t ) ];\r
+\r
+                               xTimerQueue = xQueueCreateStatic( ( UBaseType_t ) configTIMER_QUEUE_LENGTH, 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
@@ -806,6 +983,8 @@ BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer )
 BaseType_t xTimerIsInActiveList;\r
 Timer_t *pxTimer = ( Timer_t * ) xTimer;\r
 \r
+       configASSERT( xTimer );\r
+\r
        /* Is the timer in the list of active timers? */\r
        taskENTER_CRITICAL();\r
        {\r
@@ -823,8 +1002,31 @@ Timer_t *pxTimer = ( Timer_t * ) xTimer;
 void *pvTimerGetTimerID( const TimerHandle_t xTimer )\r
 {\r
 Timer_t * const pxTimer = ( Timer_t * ) 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 vTimerSetTimerID( TimerHandle_t xTimer, void *pvNewID )\r
+{\r
+Timer_t * const pxTimer = ( Timer_t * ) 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
@@ -843,7 +1045,7 @@ Timer_t * const pxTimer = ( Timer_t * ) xTimer;
                xMessage.u.xCallbackParameters.ulParameter2 = ulParameter2;\r
 \r
                xReturn = xQueueSendFromISR( xTimerQueue, &xMessage, pxHigherPriorityTaskWoken );\r
-               \r
+\r
                tracePEND_FUNC_CALL_FROM_ISR( xFunctionToPend, pvParameter1, ulParameter2, xReturn );\r
 \r
                return xReturn;\r
@@ -859,6 +1061,11 @@ Timer_t * const pxTimer = ( Timer_t * ) xTimer;
        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
@@ -869,7 +1076,7 @@ Timer_t * const pxTimer = ( Timer_t * ) xTimer;
                xReturn = xQueueSendToBack( xTimerQueue, &xMessage, xTicksToWait );\r
 \r
                tracePEND_FUNC_CALL( xFunctionToPend, pvParameter1, ulParameter2, xReturn );\r
-               \r
+\r
                return xReturn;\r
        }\r
 \r