Skip to content
Open
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
76 changes: 55 additions & 21 deletions portable/GCC/ARM_CM3_MPU/port.c
Original file line number Diff line number Diff line change
Expand Up @@ -157,11 +157,14 @@ typedef void ( * portISR_t )( void );
static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;

/*
* Return the smallest MPU region size that a given number of bytes will fit
* Calculate the smallest MPU region size that a given number of bytes will fit
* into. The region size is returned as the value that should be programmed
* into the region attribute register for that region.
* into the region attribute register for that region, and as a mask that
* should be applied to the base address to ensure it is aligned with its size.
*/
static uint32_t prvGetMPURegionSizeSetting( uint32_t ulActualSizeInBytes ) PRIVILEGED_FUNCTION;
static void prvGetMPURegionSizeSetting( uint32_t ulActualSizeInBytes,
uint32_t * ulRegionSizeSetting,
uint32_t * ulBaseAddressMask ) PRIVILEGED_FUNCTION;

/*
* Setup the timer to generate the tick interrupts. The implementation in this
Expand Down Expand Up @@ -1135,47 +1138,61 @@ static void prvSetupMPU( void )
/* Check the expected MPU is present. */
if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
{
uint32_t ulRegionSizeSetting, ulBaseAddressMask;

/* First setup the unprivileged flash for unprivileged read only access. */
portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __FLASH_segment_start__ ) | /* Base address. */
prvGetMPURegionSizeSetting( ( uint32_t ) __FLASH_segment_end__ - ( uint32_t ) __FLASH_segment_start__,
&( ulRegionSizeSetting ),
&( ulBaseAddressMask ) );
portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __FLASH_segment_start__ & ulBaseAddressMask ) | /* Base address. */
( portMPU_REGION_VALID ) |
( portUNPRIVILEGED_FLASH_REGION );

portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_READ_ONLY ) |
( portMPU_REGION_CACHEABLE_BUFFERABLE ) |
( prvGetMPURegionSizeSetting( ( uint32_t ) __FLASH_segment_end__ - ( uint32_t ) __FLASH_segment_start__ ) ) |
( ulRegionSizeSetting ) |
( portMPU_REGION_ENABLE );

/* Setup the privileged flash for privileged only access. This is where
* the kernel code is * placed. */
portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __privileged_functions_start__ ) | /* Base address. */
prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_functions_end__ - ( uint32_t ) __privileged_functions_start__,
&( ulRegionSizeSetting ),
&( ulBaseAddressMask ) );
portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __privileged_functions_start__ & ulBaseAddressMask ) | /* Base address. */
( portMPU_REGION_VALID ) |
( portPRIVILEGED_FLASH_REGION );

portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_PRIVILEGED_READ_ONLY ) |
( portMPU_REGION_CACHEABLE_BUFFERABLE ) |
( prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_functions_end__ - ( uint32_t ) __privileged_functions_start__ ) ) |
( ulRegionSizeSetting ) |
( portMPU_REGION_ENABLE );

/* Setup the privileged data RAM region. This is where the kernel data
* is placed. */
portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __privileged_data_start__ ) | /* Base address. */
prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_data_end__ - ( uint32_t ) __privileged_data_start__,
&( ulRegionSizeSetting ),
&( ulBaseAddressMask ) );
portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __privileged_data_start__ & ulBaseAddressMask ) | /* Base address. */
( portMPU_REGION_VALID ) |
( portPRIVILEGED_RAM_REGION );

portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
( portMPU_REGION_CACHEABLE_BUFFERABLE ) |
( portMPU_REGION_EXECUTE_NEVER ) |
prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_data_end__ - ( uint32_t ) __privileged_data_start__ ) |
( ulRegionSizeSetting ) |
( portMPU_REGION_ENABLE );

/* By default allow everything to access the general peripherals. The
* system peripherals and registers are protected. */
portMPU_REGION_BASE_ADDRESS_REG = ( portPERIPHERALS_START_ADDRESS ) |
prvGetMPURegionSizeSetting( portPERIPHERALS_END_ADDRESS - portPERIPHERALS_START_ADDRESS,
&( ulRegionSizeSetting ),
&( ulBaseAddressMask ) );
portMPU_REGION_BASE_ADDRESS_REG = ( portPERIPHERALS_START_ADDRESS & ulBaseAddressMask ) |
( portMPU_REGION_VALID ) |
( portGENERAL_PERIPHERALS_REGION );

portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_READ_WRITE | portMPU_REGION_EXECUTE_NEVER ) |
( prvGetMPURegionSizeSetting( portPERIPHERALS_END_ADDRESS - portPERIPHERALS_START_ADDRESS ) ) |
( ulRegionSizeSetting ) |
( portMPU_REGION_ENABLE );

/* Enable the memory fault exception. */
Expand All @@ -1187,7 +1204,9 @@ static void prvSetupMPU( void )
}
/*-----------------------------------------------------------*/

