Remove the default peripheral MPU region from the port. Add declarations of private functions to the top of port.c

This commit is contained in:
Soren Ptak 2024-02-01 15:00:33 -05:00
parent 9cf6c26a29
commit ec1332e1f4
2 changed files with 81 additions and 66 deletions

View file

@ -53,27 +53,89 @@
* become unmasked before the scheduler starts. As it is stored as part of the * become unmasked before the scheduler starts. As it is stored as part of the
* task context it will be set to 0 when the first task is started. * task context it will be set to 0 when the first task is started.
*/ */
PRIVILEGED_DATA volatile uint32_t ulCriticalNesting = 0xFFFF; PRIVILEGED_DATA volatile UBaseType_t ulCriticalNesting = 0xFFFF;
/** @brief Set to 1 to pend a context switch from an ISR. /** @brief Set to 1 to pend a context switch from an ISR.
* @ingroup Interrupt Management * @ingroup Interrupt Management
*/ */
PRIVILEGED_DATA volatile uint32_t ulPortYieldRequired = pdFALSE; PRIVILEGED_DATA volatile UBaseType_t ulPortYieldRequired = pdFALSE;
/** /**
* @brief Interrupt nesting depth, used to count the number of interrupts to unwind. * @brief Interrupt nesting depth, used to count the number of interrupts to unwind.
* @ingroup Interrupt Management * @ingroup Interrupt Management
*/ */
PRIVILEGED_DATA volatile uint32_t ulPortInterruptNesting = 0UL; PRIVILEGED_DATA volatile UBaseType_t ulPortInterruptNesting = 0UL;
/** /**
* @brief Variable to track whether or not the scheduler has been started. * @brief Variable to track whether or not the scheduler has been started.
* @ingroup Scheduler * @ingroup Scheduler
* @note This variable is set to pdTRUE when the scheduler is started. * @note This is the port specific version of the Kernel's xSchedulerRunning
*/ */
PRIVILEGED_DATA static BaseType_t prvPortSchedulerRunning = pdFALSE; PRIVILEGED_DATA static BaseType_t prvPortSchedulerRunning = pdFALSE;
/*---------------------------------------------------------------------------*/ /* -------------------------- Private Function Declarations -------------------------- */
/**
* @brief Determine if a FreeRTOS Task has been granted access to a memory region.
*
* @param xTaskMPURegion Pointer to a single set of MPU region registers.
* @param ulRegionStart Base address of the memory region access is being requested.
* @param ulRegionLength The length of the memory region that access is being requested.
* @param ulAccessRequested The type of access being requested, either read or write.
* @return BaseType_t pdTRUE if the task can access the region, pdFALSE otherwise
*
* @ingroup Task Context
* @ingroup MPU Control
*/
PRIVILEGED_FUNCTION static BaseType_t prvTaskCanAccessRegion(
const xMPU_REGION_REGISTERS * xTaskMPURegion,
const uint32_t ulRegionStart,
const uint32_t ulRegionLength,
const uint32_t ulAccessRequested
);
/**
* @brief Determine smallest MPU Region Setting for a number of bytes.
*
* @ingroup MPU Control
*
* @param ulActualSizeInBytes Number of bytes to find a valid MPU region size for.
* @return uint32_t The smallest MPU region size that can hold the requested bytes.
*/
PRIVILEGED_FUNCTION static uint32_t prvGetMPURegionSizeSetting(
uint32_t ulActualSizeInBytes
);
/** @brief Set up a default MPU memory Map
* @return PRIVILEGED_FUNCTION VOID
* @ingroup MPU Control
* @note This function shall be called before calling vPortStartFirstTask().
* @note This function works by pulling variables from the linker script.
* Ensure that the variables used in your linker script match up with the variable names
* used at the start of this function.
*/
PRIVILEGED_FUNCTION static void prvSetupMPU( void );
/**
* @brief Determine if a FreeRTOS Task has been granted access to a memory region.
*
* @param xTaskMPURegion Pointer to a single set of MPU region registers.
* @param ulRegionStart Base address of the memory region access is being requested.
* @param ulRegionLength The length of the memory region that access is being requested.
* @param ulAccessRequested The type of access being requested, either read or write.
* @return BaseType_t pdTRUE if the task can access the region, pdFALSE otherwise
*
* @ingroup Task Context
* @ingroup MPU Control
*/
PRIVILEGED_FUNCTION static BaseType_t prvTaskCanAccessRegion(
const xMPU_REGION_REGISTERS * xTaskMPURegion,
const uint32_t ulRegionStart,
const uint32_t ulRegionLength,
const uint32_t ulAccessRequested
);
/* ----------------------------------------------------------------------------------- */
/** /**
* @brief Set a FreeRTOS Task's initial context. * @brief Set a FreeRTOS Task's initial context.
@ -264,16 +326,7 @@ PRIVILEGED_DATA static BaseType_t prvPortSchedulerRunning = pdFALSE;
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
/* PRIVILEGED_FUNCTION */ static uint32_t prvGetMPURegionSizeSetting(
/**
* @brief Determine smallest MPU Region Setting for a number of bytes.
*
* @ingroup MPU Control
*
* @param ulActualSizeInBytes Number of bytes to find a valid MPU region size for.
* @return uint32_t The smallest MPU region size that can hold the requested bytes.
*/
PRIVILEGED_FUNCTION static uint32_t prvGetMPURegionSizeSetting(
uint32_t ulActualSizeInBytes uint32_t ulActualSizeInBytes
) )
{ {
@ -424,19 +477,10 @@ PRIVILEGED_FUNCTION static uint32_t prvGetMPURegionSizeSetting(
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
/** @brief Set up a default MPU memory Map /* PRIVILEGED_FUNCTION */ static void prvSetupMPU( void )
* @return PRIVILEGED_FUNCTION VOID
* @ingroup MPU Control
* @note This function shall be called before calling vPortStartFirstTask().
* @note This function works by pulling variables from the linker script.
* Ensure that the variables used in your linker script match up with the variable names
* used at the start of this function.
*/
PRIVILEGED_FUNCTION static void prvSetupMPU( void )
{ {
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code. */
* exported from linker scripts. */
/* Sections used for FLASH */ /* Sections used for FLASH */
extern uint32_t * __FLASH_segment_start__; extern uint32_t * __FLASH_segment_start__;
extern uint32_t * __FLASH_segment_end__; extern uint32_t * __FLASH_segment_end__;
@ -449,10 +493,6 @@ PRIVILEGED_FUNCTION static void prvSetupMPU( void )
extern uint32_t * __privileged_data_start__; extern uint32_t * __privileged_data_start__;
extern uint32_t * __privileged_data_end__; extern uint32_t * __privileged_data_end__;
/* Sections used for system peripherals, such as UART */
extern uint32_t * __peripherals_start__;
extern uint32_t * __peripherals_end__;
#else #else
/* Declaration when these variable are exported from linker scripts. */ /* Declaration when these variable are exported from linker scripts. */
/* Sections used for FLASH */ /* Sections used for FLASH */
@ -467,9 +507,6 @@ PRIVILEGED_FUNCTION static void prvSetupMPU( void )
extern uint32_t __privileged_data_start__[]; extern uint32_t __privileged_data_start__[];
extern uint32_t __privileged_data_end__[]; extern uint32_t __privileged_data_end__[];
/* Sections used for system peripherals, such as UART */
extern uint32_t __peripherals_start__[];
extern uint32_t __peripherals_end__[];
#endif /* if defined( __ARMCC_VERSION ) */ #endif /* if defined( __ARMCC_VERSION ) */
uint32_t ulRegionStart; uint32_t ulRegionStart;
uint32_t ulRegionEnd; uint32_t ulRegionEnd;
@ -506,21 +543,7 @@ PRIVILEGED_FUNCTION static void prvSetupMPU( void )
portMPU_PRIV_RO_USER_NA_EXEC | portMPU_NORMAL_OIWTNOWA_SHARED portMPU_PRIV_RO_USER_NA_EXEC | portMPU_NORMAL_OIWTNOWA_SHARED
); );
/* MPU Region for Peripheral Usage */ /* Privileged Write and Read Access for PRIVILEGED_DATA. */
ulRegionStart = ( uint32_t ) __peripherals_start__;
ulRegionEnd = ( uint32_t ) __peripherals_end__;
ulRegionLength = ulRegionEnd - ulRegionStart;
ulRegionLength = prvGetMPURegionSizeSetting( ulRegionLength );
ulRegionLength |= portMPU_REGION_ENABLE;
vMPUSetRegion(
portGENERAL_PERIPHERALS_REGION,
ulRegionStart,
ulRegionLength,
portMPU_PRIV_RW_USER_RW_NOEXEC | portMPU_DEVICE_NONSHAREABLE
);
/* Privileged Write and Read, Unprivileged no access, MPU Region for PRIVILEGED_DATA. */
ulRegionStart = ( uint32_t ) __privileged_data_start__; ulRegionStart = ( uint32_t ) __privileged_data_start__;
ulRegionEnd = ( uint32_t ) __privileged_data_end__; ulRegionEnd = ( uint32_t ) __privileged_data_end__;
ulRegionLength = ulRegionEnd - ulRegionStart; ulRegionLength = ulRegionEnd - ulRegionStart;
@ -542,21 +565,9 @@ PRIVILEGED_FUNCTION static void prvSetupMPU( void )
vMPUEnable(); vMPUEnable();
} }
/* ------------------------------------------------------------------------- */ /* ----------------------------------------------------------------------------------- */
/** /* PRIVILEGED_FUNCTION */ static BaseType_t prvTaskCanAccessRegion(
* @brief Determine if a FreeRTOS Task has been granted access to a memory region.
*
* @param xTaskMPURegion Pointer to a single set of MPU region registers.
* @param ulRegionStart Base address of the memory region access is being requested.
* @param ulRegionLength The length of the memory region that access is being requested.
* @param ulAccessRequested The type of access being requested, either read or write.
* @return BaseType_t pdTRUE if the task can access the region, pdFALSE otherwise
*
* @ingroup Task Context
* @ingroup MPU Control
*/
PRIVILEGED_FUNCTION static BaseType_t prvTaskCanAccessRegion(
const xMPU_REGION_REGISTERS * xTaskMPURegion, const xMPU_REGION_REGISTERS * xTaskMPURegion,
const uint32_t ulRegionStart, const uint32_t ulRegionStart,
const uint32_t ulRegionLength, const uint32_t ulRegionLength,
@ -570,6 +581,10 @@ PRIVILEGED_FUNCTION static BaseType_t prvTaskCanAccessRegion(
uint32_t ulTaskRegionLength = 2UL << ( xTaskMPURegion->ulRegionSize >> 1UL ); uint32_t ulTaskRegionLength = 2UL << ( xTaskMPURegion->ulRegionSize >> 1UL );
uint32_t ulTaskRegionEnd = xTaskMPURegion->ulRegionBaseAddress + ulTaskRegionLength; uint32_t ulTaskRegionEnd = xTaskMPURegion->ulRegionBaseAddress + ulTaskRegionLength;
/* Perform three different checks:
* 1. Ensure region being accessed is after the start of an MPU Region
* 2. Ensure region being accessed is before the end of the MPU Region
* 3. Ensure region being accessed ends after the start of the MPU region */
if( ( ulRegionStart >= xTaskMPURegion->ulRegionBaseAddress ) && if( ( ulRegionStart >= xTaskMPURegion->ulRegionBaseAddress ) &&
( ulRegionEnd <= ulTaskRegionEnd ) && ( ulRegionEnd >= ulRegionStart ) ) ( ulRegionEnd <= ulTaskRegionEnd ) && ( ulRegionEnd >= ulRegionStart ) )
{ {
@ -685,7 +700,7 @@ PRIVILEGED_FUNCTION static BaseType_t prvTaskCanAccessRegion(
* @return BaseType_t This function is not meant to be returned from. * @return BaseType_t This function is not meant to be returned from.
* If it does return it returns pdFALSE to mark that the scheduler could not be started. * If it does return it returns pdFALSE to mark that the scheduler could not be started.
*/ */
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ BaseType_t xPortStartScheduler( void )
{ {
/* Start the timer that generates the tick ISR. */ /* Start the timer that generates the tick ISR. */
configSETUP_TICK_INTERRUPT(); configSETUP_TICK_INTERRUPT();
@ -696,6 +711,7 @@ BaseType_t xPortStartScheduler( void )
/* Configure the regions in the MPU that are common to all tasks. */ /* Configure the regions in the MPU that are common to all tasks. */
prvSetupMPU(); prvSetupMPU();
/* Mark the port specific scheduler running variable as true */
prvPortSchedulerRunning = pdTRUE; prvPortSchedulerRunning = pdTRUE;
/* Load the context of the first task, starting the FreeRTOS-Scheduler's control. */ /* Load the context of the first task, starting the FreeRTOS-Scheduler's control. */

View file

@ -164,9 +164,8 @@ extern "C" {
/* Default MPU regions */ /* Default MPU regions */
#define portFIRST_CONFIGURABLE_REGION ( 0 ) #define portFIRST_CONFIGURABLE_REGION ( 0 )
#define portLAST_CONFIGURABLE_REGION ( portMPU_TOTAL_REGIONS - 6UL ) #define portLAST_CONFIGURABLE_REGION ( portMPU_TOTAL_REGIONS - 5UL )
#define portSTACK_REGION ( portMPU_TOTAL_REGIONS - 5UL ) #define portSTACK_REGION ( portMPU_TOTAL_REGIONS - 4UL )
#define portGENERAL_PERIPHERALS_REGION ( portMPU_TOTAL_REGIONS - 4UL )
#define portUNPRIVILEGED_FLASH_REGION ( portMPU_TOTAL_REGIONS - 3UL ) #define portUNPRIVILEGED_FLASH_REGION ( portMPU_TOTAL_REGIONS - 3UL )
#define portPRIVILEGED_FLASH_REGION ( portMPU_TOTAL_REGIONS - 2UL ) #define portPRIVILEGED_FLASH_REGION ( portMPU_TOTAL_REGIONS - 2UL )
#define portPRIVILEGED_RAM_REGION ( portMPU_TOTAL_REGIONS - 1UL ) #define portPRIVILEGED_RAM_REGION ( portMPU_TOTAL_REGIONS - 1UL )