]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Source/timers.c
Added uxTimerGetReloadMode() API function.
[freertos] / FreeRTOS / Source / timers.c
index c56d3bf212802cb70f853424aec60bf0adf69af8..12a2f4e9b6a6213d1befd75a5a3fa61d6e076390 100644 (file)
@@ -1,71 +1,29 @@
 /*\r
-    FreeRTOS V8.2.3 - Copyright (C) 2015 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
-    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
-    ***************************************************************************\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 on the following\r
-    link: http://www.freertos.org/a00114.html\r
-\r
-    ***************************************************************************\r
-     *                                                                       *\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
-     *    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/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.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
-    mission critical applications that require provable dependability.\r
-\r
-    1 tab == 4 spaces!\r
-*/\r
+ * FreeRTOS Kernel V10.2.1\r
+ * Copyright (C) 2019 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
@@ -84,11 +42,11 @@ task.h is included from an application file. */
        #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
@@ -100,22 +58,29 @@ configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */
 /* Misc definitions. */\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 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
-       UBaseType_t                             uxAutoReload;           /*<< Set to pdTRUE if the timer should be automatically restarted once expired.  Set to pdFALSE if the timer is, in effect, a one-shot timer. */\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
        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
-\r
-       #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
-               uint8_t                         ucStaticallyAllocated; /*<< Set to pdTRUE if the timer was created from a StaticTimer_t structure, and pdFALSE if the timer structure was allocated dynamically. */\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
@@ -158,12 +123,15 @@ typedef struct tmrTimerQueueMessage
        } u;\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
+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
@@ -171,14 +139,9 @@ 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
-\r
-       PRIVILEGED_DATA static TaskHandle_t xTimerTaskHandle = NULL;\r
-\r
-#endif\r
-\r
-/*lint +e956 */\r
+/*lint -restore */\r
 \r
 /*-----------------------------------------------------------*/\r
 \r
@@ -188,7 +151,7 @@ PRIVILEGED_DATA static QueueHandle_t xTimerQueue = NULL;
        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, uint16_t *pusTimerTaskStackSize );\r
+       extern void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize );\r
 \r
 #endif\r
 \r
@@ -203,7 +166,7 @@ static void prvCheckForValidListAndQueue( void ) PRIVILEGED_FUNCTION;
  * task.  Other tasks communicate with the timer service task using the\r
  * xTimerQueue queue.\r
  */\r
-static void prvTimerTask( void *pvParameters ) PRIVILEGED_FUNCTION;\r
+static portTASK_FUNCTION_PROTO( prvTimerTask, pvParameters ) PRIVILEGED_FUNCTION;\r
 \r
 /*\r
  * Called by the timer service task to interpret and process a command it\r
@@ -219,7 +182,7 @@ static BaseType_t prvInsertTimerInActiveList( Timer_t * const pxTimer, const Tic
 \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
+ * auto-reload timer, then call its callback.\r
  */\r
 static void prvProcessExpiredTimer( const TickType_t xNextExpireTime, const TickType_t xTimeNow ) PRIVILEGED_FUNCTION;\r
 \r
