]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Source/timers.c
Added uxTimerGetReloadMode() API function.
[freertos] / FreeRTOS / Source / timers.c
index 5ab04789eaa443228a2b42b70657e405ea52f907..12a2f4e9b6a6213d1befd75a5a3fa61d6e076390 100644 (file)
@@ -1,6 +1,6 @@
 /*\r
- * FreeRTOS Kernel V10.1.1\r
- * Copyright (C) 2018 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\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
@@ -64,22 +64,23 @@ defining trmTIMER_SERVICE_TASK_NAME in FreeRTOSConfig.h. */
        #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 /* Using old naming convention so as not to break kernel aware debuggers. */\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 ) && ( 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
+       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
@@ -127,10 +128,10 @@ which static variables must be declared volatile. */
 \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.  NOTE:  xActiveTimerList1\r
-and xActiveTimerList2 could move to be function scope, however doing so breaks\r
-kernel aware debuggers, and debug scenarios that require the static qualifier\r
-to be removed. */\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
@@ -165,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
@@ -181,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
@@ -290,22 +291,17 @@ BaseType_t xReturn = pdFAIL;
 \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 auto-reload bit may get set in\r
+                       prvInitialiseNewTimer. */\r
+                       pxNewTimer->ucStatus = 0x00;\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
 \r
                return pxNewTimer;\r
        }\r
 \r
-#endif /* configSUPPORT_STATIC_ALLOCATION */\r
+#endif /* configSUPPORT_DYNAMIC_ALLOCATION */\r
 /*-----------------------------------------------------------*/\r
 \r
 #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
@@ -336,15 +332,12 @@ BaseType_t xReturn = pdFAIL;
 \r
                if( pxNewTimer != NULL )\r
                {\r
-                       prvInitialiseNewTimer( pcTimerName, xTimerPeriodInTicks, uxAutoReload, pvTimerID, pxCallbackFunction, pxNewTimer );\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
-                       #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
+                       prvInitialiseNewTimer( pcTimerName, xTimerPeriodInTicks, uxAutoReload, pvTimerID, pxCallbackFunction, pxNewTimer );\r
                }\r
 \r
                return pxNewTimer;\r
@@ -373,10 +366,13 @@ static void prvInitialiseNewTimer(        const char * const pcTimerName,                 /*lint !e97
                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
+               if( uxAutoReload != pdFALSE )\r
+               {\r
+                       pxNewTimer->ucStatus |= tmrSTATUS_IS_AUTORELOAD;\r
+               }\r
                traceTIMER_CREATE( pxNewTimer );\r
        }\r
 }\r
@@ -443,6 +439,51 @@ Timer_t *pxTimer = xTimer;
 }\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( ( 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
+       return uxReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
 TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer )\r
 {\r
 Timer_t * pxTimer =  xTimer;\r
@@ -473,9 +514,9 @@ Timer_t * const pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTi
        ( 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
@@ -495,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
@@ -503,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
@@ -751,11 +793,12 @@ 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
+                                       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
@@ -763,7 +806,7 @@ TickType_t xTimeNow;
                                                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
@@ -782,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
@@ -801,29 +845,28 @@ 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_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) )\r
+                                       #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )\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
+                                               /* 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
+                                               /* 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_DYNAMIC_ALLOCATION */\r
                                        break;\r
 \r
@@ -861,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
@@ -948,7 +991,7 @@ static void prvCheckForValidListAndQueue( void )
 \r
 BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer )\r
 {\r
-BaseType_t xTimerIsInActiveList;\r
+BaseType_t xReturn;\r
 Timer_t *pxTimer = xTimer;\r
 \r
        configASSERT( xTimer );\r
@@ -956,21 +999,18 @@ Timer_t *pxTimer = xTimer;
        /* 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
-               if( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) == pdTRUE )\r
+               if( ( pxTimer->ucStatus & tmrSTATUS_IS_ACTIVE ) == 0 )\r
                {\r
-                       xTimerIsInActiveList = pdFALSE;\r
+                       xReturn = pdFALSE;\r
                }\r
                else\r
                {\r
-                       xTimerIsInActiveList = pdTRUE;\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