Add in functions to enable and disable the MPU background region. Add the calls to it in the MPU Setup function. Change the port's scheduler running variable name so it is different from the Kernels. Fix two incorrect comments SPSR -> CPSR

This commit is contained in:
Soren Ptak 2024-02-01 12:42:02 -05:00
parent fe424a116e
commit 9cf6c26a29
5 changed files with 73 additions and 11 deletions

View file

@ -72,7 +72,7 @@ vPortSystemCallExit:
.weak xPortIsPrivileged
.type xPortIsPrivileged, %function
xPortIsPrivileged:
/* Load value of SPSR into R0 */
/* Load value of CPSR into R0 */
MRS R0, CPSR
/* Get the relevant mode bits */
AND R0, R0, #0x1F
@ -82,6 +82,7 @@ xPortIsPrivileged:
MOVEQ R0, #0x0
/* Otherwise set R0 to 1 for the return */
MOVNE R0, #0x01
/* Return to the caller */
BLX LR
/*-------------------------------------------------------------------------------*/
@ -102,7 +103,7 @@ ulPortCountLeadingZeros:
.macro processorInUserMode
/* Push R0 before using it */
PUSH {R0}
/* Load value of SPSR into R0 */
/* Load value of CPSR into R0 */
MRS R0, CPSR
/* Get the relevant mode bits */
AND R0, R0, #0x1F

View file