@@ -249,15 +212,21 @@ static TickType_t prvGetNextExpireTime( BaseType_t * const pxListWasEmpty ) PRIV
  */\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
 BaseType_t xTimerCreateTimerTask( void )\r
 {\r
 BaseType_t xReturn = pdFAIL;\r
-StaticTask_t *pxTimerTaskTCBBuffer = NULL;\r
-StackType_t *pxTimerTaskStackBuffer = NULL;\r
-uint16_t usTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;\r
-\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
@@ -267,25 +236,36 @@ uint16_t usTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
 \r
        if( xTimerQueue != NULL )\r
        {\r
-\r
                #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
                {\r
-                       vApplicationGetTimerTaskMemory( &pxTimerTaskTCBBuffer, &pxTimerTaskStackBuffer, &usTimerTaskStackSize );\r
-               }\r
-               #endif /* configSUPPORT_STATIC_ALLOCATION */\r
-\r
-               #if ( INCLUDE_xTimerGetTimerDaemonTaskHandle == 1 )\r
-               {\r
-                       /* Create the timer task, storing its handle in xTimerTaskHandle so\r
-                       it can be returned by the xTimerGetTimerDaemonTaskHandle() function. */\r
-                       xReturn = xTaskGenericCreate( prvTimerTask, "Tmr Svc", usTimerTaskStackSize, NULL, ( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT, &xTimerTaskHandle, pxTimerTaskStackBuffer, pxTimerTaskTCBBuffer, NULL );\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 = xTaskGenericCreate( prvTimerTask, "Tmr Svc", usTimerTaskStackSize, NULL, ( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT, NULL, pxTimerTaskStackBuffer, pxTimerTaskTCBBuffer, 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
@@ -297,78 +277,104 @@ uint16_t usTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-TimerHandle_t xTimerGenericCreate( const char * const pcTimerName, const TickType_t xTimerPeriodInTicks, const UBaseType_t uxAutoReload, void * const pvTimerID, TimerCallbackFunction_t pxCallbackFunction, StaticTimer_t *pxTimerBuffer ) /*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
-       #if( ( configASSERT_DEFINED == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )\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
-               /* 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
+       Timer_t *pxNewTimer;\r
 \r
-       /* Allocate the timer structure. */\r
-       if( xTimerPeriodInTicks == ( TickType_t ) 0U )\r
-       {\r
-               pxNewTimer = NULL;\r
-       }\r
-       else\r
-       {\r
-               /* If the user passed in a statically allocated timer structure then use\r
-               it, otherwise allocate the structure dynamically. */\r
-               if( pxTimerBuffer == NULL )\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
-                       pxNewTimer = ( Timer_t * ) pvPortMalloc( sizeof( Timer_t ) );\r
+                       /* Status is thus far zero as the timer is not created statically\r
+                       and has not been started.  The auto-reload bit may get set in\r
+                       prvInitialiseNewTimer. */\r
+                       pxNewTimer->ucStatus = 0x00;\r
+                       prvInitialiseNewTimer( pcTimerName, xTimerPeriodInTicks, uxAutoReload, pvTimerID, pxCallbackFunction, pxNewTimer );\r
                }\r
-               else\r
+\r
+               return pxNewTimer;\r
+       }\r
+\r
+#endif /* configSUPPORT_DYNAMIC_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
+       Timer_t *pxNewTimer;\r
+\r
+               #if( configASSERT_DEFINED == 1 )\r
                {\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
+                       /* 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
+               #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
-                       /* 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
-\r
-                       #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
-                       {\r
-                               if( pxTimerBuffer == NULL )\r
-                               {\r
-                                       pxNewTimer->ucStaticallyAllocated = pdFALSE;\r
-                               }\r
-                               else\r
-                               {\r
-                                       pxNewTimer->ucStaticallyAllocated = pdTRUE;\r
-                               }\r
-                       }\r
-                       #endif /* configSUPPORT_STATIC_ALLOCATION */\r
+                       /* Timers can be created statically or dynamically so note this\r
+                       timer was created statically in case it is later deleted.  The\r
+                       auto-reload bit may get set in prvInitialiseNewTimer(). */\r
+                       pxNewTimer->ucStatus = tmrSTATUS_IS_STATICALLY_ALLOCATED;\r
 \r
-                       traceTIMER_CREATE( pxNewTimer );\r
-               }\r
-               else\r
-               {\r
-                       traceTIMER_CREATE_FAILED();\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 ( 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->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
@@ -386,7 +392,7 @@ DaemonTaskMessage_t 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 = ( Timer_t * ) xTimer;\r
+               xMessage.u.xTimerParameters.pxTimer = xTimer;\r
 \r
                if( xCommandID < tmrFIRST_FROM_ISR_COMMAND )\r
                {\r
@@ -415,22 +421,83 @@ 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
+TickType_t xTimerGetPeriod( TimerHandle_t xTimer )\r
+{\r
+Timer_t *pxTimer = xTimer;\r
 \r
-       TaskHandle_t xTimerGetTimerDaemonTaskHandle( void )\r
+       configASSERT( xTimer );\r
+       return pxTimer->xTimerPeriodInTicks;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vTimerSetReloadMode( TimerHandle_t xTimer, const UBaseType_t uxAutoReload )\r
+{\r
+Timer_t * pxTimer =  xTimer;\r
+\r
+       configASSERT( xTimer );\r
+       taskENTER_CRITICAL();\r
+       {\r
+               if( uxAutoReload != pdFALSE )\r
+               {\r
+                       pxTimer->ucStatus |= tmrSTATUS_IS_AUTORELOAD;\r
+               }\r
+               else\r
+               {\r
+                       pxTimer->ucStatus &= ~tmrSTATUS_IS_AUTORELOAD;\r
+               }\r
+       }\r
+       taskEXIT_CRITICAL();\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+UBaseType_t uxTimerGetReloadMode( TimerHandle_t xTimer )\r
+{\r
+Timer_t * pxTimer =  xTimer;\r
+UBaseType_t uxReturn;\r
+\r
+       configASSERT( xTimer );\r
+       taskENTER_CRITICAL();\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
+               if( ( pxTimer->ucStatus & tmrSTATUS_IS_AUTORELOAD ) == 0 )\r
+               {\r
+                       /* Not an auto-reload timer. */\r
+                       uxReturn = ( UBaseType_t ) pdFALSE;\r
+               }\r
+               else\r
+               {\r
+                       /* Is an auto-reload timer. */\r
+                       uxReturn = ( UBaseType_t ) pdTRUE;\r
+               }\r
        }\r
+       taskEXIT_CRITICAL();\r
 \r
-#endif\r
+       return uxReturn;\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
-const char * pcTimerGetTimerName( TimerHandle_t xTimer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\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
+Timer_t *pxTimer = xTimer;\r
 \r
        configASSERT( xTimer );\r
        return pxTimer->pcTimerName;\r
@@ -440,21 +507,21 @@ Timer_t *pxTimer = ( Timer_t * ) xTimer;
 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 );\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
        ( void ) uxListRemove( &( pxTimer->xTimerListItem ) );\r
        traceTIMER_EXPIRED( pxTimer );\r
 \r
-       /* If the timer is an auto reload timer then calculate the next\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 == ( UBaseType_t ) pdTRUE )\r
+       if( ( pxTimer->ucStatus & tmrSTATUS_IS_AUTORELOAD ) != 0 )\r
        {\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 ) == 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
@@ -469,6 +536,7 @@ Timer_t * const pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTi
        }\r
        else\r
        {\r
+               pxTimer->ucStatus &= ~tmrSTATUS_IS_ACTIVE;\r
                mtCOVERAGE_TEST_MARKER();\r
        }\r
 \r
@@ -477,7 +545,7 @@ Timer_t * const pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTi
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-static void prvTimerTask( void *pvParameters )\r
+static portTASK_FUNCTION( prvTimerTask, pvParameters )\r
 {\r
 TickType_t xNextExpireTime;\r
 BaseType_t xListWasEmpty;\r
@@ -633,7 +701,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( ( ( TickType_t ) ( 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
@@ -702,7 +770,7 @@ TickType_t xTimeNow;
                        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
@@ -725,19 +793,20 @@ TickType_t 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_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\r
                                                timer list.  Process it now. */\r
                                                pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer );\r
                                                traceTIMER_EXPIRED( pxTimer );\r
 \r
-                                               if( pxTimer->uxAutoReload == ( UBaseType_t ) pdTRUE )\r
+                                               if( ( pxTimer->ucStatus & tmrSTATUS_IS_AUTORELOAD ) != 0 )\r
                                                {\r
                                                        xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, NULL, tmrNO_DELAY );\r
                                                        configASSERT( xResult );\r
@@ -756,12 +825,13 @@ TickType_t xTimeNow;
 \r
                                case tmrCOMMAND_STOP :\r
                                case tmrCOMMAND_STOP_FROM_ISR :\r
-                                       /* The timer has already been removed from the active list.\r
-                                       There is nothing to do here. */\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
@@ -775,25 +845,29 @@ TickType_t xTimeNow;
                                        break;\r
 \r
                                case tmrCOMMAND_DELETE :\r
-                                       /* The timer has already been removed from the active list,\r
-                                       just free up the memory if the memory was dynamically\r
-                                       allocated. */\r
-                                       #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
+                                       #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )\r
                                        {\r
-                                               if( pxTimer->ucStaticallyAllocated == ( uint8_t ) pdFALSE )\r
+                                               /* The timer has already been removed from the active list,\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
-                                                       mtCOVERAGE_TEST_MARKER();\r
+                                                       pxTimer->ucStatus &= ~tmrSTATUS_IS_ACTIVE;\r
                                                }\r
                                        }\r
                                        #else\r
                                        {\r
-                                               vPortFree( pxTimer );\r
+                                               /* If dynamic allocation is not enabled, the memory\r
+                                               could not have been dynamically allocated. So there is\r
+                                               no need to free the memory - just mark the timer as\r
+                                               "not active". */\r
+                                               pxTimer->ucStatus &= ~tmrSTATUS_IS_ACTIVE;\r
                                        }\r
-                                       #endif /* configSUPPORT_STATIC_ALLOCATION */\r
+                                       #endif /* configSUPPORT_DYNAMIC_ALLOCATION */\r
                                        break;\r
 \r
                                default :\r
@@ -821,7 +895,7 @@ BaseType_t xResult;
                xNextExpireTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxCurrentTimerList );\r
 \r
                /* Remove the timer from the list. */\r
-               pxTimer = ( Timer_t * ) 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
@@ -830,7 +904,7 @@ BaseType_t xResult;
                have not yet been switched. */\r
                pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer );\r
 \r
-               if( pxTimer->uxAutoReload == ( UBaseType_t ) 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
@@ -877,8 +951,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; /*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
@@ -904,28 +991,32 @@ static void prvCheckForValidListAndQueue( void )
 \r
 BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer )\r
 {\r
-BaseType_t xTimerIsInActiveList;\r
-Timer_t *pxTimer = ( Timer_t * ) 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 = ( BaseType_t ) !( 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 = ( Timer_t * ) xTimer;\r
+Timer_t * const pxTimer = xTimer;\r
 void *pvReturn;\r
 \r
        configASSERT( xTimer );\r
@@ -942,7 +1033,7 @@ void *pvReturn;
 \r
 void vTimerSetTimerID( TimerHandle_t xTimer, void *pvNewID )\r
 {\r
-Timer_t * const pxTimer = ( Timer_t * ) xTimer;\r
+Timer_t * const pxTimer = xTimer;\r
 \r
        configASSERT( xTimer );\r
 \r
@@ -1007,6 +1098,26 @@ Timer_t * const pxTimer = ( Timer_t * ) xTimer;
 #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
 to include software timer functionality.  If you want to include software timer\r
 functionality then ensure configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */\r