Add support for statically allocated memory protected tasks - previously only dynamically allocated tasks could be memory protected.

This commit is contained in:
Richard Barry 2016-09-20 13:54:28 +00:00
parent 5c75e5a38a
commit 7cce089e40
17 changed files with 5302 additions and 36 deletions

View file

@ -83,6 +83,7 @@
BaseType_t MPU_xTaskCreate( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask );
TaskHandle_t MPU_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 );
BaseType_t MPU_xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask );
BaseType_t MPU_xTaskCreateRestrictedStatic( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask );
void MPU_vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t * const pxRegions );
void MPU_vTaskDelete( TaskHandle_t xTaskToDelete );
void MPU_vTaskDelay( const TickType_t xTicksToDelay );

View file

@ -177,8 +177,11 @@ only for ports that are using the MPU. */
#define xEventGroupSync MPU_xEventGroupSync
#define vEventGroupDelete MPU_vEventGroupDelete
/* Remove the privileged function macro. */
/* Remove the privileged function macro, but keep the PRIVILEGED_DATA
macro so applications can place data in privileged access sections
(useful when using statically allocated objects). */
#define PRIVILEGED_FUNCTION
#define PRIVILEGED_DATA __attribute__((section("privileged_data")))
#else /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */

View file

@ -160,6 +160,9 @@ typedef struct xTASK_PARAMETERS
UBaseType_t uxPriority;
StackType_t *puxStackBuffer;
MemoryRegion_t xRegions[ portNUM_CONFIGURABLE_REGIONS ];
#if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
StaticTask_t * const pxTaskBuffer;
#endif
} TaskParameters_t;
/* Used with the uxTaskGetSystemState() function to return the state of each task
@ -487,6 +490,8 @@ is used in assert() statements. */
*<pre>
BaseType_t xTaskCreateRestricted( TaskParameters_t *pxTaskDefinition, TaskHandle_t *pxCreatedTask );</pre>
*
* Only available when configSUPPORT_DYNAMIC_ALLOCATION is set to 1.
*
* xTaskCreateRestricted() should only be used in systems that include an MPU
* implementation.
*
@ -494,6 +499,9 @@ is used in assert() statements. */
* The function parameters define the memory regions and associated access
* permissions allocated to the task.
*
* See xTaskCreateRestrictedStatic() for a version that does not use any
* dynamic memory allocation.
*
* @param pxTaskDefinition Pointer to a structure that contains a member
* for each of the normal xTaskCreate() parameters (see the xTaskCreate() API
* documentation) plus an optional stack buffer and the memory region
@ -553,6 +561,94 @@ TaskHandle_t xHandle;
BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask ) PRIVILEGED_FUNCTION;
#endif
/**
* task. h
*<pre>
BaseType_t xTaskCreateRestrictedStatic( TaskParameters_t *pxTaskDefinition, TaskHandle_t *pxCreatedTask );</pre>
*
* Only available when configSUPPORT_STATIC_ALLOCATION is set to 1.
*
* xTaskCreateRestrictedStatic() should only be used in systems that include an
* MPU implementation.
*
* Internally, within the FreeRTOS implementation, tasks use two blocks of
* memory. The first block is used to hold the task's data structures. The
* second block is used by the task as its stack. If a task is created using
* xTaskCreateRestricted() then the stack is provided by the application writer,
* and the memory used to hold the task's data structure is automatically
* dynamically allocated inside the xTaskCreateRestricted() function. If a task
* is created using xTaskCreateRestrictedStatic() then the application writer
* must provide the memory used to hold the task's data structures too.
* xTaskCreateRestrictedStatic() therefore allows a memory protected task to be
* created without using any dynamic memory allocation.
*
* @param pxTaskDefinition Pointer to a structure that contains a member
* for each of the normal xTaskCreate() parameters (see the xTaskCreate() API
* documentation) plus an optional stack buffer and the memory region
* definitions. If configSUPPORT_STATIC_ALLOCATION is set to 1 the structure
* contains an additional member, which is used to point to a variable of type
* StaticTask_t - which is then used to hold the task's data structure.
*
* @param pxCreatedTask Used to pass back a handle by which the created task
* can be referenced.
*
* @return pdPASS if the task was successfully created and added to a ready
* list, otherwise an error code defined in the file projdefs.h
*
* Example usage:
<pre>
// Create an TaskParameters_t structure that defines the task to be created.
// The StaticTask_t variable is only included in the structure when
// configSUPPORT_STATIC_ALLOCATION is set to 1. The PRIVILEGED_DATA macro can
// be used to force the variable into the RTOS kernel's privileged data area.
static PRIVILEGED_DATA StaticTask_t xTaskBuffer;
static const TaskParameters_t xCheckTaskParameters =
{
vATask, // pvTaskCode - the function that implements the task.
"ATask", // pcName - just a text name for the task to assist debugging.
100, // usStackDepth - the stack size DEFINED IN WORDS.
NULL, // pvParameters - passed into the task function as the function parameters.
( 1UL | portPRIVILEGE_BIT ),// uxPriority - task priority, set the portPRIVILEGE_BIT if the task should run in a privileged state.
cStackBuffer,// puxStackBuffer - the buffer to be used as the task stack.
// xRegions - Allocate up to three separate memory regions for access by
// the task, with appropriate access permissions. Different processors have
// different memory alignment requirements - refer to the FreeRTOS documentation
// for full information.
{
// Base address Length Parameters
{ cReadWriteArray, 32, portMPU_REGION_READ_WRITE },
{ cReadOnlyArray, 32, portMPU_REGION_READ_ONLY },
{ cPrivilegedOnlyAccessArray, 128, portMPU_REGION_PRIVILEGED_READ_WRITE }
}
&xTaskBuffer; // Holds the task's data structure.
};
int main( void )
{
TaskHandle_t xHandle;
// Create a task from the const structure defined above. The task handle
// is requested (the second parameter is not NULL) but in this case just for
// demonstration purposes as its not actually used.
xTaskCreateRestricted( &xRegTest1Parameters, &xHandle );
// Start the scheduler.
vTaskStartScheduler();
// Will only get here if there was insufficient memory to create the idle
// and/or timer task.
for( ;; );
}
</pre>
* \defgroup xTaskCreateRestrictedStatic xTaskCreateRestrictedStatic
* \ingroup Tasks
*/
#if( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
BaseType_t xTaskCreateRestrictedStatic( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask ) PRIVILEGED_FUNCTION;
#endif
/**
* task. h
*<pre>

View file

@ -96,15 +96,30 @@ extern BaseType_t xPortRaisePrivilege( void );
/*-----------------------------------------------------------*/
BaseType_t MPU_xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask )
{
BaseType_t xReturn;
BaseType_t xRunningPrivileged = xPortRaisePrivilege();
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
BaseType_t MPU_xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask )
{
BaseType_t xReturn;
BaseType_t xRunningPrivileged = xPortRaisePrivilege();
xReturn = xTaskCreateRestricted( pxTaskDefinition, pxCreatedTask );
vPortResetPrivilege( xRunningPrivileged );
return xReturn;
}
xReturn = xTaskCreateRestricted( pxTaskDefinition, pxCreatedTask );
vPortResetPrivilege( xRunningPrivileged );
return xReturn;
}
#endif /* conifgSUPPORT_DYNAMIC_ALLOCATION */
/*-----------------------------------------------------------*/
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
BaseType_t MPU_xTaskCreateRestrictedStatic( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask )
{
BaseType_t xReturn;
BaseType_t xRunningPrivileged = xPortRaisePrivilege();
xReturn = xTaskCreateRestrictedStatic( pxTaskDefinition, pxCreatedTask );
vPortResetPrivilege( xRunningPrivileged );
return xReturn;
}
#endif /* conifgSUPPORT_DYNAMIC_ALLOCATION */
/*-----------------------------------------------------------*/
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
@ -337,7 +352,7 @@ BaseType_t xRunningPrivileged = xPortRaisePrivilege();
#endif
/*-----------------------------------------------------------*/
#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
void MPU_vTaskList( char *pcWriteBuffer )
{
BaseType_t xRunningPrivileged = xPortRaisePrivilege();
@ -348,7 +363,7 @@ BaseType_t xRunningPrivileged = xPortRaisePrivilege();
#endif
/*-----------------------------------------------------------*/
#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
void MPU_vTaskGetRunTimeStats( char *pcWriteBuffer )
{
BaseType_t xRunningPrivileged = xPortRaisePrivilege();
@ -726,7 +741,7 @@ void * xReturn;
#endif
/*-----------------------------------------------------------*/
#if ( configUSE_QUEUE_SETS == 1 )
#if( ( configUSE_QUEUE_SETS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
QueueSetHandle_t MPU_xQueueCreateSet( UBaseType_t uxEventQueueLength )
{
QueueSetHandle_t xReturn;
@ -827,7 +842,6 @@ BaseType_t xRunningPrivileged = xPortRaisePrivilege();
/*-----------------------------------------------------------*/
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
void *MPU_pvPortMalloc( size_t xSize )
{
void *pvReturn;
@ -839,12 +853,10 @@ BaseType_t xRunningPrivileged = xPortRaisePrivilege();
return pvReturn;
}
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
/*-----------------------------------------------------------*/
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
void MPU_vPortFree( void *pv )
{
BaseType_t xRunningPrivileged = xPortRaisePrivilege();
@ -853,31 +865,34 @@ BaseType_t xRunningPrivileged = xPortRaisePrivilege();
vPortResetPrivilege( xRunningPrivileged );
}
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
/*-----------------------------------------------------------*/
void MPU_vPortInitialiseBlocks( void )
{
BaseType_t xRunningPrivileged = xPortRaisePrivilege();
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
void MPU_vPortInitialiseBlocks( void )
{
BaseType_t xRunningPrivileged = xPortRaisePrivilege();
vPortInitialiseBlocks();
vPortInitialiseBlocks();
vPortResetPrivilege( xRunningPrivileged );
}
vPortResetPrivilege( xRunningPrivileged );
}
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
/*-----------------------------------------------------------*/
size_t MPU_xPortGetFreeHeapSize( void )
{
size_t xReturn;
BaseType_t xRunningPrivileged = xPortRaisePrivilege();
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
size_t MPU_xPortGetFreeHeapSize( void )
{
size_t xReturn;
BaseType_t xRunningPrivileged = xPortRaisePrivilege();
xReturn = xPortGetFreeHeapSize();
xReturn = xPortGetFreeHeapSize();
vPortResetPrivilege( xRunningPrivileged );
vPortResetPrivilege( xRunningPrivileged );
return xReturn;
}
return xReturn;
}
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
/*-----------------------------------------------------------*/
#if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configUSE_TIMERS == 1 ) )

View file

@ -134,7 +134,7 @@ that if portUSING_MPU_WRAPPERS is 1 then a protected task can be created with
a statically allocated stack and a dynamically allocated TCB.
!!!NOTE!!! If the definition of tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE is
changed then the definition of StaticTask_t must also be updated. */
#define tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE ( ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) || ( portUSING_MPU_WRAPPERS == 1 ) )
#define tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 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 )
@ -667,7 +667,53 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION;
#endif /* SUPPORT_STATIC_ALLOCATION */
/*-----------------------------------------------------------*/
#if( portUSING_MPU_WRAPPERS == 1 )
#if( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
BaseType_t xTaskCreateRestrictedStatic( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask )
{
TCB_t *pxNewTCB;
BaseType_t xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
configASSERT( pxTaskDefinition->puxStackBuffer != NULL );
configASSERT( pxTaskDefinition->pxTaskBuffer != NULL );
if( ( pxTaskDefinition->puxStackBuffer != NULL ) && ( pxTaskDefinition->pxTaskBuffer != 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 * ) pxTaskDefinition->pxTaskBuffer;
/* Store the stack location in the TCB. */
pxNewTCB->pxStack = pxTaskDefinition->puxStackBuffer;
#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 = tskSTATICALLY_ALLOCATED_STACK_AND_TCB;
}
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
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 == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) */
/*-----------------------------------------------------------*/
#if( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask )
{
@ -3987,7 +4033,7 @@ TCB_t *pxTCB;
#endif /* ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) */
/*-----------------------------------------------------------*/
#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
void vTaskList( char * pcWriteBuffer )
{
@ -4079,10 +4125,10 @@ TCB_t *pxTCB;
}
}
#endif /* ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */
#endif /* ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) */
/*----------------------------------------------------------*/
#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
void vTaskGetRunTimeStats( char *pcWriteBuffer )
{
@ -4206,7 +4252,7 @@ TCB_t *pxTCB;
}
}
#endif /* ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */
#endif /* ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) */
/*-----------------------------------------------------------*/
TickType_t uxTaskResetEventItemValue( void )