Provide the ability to create event groups and software timers using pre statically allocated memory - now all RTOS objects can be created using statically allocated memory.

Rename StaticTCB_t to StaticTask_t.
This commit is contained in:
Richard Barry 2016-01-21 14:10:04 +00:00
parent 68fced741d
commit f82953554d
12 changed files with 534 additions and 109 deletions

View file

@ -111,6 +111,9 @@ typedef struct xEventGroupDefinition
UBaseType_t uxEventGroupNumber;
#endif
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
uint8_t ucStaticallyAllocated;
#endif
} EventGroup_t;
/*-----------------------------------------------------------*/
@ -127,15 +130,36 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, co
/*-----------------------------------------------------------*/
EventGroupHandle_t xEventGroupCreate( void )
EventGroupHandle_t xEventGroupGenericCreate( StaticEventGroup_t *pxStaticEventGroup )
{
EventGroup_t *pxEventBits;
pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) );
if( pxStaticEventGroup == NULL )
{
/* The user has not provided a statically allocated event group, so
create on dynamically. */
pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) );
}
else
{
/* The user has provided a statically allocated event group - use it. */
pxEventBits = ( EventGroup_t * ) pxStaticEventGroup;
}
if( pxEventBits != NULL )
{
pxEventBits->uxEventBits = 0;
vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
if( pxStaticEventGroup == NULL )
{
pxEventBits->ucStaticallyAllocated = pdFALSE;
}
else
{
pxEventBits->ucStaticallyAllocated = pdTRUE;
}
traceEVENT_GROUP_CREATE( pxEventBits );
}
else
@ -580,7 +604,11 @@ const List_t *pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits );
( void ) xTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET );
}
vPortFree( pxEventBits );
/* Only free the memory if it was allocated dynamically. */
if( pxEventBits->ucStaticallyAllocated == pdFALSE )
{
vPortFree( pxEventBits );
}
}
( void ) xTaskResumeAll();
}

View file

