mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-09-12 09:07:46 -04:00
Updates to support FreeRTOS MPU in FreeRTOS V9.0.0 - including a GCC project that runs in the Keil simulator to allow development and testing.
This commit is contained in:
parent
255145bde1
commit
057b38ad23
16 changed files with 5877 additions and 44 deletions
|
@ -117,6 +117,26 @@ functions but without including stdio.h here. */
|
|||
*/
|
||||
#define tskSTACK_FILL_BYTE ( 0xa5U )
|
||||
|
||||
/* Sometimes the FreeRTOSConfig.h settings only allow a task to be created using
|
||||
dynamically allocated RAM, in which case when any task is deleted it is known
|
||||
that both the task's stack and TCB need to be freed. Sometimes the
|
||||
FreeRTOSConfig.h settings only allow a task to be created using statically
|
||||
allocated RAM, in which case when any task is deleted it is known that neither
|
||||
the task's stack or TCB should be freed. Sometimes the FreeRTOSConfig.h
|
||||
settings allow a task to be created using either statically or dynamically
|
||||
allocated RAM, in which case a member of the TCB is used to record whether the
|
||||
stack and/or TCB were allocated statically or dynamically, so when a task is
|
||||
deleted the RAM that was allocated dynamically is freed again and no attempt is
|
||||
made to free the RAM that was allocated statically.
|
||||
tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE is only true if it is possible for a
|
||||
task to be created using either statically or dynamically allocated RAM. Note
|
||||
that if portUSING_MPU_WRAPPERS is 1 then a protected task can be created with
|
||||
a statically allocated stack and a dynamically allocated TCB. */
|
||||
#define tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE ( ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) || ( portUSING_MPU_WRAPPERS == 1 ) )
|
||||
#define tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB ( ( uint8_t ) 0 )
|
||||
#define tskSTATICALLY_ALLOCATED_STACK_ONLY ( ( uint8_t ) 1 )
|
||||
#define tskSTATICALLY_ALLOCATED_STACK_AND_TCB ( ( uint8_t ) 2 )
|
||||
|
||||
/*
|
||||
* Macros used by vListTask to indicate which state a task is in.
|
||||
*/
|
||||
|
@ -330,8 +350,10 @@ typedef struct tskTaskControlBlock
|
|||
volatile uint8_t ucNotifyState;
|
||||
#endif
|
||||
|
||||
#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
|
||||
uint8_t ucStaticallyAllocated; /* Set to pdTRUE if the task is a statically allocated to ensure no attempt is made to free the memory. */
|
||||
/* See the comments above the definition of
|
||||
tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE. */
|
||||
#if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
|
||||
uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the task is a statically allocated to ensure no attempt is made to free the memory. */
|
||||
#endif
|
||||
|
||||
#if( INCLUDE_xTaskAbortDelay == 1 )
|
||||
|
@ -542,7 +564,14 @@ static void prvResetNextTaskUnblockTime( void );
|
|||
* Called after a Task_t structure has been allocated either statically or
|
||||
* dynamically to fill in the structure's members.
|
||||
*/
|
||||
static void prvInitialiseNewTask( TaskFunction_t pxTaskCode, const char * const pcName, const uint32_t ulStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask, TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
||||
static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
|
||||
const char * const pcName,
|
||||
const uint32_t ulStackDepth,
|
||||
void * const pvParameters,
|
||||
UBaseType_t uxPriority,
|
||||
TaskHandle_t * const pxCreatedTask,
|
||||
TCB_t *pxNewTCB,
|
||||
const MemoryRegion_t * const xRegions ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
||||
|
||||
/*
|
||||
* Called after a new task has been created and initialised to place the task
|
||||
|
@ -554,7 +583,13 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION;
|
|||
|
||||
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
|
||||
|
||||
TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode, const char * const pcName, const uint32_t ulStackDepth, void * const pvParameters, UBaseType_t uxPriority, StackType_t * const puxStackBuffer, StaticTask_t * const pxTaskBuffer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
||||
TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,
|
||||
const char * const pcName,
|
||||
const uint32_t ulStackDepth,
|
||||
void * const pvParameters,
|
||||
UBaseType_t uxPriority,
|
||||
StackType_t * const puxStackBuffer,
|
||||
StaticTask_t * const pxTaskBuffer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
||||
{
|
||||
TCB_t *pxNewTCB;
|
||||
TaskHandle_t xReturn;
|
||||
|
@ -569,15 +604,15 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION;
|
|||
pxNewTCB = ( TCB_t * ) pxTaskBuffer; /*lint !e740 Unusual cast is ok as the structures are designed to have the same alignment, and the size is checked by an assert. */
|
||||
pxNewTCB->pxStack = ( StackType_t * ) puxStackBuffer;
|
||||
|
||||
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
||||
#if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
|
||||
{
|
||||
/* Tasks can be created statically or dynamically, so note this
|
||||
task was created statically in case the task is later deleted. */
|
||||
pxNewTCB->ucStaticallyAllocated = pdTRUE;
|
||||
pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB;
|
||||
}
|
||||
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
|
||||
|
||||
prvInitialiseNewTask( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, &xReturn, pxNewTCB );
|
||||
prvInitialiseNewTask( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, &xReturn, pxNewTCB, NULL );
|
||||
prvAddNewTaskToReadyList( pxNewTCB );
|
||||
}
|
||||
else
|
||||
|
@ -591,9 +626,59 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION;
|
|||
#endif /* SUPPORT_STATIC_ALLOCATION */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( portUSING_MPU_WRAPPERS == 1 )
|
||||
|
||||
BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask )
|
||||
{
|
||||
TCB_t *pxNewTCB;
|
||||
BaseType_t xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
|
||||
|
||||
configASSERT( pxTaskDefinition->puxStackBuffer );
|
||||
|
||||
if( pxTaskDefinition->puxStackBuffer != NULL )
|
||||
{
|
||||
/* Allocate space for the TCB. Where the memory comes from depends
|
||||
on the implementation of the port malloc function and whether or
|
||||
not static allocation is being used. */
|
||||
pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
|
||||
|
||||
if( pxNewTCB != NULL )
|
||||
{
|
||||
/* Store the stack location in the TCB. */
|
||||
pxNewTCB->pxStack = pxTaskDefinition->puxStackBuffer;
|
||||
|
||||
/* Tasks can be created statically or dynamically, so note
|
||||
this task had a statically allocated stack in case it is
|
||||
later deleted. The TCB was allocated dynamically. */
|
||||
pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_ONLY;
|
||||
|
||||
prvInitialiseNewTask( pxTaskDefinition->pvTaskCode,
|
||||
pxTaskDefinition->pcName,
|
||||
( uint32_t ) pxTaskDefinition->usStackDepth,
|
||||
pxTaskDefinition->pvParameters,
|
||||
pxTaskDefinition->uxPriority,
|
||||
pxCreatedTask, pxNewTCB,
|
||||
pxTaskDefinition->xRegions );
|
||||
|
||||
prvAddNewTaskToReadyList( pxNewTCB );
|
||||
xReturn = pdPASS;
|
||||
}
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
#endif /* portUSING_MPU_WRAPPERS */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
||||
|
||||
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
||||
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
|
||||
const char * const pcName,
|
||||
const uint16_t usStackDepth,
|
||||
void * const pvParameters,
|
||||
UBaseType_t uxPriority,
|
||||
TaskHandle_t * const pxCreatedTask ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
||||
{
|
||||
TCB_t *pxNewTCB;
|
||||
BaseType_t xReturn;
|
||||
|
@ -656,15 +741,15 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION;
|
|||
|
||||
if( pxNewTCB != NULL )
|
||||
{
|
||||
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
|
||||
#if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
|
||||
{
|
||||
/* Tasks can be created statically or dynamically, so note this
|
||||
task was created dynamically in case it is later deleted. */
|
||||
pxNewTCB->ucStaticallyAllocated = pdFALSE;
|
||||
pxNewTCB->ucStaticallyAllocated = tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB;
|
||||
}
|
||||
#endif /* configSUPPORT_STATIC_ALLOCATION */
|
||||
|
||||
prvInitialiseNewTask( pxTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB );
|
||||
prvInitialiseNewTask( pxTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, NULL );
|
||||
prvAddNewTaskToReadyList( pxNewTCB );
|
||||
xReturn = pdPASS;
|
||||
}
|
||||
|
@ -679,7 +764,14 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION;
|
|||
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvInitialiseNewTask( TaskFunction_t pxTaskCode, const char * const pcName, const uint32_t ulStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask, TCB_t *pxNewTCB ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
||||
static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
|
||||
const char * const pcName,
|
||||
const uint32_t ulStackDepth,
|
||||
void * const pvParameters,
|
||||
UBaseType_t uxPriority,
|
||||
TaskHandle_t * const pxCreatedTask,
|
||||
TCB_t *pxNewTCB,
|
||||
const MemoryRegion_t * const xRegions ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
||||
{
|
||||
StackType_t *pxTopOfStack;
|
||||
UBaseType_t x;
|
||||
|
@ -805,6 +897,11 @@ UBaseType_t x;
|
|||
{
|
||||
vPortStoreTaskMPUSettings( &( pxNewTCB->xMPUSettings ), xRegions, pxNewTCB->pxStack, ulStackDepth );
|
||||
}
|
||||
#else
|
||||
{
|
||||
/* Avoid compiler warning about unreferenced parameter. */
|
||||
( void ) xRegions;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )
|
||||
|
@ -1740,7 +1837,13 @@ BaseType_t xReturn;
|
|||
/* The Idle task is created using user provided RAM - obtain the
|
||||
address of the RAM then create the idle task. */
|
||||
vApplicationGetIdleTaskMemory( &pxIdleTaskTCBBuffer, &pxIdleTaskStackBuffer, &ulIdleTaskStackSize );
|
||||
xIdleTaskHandle = xTaskCreateStatic( prvIdleTask, "IDLE", ulIdleTaskStackSize, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), pxIdleTaskStackBuffer, pxIdleTaskTCBBuffer ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
|
||||
xIdleTaskHandle = xTaskCreateStatic( prvIdleTask,
|
||||
"IDLE",
|
||||
ulIdleTaskStackSize,
|
||||
( void * ) NULL,
|
||||
( tskIDLE_PRIORITY | portPRIVILEGE_BIT ),
|
||||
pxIdleTaskStackBuffer,
|
||||
pxIdleTaskTCBBuffer ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
|
||||
|
||||
if( xIdleTaskHandle != NULL )
|
||||
{
|
||||
|
@ -1754,7 +1857,11 @@ BaseType_t xReturn;
|
|||
#else
|
||||
{
|
||||
/* The Idle task is being created using dynamically allocated RAM. */
|
||||
xReturn = xTaskCreate( prvIdleTask, "IDLE", configMINIMAL_STACK_SIZE, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), &xIdleTaskHandle ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
|
||||
xReturn = xTaskCreate( prvIdleTask,
|
||||
"IDLE", configMINIMAL_STACK_SIZE,
|
||||
( void * ) NULL,
|
||||
( tskIDLE_PRIORITY | portPRIVILEGE_BIT ),
|
||||
&xIdleTaskHandle ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
|
||||
}
|
||||
#endif /* configSUPPORT_STATIC_ALLOCATION */
|
||||
|
||||
|
@ -3486,24 +3593,36 @@ static void prvCheckTasksWaitingTermination( void )
|
|||
}
|
||||
#endif /* configUSE_NEWLIB_REENTRANT */
|
||||
|
||||
#if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) )
|
||||
#if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) && ( portUSING_MPU_WRAPPERS == 0 ) )
|
||||
{
|
||||
/* The task can only have been allocated dynamically - free it
|
||||
again. */
|
||||
/* The task can only have been allocated dynamically - free both
|
||||
the stack and TCB. */
|
||||
vPortFree( pxTCB->pxStack );
|
||||
vPortFree( pxTCB );
|
||||
}
|
||||
#elif( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
|
||||
#elif( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE == 1 )
|
||||
{
|
||||
/* The task could have been allocated statically or dynamically, so
|
||||
check before attempting to free the memory. */
|
||||
if( pxTCB->ucStaticallyAllocated == ( uint8_t ) pdFALSE )
|
||||
check what was statically allocated before trying to free the
|
||||
memory. */
|
||||
if( pxTCB->ucStaticallyAllocated == tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB )
|
||||
{
|
||||
/* Both the stack and TCB were allocated dynamically, so both
|
||||
must be freed. */
|
||||
vPortFree( pxTCB->pxStack );
|
||||
vPortFree( pxTCB );
|
||||
}
|
||||
else if( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_ONLY )
|
||||
{
|
||||
/* Only the stack was statically allocated, so the TCB is the
|
||||
only memory that must be freed. */
|
||||
vPortFree( pxTCB );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Neither the stack nor the TCB were allocated dynamically, so
|
||||
nothing needs to be freed. */
|
||||
configASSERT( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_AND_TCB )
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue