Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
136 changes: 127 additions & 9 deletions portable/GCC/ARM_CRx_MPU/port.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,128 @@ PRIVILEGED_FUNCTION void vPortExitCritical( void );

/* ----------------------------------------------------------------------------------- */


/**
* @brief Determine if the MPU Register Settings are valid MPU Settings
*/
BaseType_t xPortMPURegisterCheck( xMPU_REGION_REGISTERS * xMPURegisters,
uint32_t ulTaskFlags )
{
#if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */
extern uint32_t * __SRAM_segment_start__;
extern uint32_t * __SRAM_segment_end__;
extern uint32_t * __FLASH_segment_start__;
extern uint32_t * __FLASH_segment_end__;
extern uint32_t * __privileged_functions_start__;
extern uint32_t * __privileged_functions_end__;
extern uint32_t * __privileged_data_start__;
extern uint32_t * __privileged_data_end__;
#else
/* Declaration when these variable are exported from linker scripts. */
extern uint32_t __FLASH_segment_start__[];
extern uint32_t __FLASH_segment_end__[];
extern uint32_t __SRAM_segment_start__[];
extern uint32_t __SRAM_segment_end__[];
extern uint32_t __privileged_functions_start__[];
extern uint32_t __privileged_functions_end__[];
extern uint32_t __privileged_data_start__[];
extern uint32_t __privileged_data_end__[];
#endif /* if defined( __ARMCC_VERSION ) */

BaseType_t retVal;
if( NULL == xMPURegisters )
{
retVal = pdFAIL;
}

else if( ( xMPURegisters->ulRegionSize & portMPU_REGION_ENABLE ) != portMPU_REGION_ENABLE )
{
retVal = pdPASS;
}

else
{
uint32_t ulBaseAddr = xMPURegisters->ulRegionBaseAddress;
/* Bits [5:1] are the MPU Region Size Bits, need to clear the enable bit */
uint32_t ulSize = xMPURegisters->ulRegionSize;
uint32_t ulSizeMask = 2UL << ( xMPURegisters->ulRegionSize >> 1U );
uint32_t ulAttributes = xMPURegisters->ulRegionAttribute;

/* Make sure the MPU Region Size is a valid value */
if( ( ulSize < portMPU_REGION_SIZE_32B ) || ( ulSize > portMPU_REGION_SIZE_4GB ) )
{
retVal = pdFAIL;
}

/* Make sure that the Region Base Address is aligned to the size of the region */
else if( ( ulBaseAddr % ( ulSizeMask ) ) != 0 )
{
retVal = pdFAIL;
}

/* If using subregions, make sure that the size is larger than 256 bytes */
else if( ( ( ulSize & ( 0XFF00UL ) ) && ( ulSize < portMPU_REGION_SIZE_256B ) ) )
{
retVal = pdFAIL;
}

/* Tasks shall not be granted write access to Function Code.
* Access Permission 0XX means that writes to the memory location are allowed */
else if( ( ( ulBaseAddr >= ( uint32_t ) __FLASH_segment_start__ ) && ( ulBaseAddr < ( uint32_t ) __FLASH_segment_end__ ) ) &&
( ( ulAttributes & ( 1UL << 11UL ) ) != ( 1UL << 11UL ) ) )
{
retVal = pdFAIL;
}

/* Ensure that tasks are not attempting to mark RAM as an executable code region */
else if( ( ( ulBaseAddr >= ( uint32_t ) __SRAM_segment_start__ ) && ( ulBaseAddr < ( uint32_t ) __SRAM_segment_end__ ) ) &&
( ( ulAttributes & portMPU_REGION_EXECUTE_NEVER ) != portMPU_REGION_EXECUTE_NEVER ) )
{
retVal = pdFAIL;
}

/* Unprivileged tasks shall not be granted access to Kernel Code or data. */
else if( ( ( ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) != portTASK_IS_PRIVILEGED_FLAG ) &&
( ( ( ulBaseAddr < ( uint32_t ) __privileged_data_end__ ) && ( ulBaseAddr >= ( uint32_t ) __privileged_data_start__ ) ) ||
( ( ulBaseAddr < ( uint32_t ) __privileged_functions_end__ ) && ( ulBaseAddr >= ( uint32_t ) __privileged_functions_start__ ) ) ) )
{
retVal = pdFAIL;
}

/* Region passed all checks*/
else
{
retVal = pdPASS;
}
}
return retVal;
}

BaseType_t xPortValidateTaskMPUSettings( xMPU_SETTINGS * xTaskMPUSettings )
{
BaseType_t retVal = pdPASS;
if( xTaskMPUSettings == NULL )
{
retVal = pdFAIL;
}
else
{
uint32_t ulRegionNum = 0UL;
do
{
retVal = xPortMPURegisterCheck( &xTaskMPUSettings->xRegion[ ulRegionNum ],
xTaskMPUSettings->ulTaskFlags );

ulRegionNum++;
} while( (retVal == pdPASS ) && ( ulRegionNum < portTOTAL_NUM_REGIONS_IN_TCB ) );
}

return retVal;
}


/**
* @brief Setup a FreeRTOS task's initial context.
*
Expand All @@ -167,6 +289,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
{
/* Setup the initial context of the task. The context is set exactly as
* expected by the portRESTORE_CONTEXT() macro. */

UBaseType_t ulIndex = CONTEXT_SIZE - 1U;

xSYSTEM_CALL_STACK_INFO * xSysCallInfo = NULL;
Expand All @@ -193,6 +316,10 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,

ulIndex--;

/* Ensure per-task MPU Settings are valid */
volatile BaseType_t retVal = xPortValidateTaskMPUSettings( xMPUSettings );
configASSERT( retVal == pdTRUE );

xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) pxCode; /* PC. */
ulIndex--;

Expand Down Expand Up @@ -550,15 +677,6 @@ static void prvSetupMPU( void )
( portMPU_REGION_PRIV_RO_USER_NA_EXEC |
portMPU_REGION_NORMAL_OIWTNOWA_SHARED ) );

/* Priv: RW, Unpriv: No Access for privileged data. */
ulRegionLength = ( uint32_t ) __privileged_data_end__ - ( uint32_t ) __privileged_data_start__;
ulRegionLengthEncoded = prvGetMPURegionSizeEncoding( ulRegionLength );
vMPUSetRegion( portPRIVILEGED_RAM_REGION,
( uint32_t ) __privileged_data_start__,
( ulRegionLengthEncoded | portMPU_REGION_ENABLE ),
( portMPU_REGION_PRIV_RW_USER_NA_NOEXEC |
portMPU_REGION_PRIV_RW_USER_NA_NOEXEC ) );

/* Enable the MPU background region - it allows privileged operating modes
* access to unmapped regions of memory without generating a fault. */
vMPUEnableBackgroundRegion();
Expand Down
9 changes: 4 additions & 5 deletions portable/GCC/ARM_CRx_MPU/portmacro_asm.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,11 +124,10 @@ extern "C" {

/* Default MPU regions. */
#define portFIRST_CONFIGURABLE_REGION ( 0 )
#define portLAST_CONFIGURABLE_REGION ( portMPU_TOTAL_REGIONS - 5UL )
#define portSTACK_REGION ( portMPU_TOTAL_REGIONS - 4UL )
#define portUNPRIVILEGED_FLASH_REGION ( portMPU_TOTAL_REGIONS - 3UL )
#define portPRIVILEGED_FLASH_REGION ( portMPU_TOTAL_REGIONS - 2UL )
#define portPRIVILEGED_RAM_REGION ( portMPU_TOTAL_REGIONS - 1UL )
#define portLAST_CONFIGURABLE_REGION ( portMPU_TOTAL_REGIONS - 4UL )
#define portSTACK_REGION ( portMPU_TOTAL_REGIONS - 3UL )
#define portUNPRIVILEGED_FLASH_REGION ( portMPU_TOTAL_REGIONS - 2UL )
#define portPRIVILEGED_FLASH_REGION ( portMPU_TOTAL_REGIONS - 1UL )
#define portNUM_CONFIGURABLE_REGIONS \
( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1UL )
/* Plus one to make space for the stack region. */
Expand Down