@ -876,12 +876,17 @@ typedef enum
} eDummy;
/*
* In line with software engineering best practice, FreeRTOS implements a strict
* data hiding policy, so the real task control block (TCB) structure is not
* accessible to the application code. However, if the application writer wants
* to statically allocate a TCB then the size of the TCB needs to be know. The
* dummy TCB structure below is used for this purpose. Its size will allows
* match the size of the real TCB, no matter what the FreeRTOSConfig.h settings.
* In line with software engineering best practice, especially when supplying a
* library that is likely to change in future versions, FreeRTOS implements a
* strict data hiding policy. This means the Task structure used internally by
* FreeRTOS is not accessible to application code. However, if the application
* writer wants to statically allocate the memory required to create a task then
* the size of the task object needs to be know. The StaticTask_t structure
* below is provided for this purpose. Its sizes and alignment requirements are
* guaranteed to match those of the genuine structure, no matter which
* architecture is being used, and no matter how the values in FreeRTOSConfig.h
* are set. Its contents are somewhat obfuscated in the hope users will
* recognise that it would be unwise to make direct use of the structure members.
*/
typedef struct xSTATIC_TCB
{
@ -925,16 +930,21 @@ typedef struct xSTATIC_TCB
uint8_t uxDummy20;
#endif
} StaticTCB_t;
} StaticTask_t;
/*
* In line with software engineering best practice, FreeRTOS implements a strict
* data hiding policy, so the queue structure is not accessible to the
* application code. However, if the application writer wants to statically
* allocate a queue (or one of the other objects that uses a queue as its base
* structure) then the size of the queue needs to be know. The dummy queue
* structure below is used for this purpose. Its size will allows match the
* size of the real queue, no matter what the FreeRTOSConfig.h settings.
* In line with software engineering best practice, especially when supplying a
* library that is likely to change in future versions, FreeRTOS implements a
* strict data hiding policy. This means the Queue structure used internally by
* FreeRTOS is not accessible to application code. However, if the application
* writer wants to statically allocate the memory required to create a queue
* then the size of the queue object needs to be know. The StaticQueue_t
* structure below is provided for this purpose. Its sizes and alignment
* requirements are guaranteed to match those of the genuine structure, no
* matter which architecture is being used, and no matter how the values in
* FreeRTOSConfig.h are set. Its contents are somewhat obfuscated in the hope
* users will recognise that it would be unwise to make direct use of the
* structure members.
*/
typedef struct xSTATIC_QUEUE
{
@ -963,9 +973,67 @@ typedef struct xSTATIC_QUEUE
#endif
} StaticQueue_t;
typedef StaticQueue_t StaticSemaphore_t;
/*
* In line with software engineering best practice, especially when supplying a
* library that is likely to change in future versions, FreeRTOS implements a
* strict data hiding policy. This means the event group structure used
* internally by FreeRTOS is not accessible to application code. However, if
* the application writer wants to statically allocate the memory required to
* create an event group then the size of the event group object needs to be
* know. The StaticEventGroup_t structure below is provided for this purpose.
* Its sizes and alignment requirements are guaranteed to match those of the
* genuine structure, no matter which architecture is being used, and no matter
* how the values in FreeRTOSConfig.h are set. Its contents are somewhat
* obfuscated in the hope users will recognise that it would be unwise to make
* direct use of the structure members.
*/
typedef struct xSTATIC_EVENT_GROUP
{
TickType_t xDummy1;
StaticList_t xDummy2;
#if( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxDummy3;
#endif
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
uint8_t ucStaticallyAllocated;
#endif
} StaticEventGroup_t;
/*
* In line with software engineering best practice, especially when supplying a
* library that is likely to change in future versions, FreeRTOS implements a
* strict data hiding policy. This means the software timer structure used
* internally by FreeRTOS is not accessible to application code. However, if
* the application writer wants to statically allocate the memory required to
* create a software timer then the size of the queue object needs to be know.
* The StaticTimer_t structure below is provided for this purpose. Its sizes
* and alignment requirements are guaranteed to match those of the genuine
* structure, no matter which architecture is being used, and no matter how the
* values in FreeRTOSConfig.h are set. Its contents are somewhat obfuscated in
* the hope users will recognise that it would be unwise to make direct use of
* the structure members.
*/
typedef struct xSTATIC_TIMER
{
void *pvDummy1;
StaticListItem_t xDummy2;
TickType_t xDummy3;
UBaseType_t uxDummy4;
void *pvDummy5[ 2 ];
#if( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxDummy6;
#endif
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
uint8_t ucStaticallyAllocated;
#endif
} StaticTimer_t;
#ifdef __cplusplus
}

View file

@ -121,10 +121,10 @@ extern "C" {
*/
typedef void * EventGroupHandle_t;
/*
/*
* The type that holds event bits always matches TickType_t - therefore the
* number of bits it holds is set by configUSE_16_BIT_TICKS (16 bits if set to 1,
* 32 bits if set to 0.
* 32 bits if set to 0.
*
* \defgroup EventBits_t EventBits_t
* \ingroup EventGroup
@ -173,7 +173,11 @@ typedef TickType_t EventBits_t;
* \defgroup xEventGroupCreate xEventGroupCreate
* \ingroup EventGroup
*/
EventGroupHandle_t xEventGroupCreate( void ) PRIVILEGED_FUNCTION;
#define xEventGroupCreate() xEventGroupGenericCreate( NULL )
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
#define xEventGroupCreateStatic( pxStaticEventGroup ) xEventGroupGenericCreate( ( pxStaticEventGroup ) )
#endif
/**
* event_groups.h
@ -340,8 +344,8 @@ EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBit
* while interrupts are disabled, so protects event groups that are accessed
* from tasks by suspending the scheduler rather than disabling interrupts. As
* a result event groups cannot be accessed directly from an interrupt service
* routine. Therefore xEventGroupClearBitsFromISR() sends a message to the
* timer task to have the clear operation performed in the context of the timer
* routine. Therefore xEventGroupClearBitsFromISR() sends a message to the
* timer task to have the clear operation performed in the context of the timer
* task.
*
* @param xEventGroup The event group in which the bits are to be cleared.
@ -350,8 +354,8 @@ EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBit
* For example, to clear bit 3 only, set uxBitsToClear to 0x08. To clear bit 3
* and bit 0 set uxBitsToClear to 0x09.
*
* @return If the request to execute the function was posted successfully then
* pdPASS is returned, otherwise pdFALSE is returned. pdFALSE will be returned
* @return If the request to execute the function was posted successfully then
* pdPASS is returned, otherwise pdFALSE is returned. pdFALSE will be returned
* if the timer service queue was full.
*
* Example usage:
@ -491,8 +495,8 @@ EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_
* *pxHigherPriorityTaskWoken must be initialised to pdFALSE. See the
* example code below.
*
* @return If the request to execute the function was posted successfully then
* pdPASS is returned, otherwise pdFALSE is returned. pdFALSE will be returned
* @return If the request to execute the function was posted successfully then
* pdPASS is returned, otherwise pdFALSE is returned. pdFALSE will be returned
* if the timer service queue was full.
*
* Example usage:
@ -521,8 +525,8 @@ EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_
if( xResult == pdPASS )
{
// If xHigherPriorityTaskWoken is now set to pdTRUE then a context
// switch should be requested. The macro used is port specific and
// will be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() -
// switch should be requested. The macro used is port specific and
// will be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() -
// refer to the documentation page for the port being used.
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
@ -717,6 +721,12 @@ void vEventGroupDelete( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION;
void vEventGroupSetBitsCallback( void *pvEventGroup, const uint32_t ulBitsToSet ) PRIVILEGED_FUNCTION;
void vEventGroupClearBitsCallback( void *pvEventGroup, const uint32_t ulBitsToClear ) PRIVILEGED_FUNCTION;
/*
* Generic version of the event group creation function, which is in turn called
* by the event group creation macros.
*/
EventGroupHandle_t xEventGroupGenericCreate( StaticEventGroup_t *pxStaticEventGroup );
#if (configUSE_TRACE_FACILITY == 1)
UBaseType_t uxEventGroupGetNumber( void* xEventGroup ) PRIVILEGED_FUNCTION;
#endif

View file

@ -174,7 +174,7 @@ typedef void * QueueSetMemberHandle_t;
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
#define xQueueCreateStatic( uxQueueLength, uxItemSize, pucQueueStorage, pxStaticQueue ) xQueueGenericCreate( uxQueueLength, uxItemSize, pucQueueStorage, pxStaticQueue, queueQUEUE_TYPE_BASE )
#endif
#endif /* configSUPPORT_STATIC_ALLOCATION */
/**
* queue. h

View file

@ -191,7 +191,10 @@ typedef QueueHandle_t SemaphoreHandle_t;
* \ingroup Semaphores
*/
#define xSemaphoreCreateBinary() xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, NULL, NULL, queueQUEUE_TYPE_BINARY_SEMAPHORE )
#define xSemaphoreCreateBinaryStatic( pxStaticQueue ) xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, NULL, pxStaticQueue, queueQUEUE_TYPE_BINARY_SEMAPHORE )
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
#define xSemaphoreCreateBinaryStatic( pxStaticQueue ) xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, NULL, pxStaticQueue, queueQUEUE_TYPE_BINARY_SEMAPHORE )
#endif /* configSUPPORT_STATIC_ALLOCATION */
/**
* semphr. h
@ -700,7 +703,10 @@ typedef QueueHandle_t SemaphoreHandle_t;
* \ingroup Semaphores
*/
#define xSemaphoreCreateMutex() xQueueCreateMutex( queueQUEUE_TYPE_MUTEX, NULL )
#define xSemaphoreCreateMutexStatic( pxStaticQueue ) xQueueCreateMutex( queueQUEUE_TYPE_MUTEX, ( pxStaticQueue ) )
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
#define xSemaphoreCreateMutexStatic( pxStaticQueue ) xQueueCreateMutex( queueQUEUE_TYPE_MUTEX, ( pxStaticQueue ) )
#endif /* configSUPPORT_STATIC_ALLOCATION */
/**
@ -756,7 +762,10 @@ typedef QueueHandle_t SemaphoreHandle_t;
* \ingroup Semaphores
*/
#define xSemaphoreCreateRecursiveMutex() xQueueCreateMutex( queueQUEUE_TYPE_RECURSIVE_MUTEX, NULL )
#define xSemaphoreCreateRecursiveMutexStatic( pxStaticSemaphore ) xQueueCreateMutex( queueQUEUE_TYPE_RECURSIVE_MUTEX, pxStaticSemaphore )
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
#define xSemaphoreCreateRecursiveMutexStatic( pxStaticSemaphore ) xQueueCreateMutex( queueQUEUE_TYPE_RECURSIVE_MUTEX, pxStaticSemaphore )
#endif /* configSUPPORT_STATIC_ALLOCATION */
/**
* semphr. h
@ -820,7 +829,10 @@ typedef QueueHandle_t SemaphoreHandle_t;
* \ingroup Semaphores
*/
#define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount ) xQueueCreateCountingSemaphore( ( uxMaxCount ), ( uxInitialCount ), ( NULL ) )
#define xSemaphoreCreateCountingStatic( uxMaxCount, uxInitialCount, pxStaticSemaphore ) xQueueCreateCountingSemaphore( ( uxMaxCount ), ( uxInitialCount ), ( pxStaticSemaphore ) )
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
#define xSemaphoreCreateCountingStatic( uxMaxCount, uxInitialCount, pxStaticSemaphore ) xQueueCreateCountingSemaphore( ( uxMaxCount ), ( uxInitialCount ), ( pxStaticSemaphore ) )
#endif /* configSUPPORT_STATIC_ALLOCATION */
/**
* semphr. h

View file

@ -362,7 +362,7 @@ is used in assert() statements. */
UBaseType_t uxPriority,
TaskHandle_t *pvCreatedTask,
StackType_t *pxStackBuffer,
StaticTCB_t *pxTCBBuffer
StaticTask_t *pxTCBBuffer
);</pre>
*
* Create a new task and add it to the list of tasks that are ready to run.
@ -402,7 +402,7 @@ is used in assert() statements. */
* @param pxTCBBuffer If pxTCBBuffer is NULL then the TCB (which is the
* structures used internally within FreeRTOS to hold information on the task)
* will be allocated dynamically, just as when xTaskCreate() is used. If
* pxTCBBuffer is not NULL then it must point to a variable of type StaticTCB_t,
* pxTCBBuffer is not NULL then it must point to a variable of type StaticTask_t,
* which will then be used as the TCB of the task being created.
*
* @return pdPASS if the task was successfully created and added to a ready
@ -418,7 +418,7 @@ is used in assert() statements. */
#define STACK_SIZE 200
// Structure that will hold the TCB of the task being created.
StaticTCB_t xTCB;
StaticTask_t xTCB;
// Buffer that the task being created will use as its stack.
StackType_t xStack[ STACK_SIZE ];
@ -454,7 +454,7 @@ is used in assert() statements. */
*/
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
#define xTaskCreateStatic( pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask, puxStackBuffer, pxDummyTCB ) xTaskGenericCreate( ( pvTaskCode ), ( pcName ), ( usStackDepth ), ( pvParameters ), ( uxPriority ), ( pxCreatedTask ), ( puxStackBuffer ), ( pxDummyTCB ), ( NULL ) )
#endif
#endif /* configSUPPORT_STATIC_ALLOCATION */
/**
* task. h
@ -2095,7 +2095,7 @@ BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder ) PRIVILEGE
* Generic version of the task creation function which is in turn called by the
* xTaskCreate() and xTaskCreateRestricted() macros.
*/
BaseType_t xTaskGenericCreate( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask, StackType_t * const puxStackBuffer, StaticTCB_t * const pxTCBBuffer, const MemoryRegion_t * const xRegions ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
BaseType_t xTaskGenericCreate( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask, StackType_t * const puxStackBuffer, StaticTask_t * const pxTCBBuffer, const MemoryRegion_t * const xRegions ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
/*
* Get the uxTCBNumber assigned to the task referenced by the xTask parameter.

View file

@ -257,7 +257,11 @@ typedef void (*PendedFunction_t)( void *, uint32_t );
* }
* @endverbatim
*/
TimerHandle_t xTimerCreate( const char * const pcTimerName, const TickType_t xTimerPeriodInTicks, const UBaseType_t uxAutoReload, void * const pvTimerID, TimerCallbackFunction_t pxCallbackFunction ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
#define xTimerCreate( pcTimerName, xTimerPeriodInTicks, uxAutoReload, pvTimerID, pxCallbackFunction ) xTimerGenericCreate( ( pcTimerName ), ( xTimerPeriodInTicks ), ( uxAutoReload ), ( pvTimerID ), ( pxCallbackFunction ), NULL )
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
#define xTimerCreateStatic( pcTimerName, xTimerPeriodInTicks, uxAutoReload, pvTimerID, pxCallbackFunction, pxStaticTimer ) xTimerGenericCreate( ( pcTimerName ), ( xTimerPeriodInTicks ), ( uxAutoReload ), ( pvTimerID ), ( pxCallbackFunction ), pxStaticTimer )
#endif /* configSUPPORT_STATIC_ALLOCATION */
/**
* void *pvTimerGetTimerID( TimerHandle_t xTimer );
@ -1136,6 +1140,7 @@ const char * pcTimerGetTimerName( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; /*
*/
BaseType_t xTimerCreateTimerTask( void ) PRIVILEGED_FUNCTION;
BaseType_t xTimerGenericCommand( TimerHandle_t xTimer, const BaseType_t xCommandID, const TickType_t xOptionalValue, BaseType_t * const pxHigherPriorityTaskWoken, const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
TimerHandle_t xTimerGenericCreate( const char * const pcTimerName, const TickType_t xTimerPeriodInTicks, const UBaseType_t uxAutoReload, void * const pvTimerID, TimerCallbackFunction_t pxCallbackFunction, StaticTimer_t *pxStaticTimer ) PRIVILEGED_FUNCTION;
#ifdef __cplusplus
}

View file

@ -426,7 +426,7 @@ to its original value when it is released. */
#endif
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
extern void vApplicationGetIdleTaskMemory( StaticTCB_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint16_t *pusIdleTaskStackSize );
extern void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint16_t *pusIdleTaskStackSize );
#endif
/* File private functions. --------------------------------*/
@ -554,7 +554,7 @@ static void prvResetNextTaskUnblockTime( void );
#endif
/*-----------------------------------------------------------*/
BaseType_t xTaskGenericCreate( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask, StackType_t * const puxStackBuffer, StaticTCB_t * const pxTCBBuffer, const MemoryRegion_t * const xRegions ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
BaseType_t xTaskGenericCreate( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask, StackType_t * const puxStackBuffer, StaticTask_t * const pxTCBBuffer, const MemoryRegion_t * const xRegions ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
{
BaseType_t xReturn;
TCB_t * pxNewTCB;
@ -1546,7 +1546,7 @@ StackType_t *pxTopOfStack;
void vTaskStartScheduler( void )
{
BaseType_t xReturn;
StaticTCB_t *pxIdleTaskTCBBuffer = NULL;
StaticTask_t *pxIdleTaskTCBBuffer = NULL;
StackType_t *pxIdleTaskStackBuffer = NULL;
uint16_t usIdleTaskStackSize = tskIDLE_STACK_SIZE;
@ -3152,9 +3152,9 @@ TCB_t *pxNewTCB;
#if( ( configASSERT_DEFINED == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
{
/* Sanity check that the size of the structure used to declare a
variable of type StaticTCB_t matches the size of the actual TCB_t
variable of type StaticTask_t matches the size of the actual TCB_t
structure. */
volatile size_t xSize = sizeof( StaticTCB_t );
volatile size_t xSize = sizeof( StaticTask_t );
configASSERT( xSize == sizeof( TCB_t ) );
}
#endif /* configASSERT_DEFINED */

View file

@ -112,6 +112,10 @@ typedef struct tmrTimerControl
#if( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxTimerNumber; /*<< An ID assigned by trace tools such as FreeRTOS+Trace */
#endif
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
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. */
#endif
} xTIMER;
/* The old xTIMER name is maintained above then typedefed to the new Timer_t
@ -184,7 +188,7 @@ PRIVILEGED_DATA static QueueHandle_t xTimerQueue = NULL;
following callback function - which enables the application to optionally
provide the memory that will be used by the timer task as the task's stack
and TCB. */
extern void vApplicationGetTimerTaskMemory( StaticTCB_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint16_t *pusTimerTaskStackSize );
extern void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint16_t *pusTimerTaskStackSize );
#endif
@ -250,7 +254,7 @@ static void prvProcessTimerOrBlockTask( const TickType_t xNextExpireTime, BaseTy
BaseType_t xTimerCreateTimerTask( void )
{
BaseType_t xReturn = pdFAIL;
StaticTCB_t *pxTimerTaskTCBBuffer = NULL;
StaticTask_t *pxTimerTaskTCBBuffer = NULL;
StackType_t *pxTimerTaskStackBuffer = NULL;
uint16_t usTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
@ -294,10 +298,20 @@ uint16_t usTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
}
/*-----------------------------------------------------------*/
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. */
TimerHandle_t xTimerGenericCreate( const char * const pcTimerName, const TickType_t xTimerPeriodInTicks, const UBaseType_t uxAutoReload, void * const pvTimerID, TimerCallbackFunction_t pxCallbackFunction, StaticTimer_t *pxStaticTimer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
{
Timer_t *pxNewTimer;
#if( ( configASSERT_DEFINED == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
{
/* Sanity check that the size of the structure used to declare a
variable of type StaticTimer_t equals the size of the real timer
structures. */
volatile size_t xSize = sizeof( StaticTimer_t );
configASSERT( xSize == sizeof( Timer_t ) );
}
#endif /* configASSERT_DEFINED */
/* Allocate the timer structure. */
if( xTimerPeriodInTicks == ( TickType_t ) 0U )
{
@ -305,14 +319,25 @@ Timer_t *pxNewTimer;
}
else
{
pxNewTimer = ( Timer_t * ) pvPortMalloc( sizeof( Timer_t ) );
/* If the user passed in a statically allocated timer structure then use
it, otherwise allocate the structure dynamically. */
if( pxStaticTimer == NULL )
{
pxNewTimer = ( Timer_t * ) pvPortMalloc( sizeof( Timer_t ) );
}
else
{
pxNewTimer = ( Timer_t * ) pxStaticTimer;
}
if( pxNewTimer != NULL )
{
/* Ensure the infrastructure used by the timer service task has been
created/initialised. */
prvCheckForValidListAndQueue();
/* Initialise the timer structure members using the function parameters. */
/* Initialise the timer structure members using the function
parameters. */
pxNewTimer->pcTimerName = pcTimerName;
pxNewTimer->xTimerPeriodInTicks = xTimerPeriodInTicks;
pxNewTimer->uxAutoReload = uxAutoReload;
@ -320,6 +345,15 @@ Timer_t *pxNewTimer;
pxNewTimer->pxCallbackFunction = pxCallbackFunction;
vListInitialiseItem( &( pxNewTimer->xTimerListItem ) );
if( pxStaticTimer == NULL )
{
pxNewTimer->ucStaticallyAllocated = pdFALSE;
}
else
{
pxNewTimer->ucStaticallyAllocated = pdTRUE;
}
traceTIMER_CREATE( pxNewTimer );
}
else
@ -716,19 +750,27 @@ TickType_t xTimeNow;
pxTimer->xTimerPeriodInTicks = xMessage.u.xTimerParameters.xMessageValue;
configASSERT( ( pxTimer->xTimerPeriodInTicks > 0 ) );
/* The new period does not really have a reference, and can be
longer or shorter than the old one. The command time is
therefore set to the current time, and as the period cannot be
zero the next expiry time can only be in the future, meaning
(unlike for the xTimerStart() case above) there is no fail case
that needs to be handled here. */
/* The new period does not really have a reference, and can
be longer or shorter than the old one. The command time is
therefore set to the current time, and as the period cannot
be zero the next expiry time can only be in the future,
meaning (unlike for the xTimerStart() case above) there is
no fail case that needs to be handled here. */
( void ) prvInsertTimerInActiveList( pxTimer, ( xTimeNow + pxTimer->xTimerPeriodInTicks ), xTimeNow, xTimeNow );
break;
case tmrCOMMAND_DELETE :
/* The timer has already been removed from the active list,
just free up the memory. */
vPortFree( pxTimer );
just free up the memory if the memory was dynamically
allocated. */
if( pxTimer->ucStaticallyAllocated == pdFALSE )
{
vPortFree( pxTimer );
}
else
{
mtCOVERAGE_TEST_MARKER();
}
break;
default :