static uint32_t prvGetMPURegionSizeSetting( uint32_t ulActualSizeInBytes )
static void prvGetMPURegionSizeSetting( uint32_t ulActualSizeInBytes,
uint32_t * ulRegionSizeSetting,
uint32_t * ulBaseAddressMask )
{
uint32_t ulRegionSize, ulReturnValue = 4;

Expand All @@ -1205,9 +1224,12 @@ static uint32_t prvGetMPURegionSizeSetting( uint32_t ulActualSizeInBytes )
}
}

/* Shift the code by one before returning so it can be written directly
/* Shift the code by one so it can be written directly
* into the correct bit position of the attribute register. */
return( ulReturnValue << 1UL );
*ulRegionSizeSetting = ulReturnValue << 1UL;

/* Prepare base address mask to ensure alignment */
*ulBaseAddressMask = ~( ulRegionSize - 1UL );
}
/*-----------------------------------------------------------*/

Expand Down Expand Up @@ -1279,16 +1301,20 @@ void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,
if( xRegions == NULL )
{
/* No MPU regions are specified so allow access to all RAM. */
uint32_t ulRegionSizeSetting, ulBaseAddressMask;
prvGetMPURegionSizeSetting( ( uint32_t ) __SRAM_segment_end__ - ( uint32_t ) __SRAM_segment_start__,
&( ulRegionSizeSetting ),
&( ulBaseAddressMask ) );
xMPUSettings->xRegion[ 0 ].ulRegionBaseAddress =
( ( uint32_t ) __SRAM_segment_start__ ) | /* Base address. */
( ( uint32_t ) __SRAM_segment_start__ & ulBaseAddressMask ) | /* Base address. */
( portMPU_REGION_VALID ) |
( portSTACK_REGION ); /* Region number. */
( portSTACK_REGION ); /* Region number. */

xMPUSettings->xRegion[ 0 ].ulRegionAttribute =
( portMPU_REGION_READ_WRITE ) |
( portMPU_REGION_CACHEABLE_BUFFERABLE ) |
( portMPU_REGION_EXECUTE_NEVER ) |
( prvGetMPURegionSizeSetting( ( uint32_t ) __SRAM_segment_end__ - ( uint32_t ) __SRAM_segment_start__ ) ) |
( ulRegionSizeSetting ) |
( portMPU_REGION_ENABLE );

xMPUSettings->xRegionSettings[ 0 ].ulRegionStartAddress = ( uint32_t ) __SRAM_segment_start__;
Expand All @@ -1315,15 +1341,19 @@ void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,
if( uxStackDepth > 0 )
{
/* Define the region that allows access to the stack. */
uint32_t ulRegionSizeSetting, ulBaseAddressMask;
prvGetMPURegionSizeSetting( ( uint32_t ) ( uxStackDepth * ( configSTACK_DEPTH_TYPE ) sizeof( StackType_t ) ),
&( ulRegionSizeSetting ),
&( ulBaseAddressMask ) );
xMPUSettings->xRegion[ 0 ].ulRegionBaseAddress =
( ( uint32_t ) pxBottomOfStack ) |
( ( uint32_t ) pxBottomOfStack & ulBaseAddressMask ) |
( portMPU_REGION_VALID ) |
( portSTACK_REGION ); /* Region number. */

xMPUSettings->xRegion[ 0 ].ulRegionAttribute =
( portMPU_REGION_READ_WRITE ) |
( portMPU_REGION_EXECUTE_NEVER ) |
( prvGetMPURegionSizeSetting ( ( uint32_t ) ( uxStackDepth * ( configSTACK_DEPTH_TYPE ) sizeof( StackType_t ) ) ) ) |
( ulRegionSizeSetting ) |
( portMPU_REGION_CACHEABLE_BUFFERABLE ) |
( portMPU_REGION_ENABLE );
xMPUSettings->xRegionSettings[ 0 ].ulRegionStartAddress = ( uint32_t ) pxBottomOfStack;
Expand All @@ -1342,13 +1372,17 @@ void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,
/* Translate the generic region definition contained in
* xRegions into the CM3 specific MPU settings that are then
* stored in xMPUSettings. */
uint32_t ulRegionSizeSetting, ulBaseAddressMask;
prvGetMPURegionSizeSetting( xRegions[ lIndex ].ulLengthInBytes,
&( ulRegionSizeSetting ),
&( ulBaseAddressMask ) );
xMPUSettings->xRegion[ ul ].ulRegionBaseAddress =
( ( uint32_t ) xRegions[ lIndex ].pvBaseAddress ) |
( ( uint32_t ) xRegions[ lIndex ].pvBaseAddress & ulBaseAddressMask ) |
( portMPU_REGION_VALID ) |
( ul - 1UL ); /* Region number. */

xMPUSettings->xRegion[ ul ].ulRegionAttribute =
( prvGetMPURegionSizeSetting( xRegions[ lIndex ].ulLengthInBytes ) ) |
( ulRegionSizeSetting ) |
( xRegions[ lIndex ].ulParameters ) |
( portMPU_REGION_ENABLE );

Expand Down
Loading