@ -71,7 +71,7 @@ PRIVILEGED_DATA volatile uint32_t ulPortInterruptNesting = 0UL;
* @ingroup Scheduler
* @note This variable is set to pdTRUE when the scheduler is started.
*/
PRIVILEGED_DATA static BaseType_t xSchedulerRunning = pdFALSE;
PRIVILEGED_DATA static BaseType_t prvPortSchedulerRunning = pdFALSE;
/*---------------------------------------------------------------------------*/
@ -534,6 +534,10 @@ PRIVILEGED_FUNCTION static void prvSetupMPU( void )
portMPU_PRIV_RW_USER_NA_NOEXEC | portMPU_NORMAL_OIWTNOWA_SHARED
);
/* Enable the MPU Background region, allows privileged operating modes access to
* unmapped regions of memory without generating a fault. */
vMPUEnableBackgroundRegion();
/* After setting default regions, enable the MPU */
vMPUEnable();
}
@ -611,7 +615,7 @@ PRIVILEGED_FUNCTION static BaseType_t prvTaskCanAccessRegion(
xMPU_SETTINGS * xTaskMPUSettings = NULL;
xMPU_REGION_REGISTERS * xTaskMPURegion = NULL;
if( pdFALSE == xSchedulerRunning )
if( pdFALSE == prvPortSchedulerRunning )
{
/* Before the scheduler starts an unknown task will be pxCurrentTCB */
xAccessGranted = pdTRUE;
@ -692,7 +696,7 @@ BaseType_t xPortStartScheduler( void )
/* Configure the regions in the MPU that are common to all tasks. */
prvSetupMPU();
xSchedulerRunning = pdTRUE;
prvPortSchedulerRunning = pdTRUE;
/* Load the context of the first task, starting the FreeRTOS-Scheduler's control. */
vPortStartFirstTask();
@ -717,7 +721,7 @@ BaseType_t xPortStartScheduler( void )
BaseType_t xAccessGranted = pdFALSE;
const xMPU_SETTINGS * xTaskMpuSettings;
if( pdFALSE == xSchedulerRunning )
if( pdFALSE == prvPortSchedulerRunning )
{
/* Grant access to all the kernel objects before the scheduler
* is started. It is necessary because there is no task running
@ -831,10 +835,10 @@ void prvTaskExitError( void )
*/
void vPortEndScheduler( void )
{
xSchedulerRunning = pdFALSE;
prvPortSchedulerRunning = pdFALSE;
/* Not implemented in ports where there is nothing to return to.
* Artificially force an assert. */
configASSERT( xSchedulerRunning );
configASSERT( prvPortSchedulerRunning );
}
/*---------------------------------------------------------------------------*/

View file

@ -121,7 +121,7 @@
/* Load the first per-task MPU region into R5 */
MOV R5, #portFIRST_CONFIGURABLE_REGION
/* When creating a loop label in a macro it has to be a numeric label.
* For (R5 = portFIRST_CONFIGURABLE_REGION ; R5 <= portSTACK_REGION ; R5++ ) */
* For (R5 = portFIRST_CONFIGURABLE_REGION ; R5 <= portNUM_CONFIGURABLE_REGIONS ; R5++ ) */
123:
/* Load values of struct MPU_REGION_REGISTERS into R2-R4 */
LDMIA R1!, { R2-R4 }
@ -142,7 +142,7 @@
/* R5++ */
ADD R5, R5, #1
/* R5 <= R6 */
CMP R5, #portSTACK_REGION
CMP R5, #portNUM_CONFIGURABLE_REGIONS
/* R5 <= R6, loop again */
BLE 123b
/* R5 > portSTACK_REGION, all MPU regions have been restored */
@ -496,6 +496,45 @@ vMPUDisable:
/* Return to caller */
BX LR
/* ----------------------------------------------------------------------------------- */
/* Enable the MPU Background Region */
.align 4
.global vMPUEnableBackgroundRegion
.type vMPUEnableBackgroundRegion, %function
vMPUEnableBackgroundRegion:
/* Save value in R0 */
PUSH { R0 }
/* Read CP15 System Control Register into R0 */
MRC p15, 0, R0, c1, c0, 0
/* Set bit 17 so that privileged modes won't trigger unmapped MPU region faults */
ORR R0, R0, #0x20000
/* Write the value back out */
MCR p15, 0, R0, c1, c0, 0
/* Restore the used register */
POP { R0 }
/* Return to the caller */
BX LR
/* ----------------------------------------------------------------------------------- */
/* Disable the MPU Background Region */
.align 4
.global vMPUDisableBackgroundRegion
.type vMPUDisableBackgroundRegion, %function
vMPUDisableBackgroundRegion:
/* Save value in R0 */
PUSH { R0 }
/* Read CP15 System Control Register into R0 */
MRC p15, 0, R0, c1, c0, 0
/* Clear bit 17 so that privileged modes won't trigger unmapped MPU region faults */
BIC R0, R0, #0x20000
/* Write the value back out */
MCR p15, 0, R0, c1, c0, 0
/* Restore the used register */
POP { R0 }
/* Return to the caller */
BX LR
/* ----------------------------------------------------------------------------------- */
.align 4
.global FreeRTOS_IRQ_Handler
.type FreeRTOS_IRQ_Handler, %function

View file

@ -69,7 +69,6 @@ extern "C" {
#endif /* configPROTECTED_KERNEL_OBJECT_POOL_SIZE */
/**
* @brief The size in Bytes that the Privileged System Call Stack should be.
*
@ -397,6 +396,23 @@ void vMPUEnable( void );
*/
void vMPUDisable( void );
/**
* @brief Enable the MPU Background Region.
*
* @ingroup MPU Control
*
* @return void
*/
void vMPUEnableBackgroundRegion( void );
/**
* @brief Disable the MPU Background Region
*
* @ingroup MPU Control
*
* @return void
*/
void vMPUDisableBackgroundRegion( void );
/**
* @brief Assembly routine to set permissions for an MPU Region.
*

View file

@ -133,12 +133,14 @@ extern "C" {
/**
* @brief SVC Number to use when requesting a context swap.
* @ingroup Scheduler
* @note This value must not be in use in mpu_syscall_numbers.h
*/
#define portSVC_YIELD 0x0100
/**
* @brief SVC Number to use when exiting a FreeRTOS System Call.
* @ingroup MPU Control
* @note This value must not be in use in mpu_syscall_numbers.h
*/
#define portSVC_SYSTEM_CALL_EXIT 0x0104