FreeRTOS: update to v10.2.0

This commit is contained in:
Our Air Quality 2019-04-05 21:45:00 +11:00
parent d0373af5c0
commit bceb096e69
27 changed files with 1155 additions and 711 deletions

View file

@ -1,6 +1,6 @@
/*
* FreeRTOS Kernel V10.0.1
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* FreeRTOS Kernel V10.2.0
* Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
@ -42,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.
#endif
/* Lint e961 and e750 are suppressed as a MISRA exception justified because the
MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the
header files above, but not in this file, in order to generate the correct
privileged Vs unprivileged linkage and placement. */
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */
/* Lint e9021, e961 and e750 are suppressed as a MISRA exception justified
because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined
for the header files above, but not in this file, in order to generate the
correct privileged Vs unprivileged linkage and placement. */
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e9021 !e961 !e750. */
/* This entire source file will be skipped if the application is not configured
@ -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
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
@ -127,7 +128,10 @@ which static variables must be declared volatile. */
/* The list in which active timers are stored. Timers are referenced in expire
time order, with the nearest expiry time at the front of the list. Only the
timer service task is allowed to access these lists. */
timer service task is allowed to access these lists.
xActiveTimerList1 and xActiveTimerList2 could be at function scope but that
breaks some kernel aware debuggers, and debuggers that reply on removing the
static qualifier. */
PRIVILEGED_DATA static List_t xActiveTimerList1;
PRIVILEGED_DATA static List_t xActiveTimerList2;
PRIVILEGED_DATA static List_t *pxCurrentTimerList;
@ -162,7 +166,7 @@ static void prvCheckForValidListAndQueue( void ) PRIVILEGED_FUNCTION;
* task. Other tasks communicate with the timer service task using the
* xTimerQueue queue.
*/
static void prvTimerTask( void *pvParameters ) PRIVILEGED_FUNCTION;
static portTASK_FUNCTION_PROTO( prvTimerTask, pvParameters ) PRIVILEGED_FUNCTION;
/*
* Called by the timer service task to interpret and process a command it
@ -283,26 +287,21 @@ BaseType_t xReturn = pdFAIL;
{
Timer_t *pxNewTimer;
pxNewTimer = ( Timer_t * ) pvPortMalloc( sizeof( Timer_t ) );
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. */
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;
}
#endif /* configSUPPORT_STATIC_ALLOCATION */
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
/*-----------------------------------------------------------*/
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
@ -323,24 +322,22 @@ BaseType_t xReturn = pdFAIL;
structure. */
volatile size_t xSize = sizeof( StaticTimer_t );
configASSERT( xSize == sizeof( Timer_t ) );
( void ) xSize; /* Keeps lint quiet when configASSERT() is not defined. */
}
#endif /* configASSERT_DEFINED */
/* A pointer to a StaticTimer_t structure MUST be provided, use it. */
configASSERT( pxTimerBuffer );
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. */
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 );
/* Timers can be created statically or dynamically so note this
timer was created statically in case it is later deleted. The
autoreload bit may get set in prvInitialiseNewTimer(). */
pxNewTimer->ucStatus = tmrSTATUS_IS_STATICALLY_ALLOCATED;
#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 */
prvInitialiseNewTimer( pcTimerName, xTimerPeriodInTicks, uxAutoReload, pvTimerID, pxCallbackFunction, pxNewTimer );
}
return pxNewTimer;
@ -369,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 );
}
}
@ -392,7 +392,7 @@ DaemonTaskMessage_t xMessage;
/* Send a command to the timer service task to start the xTimer timer. */
xMessage.xMessageID = xCommandID;
xMessage.u.xTimerParameters.xMessageValue = xOptionalValue;
xMessage.u.xTimerParameters.pxTimer = ( Timer_t * ) xTimer;
xMessage.u.xTimerParameters.pxTimer = xTimer;
if( xCommandID < tmrFIRST_FROM_ISR_COMMAND )
{
@ -432,16 +432,36 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void )
TickType_t xTimerGetPeriod( TimerHandle_t xTimer )
{
Timer_t *pxTimer = ( Timer_t * ) xTimer;
Timer_t *pxTimer = xTimer;
configASSERT( xTimer );
return pxTimer->xTimerPeriodInTicks;
}
/*-----------------------------------------------------------*/
void vTimerSetReloadMode( TimerHandle_t xTimer, const UBaseType_t uxAutoReload )
{
Timer_t * pxTimer = xTimer;
configASSERT( xTimer );
taskENTER_CRITICAL();
{
if( uxAutoReload != pdFALSE )
{
pxTimer->ucStatus |= tmrSTATUS_IS_AUTORELOAD;
}
else
{
pxTimer->ucStatus &= ~tmrSTATUS_IS_AUTORELOAD;
}
}
taskEXIT_CRITICAL();
}
/*-----------------------------------------------------------*/
TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer )
{
Timer_t * pxTimer = ( Timer_t * ) xTimer;
Timer_t * pxTimer = xTimer;
TickType_t xReturn;
configASSERT( xTimer );
@ -452,7 +472,7 @@ TickType_t xReturn;
const char * pcTimerGetName( TimerHandle_t xTimer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
{
Timer_t *pxTimer = ( Timer_t * ) xTimer;
Timer_t *pxTimer = xTimer;
configASSERT( xTimer );
return pxTimer->pcTimerName;
@ -462,7 +482,7 @@ Timer_t *pxTimer = ( Timer_t * ) xTimer;
static void prvProcessExpiredTimer( const TickType_t xNextExpireTime, const TickType_t xTimeNow )
{
BaseType_t xResult;
Timer_t * const pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList );
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. */
/* Remove the timer from the list of active timers. A check has already
been performed to ensure the list is not empty. */
@ -471,7 +491,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
@ -491,6 +511,7 @@ Timer_t * const pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTi
}
else
{
pxTimer->ucStatus &= ~tmrSTATUS_IS_ACTIVE;
mtCOVERAGE_TEST_MARKER();
}
@ -499,7 +520,7 @@ Timer_t * const pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTi
}
/*-----------------------------------------------------------*/
static void prvTimerTask( void *pvParameters )
static portTASK_FUNCTION( prvTimerTask, pvParameters )
{
TickType_t xNextExpireTime;
BaseType_t xListWasEmpty;
@ -747,11 +768,12 @@ TickType_t xTimeNow;
switch( xMessage.xMessageID )
{
case tmrCOMMAND_START :
case tmrCOMMAND_START_FROM_ISR :
case tmrCOMMAND_RESET :
case tmrCOMMAND_RESET_FROM_ISR :
case tmrCOMMAND_START_FROM_ISR :
case tmrCOMMAND_RESET :
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
@ -759,7 +781,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 );
@ -778,12 +800,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 ) );
@ -797,29 +820,28 @@ TickType_t xTimeNow;
break;
case tmrCOMMAND_DELETE :
/* 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 ) )
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
{
/* 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 )
/* The timer has already been removed from the active list,
just free up the memory if the memory was dynamically
allocated. */
if( ( pxTimer->ucStatus & tmrSTATUS_IS_STATICALLY_ALLOCATED ) == ( uint8_t ) 0 )
{
vPortFree( pxTimer );
}
else
{
mtCOVERAGE_TEST_MARKER();
pxTimer->ucStatus &= ~tmrSTATUS_IS_ACTIVE;
}
}
#else
{
/* If dynamic allocation is not enabled, the memory
could not have been dynamically allocated. So there is
no need to free the memory - just mark the timer as
"not active". */
pxTimer->ucStatus &= ~tmrSTATUS_IS_ACTIVE;
}
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
break;
@ -848,7 +870,7 @@ BaseType_t xResult;
xNextExpireTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxCurrentTimerList );
/* Remove the timer from the list. */
pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList );
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. */
( void ) uxListRemove( &( pxTimer->xTimerListItem ) );
traceTIMER_EXPIRED( pxTimer );
@ -857,7 +879,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
@ -944,28 +966,32 @@ static void prvCheckForValidListAndQueue( void )
BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer )
{
BaseType_t xTimerIsInActiveList;
Timer_t *pxTimer = ( Timer_t * ) xTimer;
BaseType_t xReturn;
Timer_t *pxTimer = xTimer;
configASSERT( 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 '!'. */
xTimerIsInActiveList = ( BaseType_t ) !( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) ); /*lint !e961. Cast is only redundant when NULL is passed into the macro. */
if( ( pxTimer->ucStatus & tmrSTATUS_IS_ACTIVE ) == 0 )
{
xReturn = pdFALSE;
}
else
{
xReturn = pdTRUE;
}
}
taskEXIT_CRITICAL();
return xTimerIsInActiveList;
return xReturn;
} /*lint !e818 Can't be pointer to const due to the typedef. */
/*-----------------------------------------------------------*/
void *pvTimerGetTimerID( const TimerHandle_t xTimer )
{
Timer_t * const pxTimer = ( Timer_t * ) xTimer;
Timer_t * const pxTimer = xTimer;
void *pvReturn;
configASSERT( xTimer );
@ -982,7 +1008,7 @@ void *pvReturn;
void vTimerSetTimerID( TimerHandle_t xTimer, void *pvNewID )
{
Timer_t * const pxTimer = ( Timer_t * ) xTimer;
Timer_t * const pxTimer = xTimer;
configASSERT( xTimer );