Update the method used to detect if a timer is active. Previously the timer was deemed to be inactive if it was not referenced from a list. However, when a timer is updated it is temporarily removed from, then re-added to a list, so now the timer's active status is stored separately.

This commit is contained in:
Richard Barry 2018-10-24 21:37:59 +00:00
parent 6fab2b9e0d
commit 55ff89373a
2 changed files with 37 additions and 58 deletions

View File

@ -1142,16 +1142,12 @@ typedef struct xSTATIC_TIMER
void *pvDummy1;
StaticListItem_t xDummy2;
TickType_t xDummy3;
UBaseType_t uxDummy4;
void *pvDummy5;
TaskFunction_t pvDummy6;
#if( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxDummy7;
#endif
#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
uint8_t ucDummy8;
#endif
} StaticTimer_t;

View File

@ -64,22 +64,23 @@ defining trmTIMER_SERVICE_TASK_NAME in FreeRTOSConfig.h. */
#define configTIMER_SERVICE_TASK_NAME "Tmr Svc"
#endif
/* Bit definitions used in the ucStatus member of a timer structure. */
#define tmrSTATUS_IS_ACTIVE ( ( uint8_t ) 0x01 )
#define tmrSTATUS_IS_STATICALLY_ALLOCATED ( ( uint8_t ) 0x02 )
#define tmrSTATUS_IS_AUTORELOAD ( ( uint8_t ) 0x04 )
/* The definition of the timers themselves. */
typedef struct tmrTimerControl /* The old naming convention is used to prevent breaking kernel aware debuggers. */
{
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. */
ListItem_t xTimerListItem; /*<< Standard linked list item as used by all kernel features for event management. */
TickType_t xTimerPeriodInTicks;/*<< How quickly and often the timer expires. */
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. */
void *pvTimerID; /*<< An ID to identify the timer. This allows the timer to be identified when the same callback is used for multiple timers. */
TimerCallbackFunction_t pxCallbackFunction; /*<< The function that will be called when the timer expires. */
#if( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxTimerNumber; /*<< An ID assigned by trace tools such as FreeRTOS+Trace */
#endif
#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
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. */
#endif
uint8_t ucStatus; /*<< Holds bits to say if the timer was statically allocated or not, and if it is active or not. */
} xTIMER;
/* The old xTIMER name is maintained above then typedefed to the new Timer_t
@ -290,16 +291,11 @@ BaseType_t xReturn = pdFAIL;
if( pxNewTimer != NULL )
{
/* Status is thus far zero as the timer is not created statically
and has not been started. The autoreload bit may get set in
prvInitialiseNewTimer. */
pxNewTimer->ucStatus = 0x00;
prvInitialiseNewTimer( pcTimerName, xTimerPeriodInTicks, uxAutoReload, pvTimerID, pxCallbackFunction, pxNewTimer );
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
{
/* Timers can be created statically or dynamically, so note this
timer was created dynamically in case the timer is later
deleted. */
pxNewTimer->ucStaticallyAllocated = pdFALSE;
}
#endif /* configSUPPORT_STATIC_ALLOCATION */
}
return pxNewTimer;
@ -335,16 +331,13 @@ BaseType_t xReturn = pdFAIL;
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. */
if( pxNewTimer != NULL )
{
prvInitialiseNewTimer( pcTimerName, xTimerPeriodInTicks, uxAutoReload, pvTimerID, pxCallbackFunction, pxNewTimer );
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
{
/* Timers can be created statically or dynamically so note this
timer was created statically in case it is later deleted. */
pxNewTimer->ucStaticallyAllocated = pdTRUE;
}
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
timer was created statically in case it is later deleted. The
autoreload bit may get set in prvInitialiseNewTimer(). */
pxNewTimer->ucStatus = tmrSTATUS_IS_STATICALLY_ALLOCATED;
prvInitialiseNewTimer( pcTimerName, xTimerPeriodInTicks, uxAutoReload, pvTimerID, pxCallbackFunction, pxNewTimer );
}
return pxNewTimer;
@ -373,10 +366,13 @@ static void prvInitialiseNewTimer( const char * const pcTimerName, /*lint !e97
parameters. */
pxNewTimer->pcTimerName = pcTimerName;
pxNewTimer->xTimerPeriodInTicks = xTimerPeriodInTicks;
pxNewTimer->uxAutoReload = uxAutoReload;
pxNewTimer->pvTimerID = pvTimerID;
pxNewTimer->pxCallbackFunction = pxCallbackFunction;
vListInitialiseItem( &( pxNewTimer->xTimerListItem ) );
if( uxAutoReload != pdFALSE )
{
pxNewTimer->ucStatus |= tmrSTATUS_IS_AUTORELOAD;
}
traceTIMER_CREATE( pxNewTimer );
}
}
@ -475,7 +471,7 @@ Timer_t * const pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTi
/* If the timer is an auto reload timer then calculate the next
expiry time and re-insert the timer in the list of active timers. */
if( pxTimer->uxAutoReload == ( UBaseType_t ) pdTRUE )
if( ( pxTimer->ucStatus & tmrSTATUS_IS_AUTORELOAD ) != 0 )
{
/* The timer is inserted into a list using a time relative to anything
other than the current time. It will therefore be inserted into the
@ -495,6 +491,7 @@ Timer_t * const pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTi
}
else
{
pxTimer->ucStatus &= ~tmrSTATUS_IS_ACTIVE;
mtCOVERAGE_TEST_MARKER();
}
@ -756,6 +753,7 @@ TickType_t xTimeNow;
case tmrCOMMAND_RESET_FROM_ISR :
case tmrCOMMAND_START_DONT_TRACE :
/* Start or restart a timer. */
pxTimer->ucStatus |= tmrSTATUS_IS_ACTIVE;
if( prvInsertTimerInActiveList( pxTimer, xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, xTimeNow, xMessage.u.xTimerParameters.xMessageValue ) != pdFALSE )
{
/* The timer expired before it was added to the active
@ -763,7 +761,7 @@ TickType_t xTimeNow;
pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer );
traceTIMER_EXPIRED( pxTimer );
if( pxTimer->uxAutoReload == ( UBaseType_t ) pdTRUE )
if( ( pxTimer->ucStatus & tmrSTATUS_IS_AUTORELOAD ) != 0 )
{
xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, NULL, tmrNO_DELAY );
configASSERT( xResult );
@ -782,12 +780,13 @@ TickType_t xTimeNow;
case tmrCOMMAND_STOP :
case tmrCOMMAND_STOP_FROM_ISR :
/* The timer has already been removed from the active list.
There is nothing to do here. */
/* The timer has already been removed from the active list. */
pxTimer->ucStatus &= ~tmrSTATUS_IS_ACTIVE;
break;
case tmrCOMMAND_CHANGE_PERIOD :
case tmrCOMMAND_CHANGE_PERIOD_FROM_ISR :
pxTimer->ucStatus |= tmrSTATUS_IS_ACTIVE;
pxTimer->xTimerPeriodInTicks = xMessage.u.xTimerParameters.xMessageValue;
configASSERT( ( pxTimer->xTimerPeriodInTicks > 0 ) );
@ -804,27 +803,14 @@ TickType_t xTimeNow;
/* The timer has already been removed from the active list,
just free up the memory if the memory was dynamically
allocated. */
#if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) )
{
/* The timer can only have been allocated dynamically -
free it again. */
vPortFree( pxTimer );
}
#elif( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
{
/* The timer could have been allocated statically or
dynamically, so check before attempting to free the
memory. */
if( pxTimer->ucStaticallyAllocated == ( uint8_t ) pdFALSE )
if( ( pxTimer->ucStatus & tmrSTATUS_IS_STATICALLY_ALLOCATED ) == ( uint8_t ) 0 )
{
vPortFree( pxTimer );
}
else
{
mtCOVERAGE_TEST_MARKER();
pxTimer->ucStatus &= ~tmrSTATUS_IS_ACTIVE;
}
}
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
break;
default :
@ -861,7 +847,7 @@ BaseType_t xResult;
have not yet been switched. */
pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer );
if( pxTimer->uxAutoReload == ( UBaseType_t ) pdTRUE )
if( ( pxTimer->ucStatus & tmrSTATUS_IS_AUTORELOAD ) != 0 )
{
/* Calculate the reload value, and if the reload value results in
the timer going into the same timer list then it has already expired
@ -948,7 +934,7 @@ static void prvCheckForValidListAndQueue( void )
BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer )
{
BaseType_t xTimerIsInActiveList;
BaseType_t xReturn;
Timer_t *pxTimer = xTimer;
configASSERT( xTimer );
@ -956,21 +942,18 @@ Timer_t *pxTimer = xTimer;
/* Is the timer in the list of active timers? */
taskENTER_CRITICAL();
{
/* Checking to see if it is in the NULL list in effect checks to see if
it is referenced from either the current or the overflow timer lists in
one go, but the logic has to be reversed, hence the '!'. */
if( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) == pdTRUE )
if( ( pxTimer->ucStatus & tmrSTATUS_IS_ACTIVE ) == 0 )
{
xTimerIsInActiveList = pdFALSE;
xReturn = pdFALSE;
}
else
{
xTimerIsInActiveList = pdTRUE;
xReturn = pdTRUE;
}
}
taskEXIT_CRITICAL();
return xTimerIsInActiveList;
return xReturn;
} /*lint !e818 Can't be pointer to const due to the typedef. */
/*-----------------------------------------------------------*/