mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-08-19 17:48:33 -04:00
Memory Protection Unit (MPU) Enhancements (#705)
Memory Protection Unit (MPU) Enhancements This commit introduces a new MPU wrapper that places additional restrictions on unprivileged tasks. The following is the list of changes introduced with the new MPU wrapper: 1. Opaque and indirectly verifiable integers for kernel object handles: All the kernel object handles (for example, queue handles) are now opaque integers. Previously object handles were raw pointers. 2. Saving the task context in Task Control Block (TCB): When a task is swapped out by the scheduler, the task's context is now saved in its TCB. Previously the task's context was saved on its stack. 3. Execute system calls on a separate privileged only stack: FreeRTOS system calls, which execute with elevated privilege, now use a separate privileged only stack. Previously system calls used the calling task's stack. The application writer can control the size of the system call stack using new configSYSTEM_CALL_STACK_SIZE config macro. 4. Memory bounds checks: FreeRTOS system calls which accept a pointer and de-reference it, now verify that the calling task has required permissions to access the memory location referenced by the pointer. 5. System call restrictions: The following system calls are no longer available to unprivileged tasks: - vQueueDelete - xQueueCreateMutex - xQueueCreateMutexStatic - xQueueCreateCountingSemaphore - xQueueCreateCountingSemaphoreStatic - xQueueGenericCreate - xQueueGenericCreateStatic - xQueueCreateSet - xQueueRemoveFromSet - xQueueGenericReset - xTaskCreate - xTaskCreateStatic - vTaskDelete - vTaskPrioritySet - vTaskSuspendAll - xTaskResumeAll - xTaskGetHandle - xTaskCallApplicationTaskHook - vTaskList - vTaskGetRunTimeStats - xTaskCatchUpTicks - xEventGroupCreate - xEventGroupCreateStatic - vEventGroupDelete - xStreamBufferGenericCreate - xStreamBufferGenericCreateStatic - vStreamBufferDelete - xStreamBufferReset Also, an unprivileged task can no longer use vTaskSuspend to suspend any task other than itself. We thank the following people for their inputs in these enhancements: - David Reiss of Meta Platforms, Inc. - Lan Luo, Xinhui Shao, Yumeng Wei, Zixia Liu, Huaiyu Yan and Zhen Ling of School of Computer Science and Engineering, Southeast University, China. - Xinwen Fu of Department of Computer Science, University of Massachusetts Lowell, USA. - Yuequi Chen, Zicheng Wang, Minghao Lin of University of Colorado Boulder, USA.
This commit is contained in:
parent
18e2937239
commit
97050a17aa
123 changed files with 94802 additions and 6515 deletions
|
@ -107,6 +107,13 @@
|
|||
#define portPRIGROUP_SHIFT ( 8UL )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Constants used during system call enter and exit.
|
||||
*/
|
||||
#define portPSR_STACK_PADDING_MASK ( 1UL << 9UL )
|
||||
#define portEXC_RETURN_STACK_FRAME_TYPE_MASK ( 1UL << 4UL )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Constants required to manipulate the FPU.
|
||||
*/
|
||||
|
@ -123,6 +130,14 @@
|
|||
#define portFPCCR_LSPEN_MASK ( 1UL << portFPCCR_LSPEN_POS )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Offsets in the stack to the parameters when inside the SVC handler.
|
||||
*/
|
||||
#define portOFFSET_TO_LR ( 5 )
|
||||
#define portOFFSET_TO_PC ( 6 )
|
||||
#define portOFFSET_TO_PSR ( 7 )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Constants required to manipulate the MPU.
|
||||
*/
|
||||
|
@ -148,6 +163,8 @@
|
|||
#define portMPU_RBAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */
|
||||
#define portMPU_RLAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */
|
||||
|
||||
#define portMPU_RBAR_ACCESS_PERMISSIONS_MASK ( 3UL << 1UL )
|
||||
|
||||
#define portMPU_MAIR_ATTR0_POS ( 0UL )
|
||||
#define portMPU_MAIR_ATTR0_MASK ( 0x000000ff )
|
||||
|
||||
|
@ -191,6 +208,30 @@
|
|||
|
||||
/* Expected value of the portMPU_TYPE register. */
|
||||
#define portEXPECTED_MPU_TYPE_VALUE ( configTOTAL_MPU_REGIONS << 8UL )
|
||||
|
||||
/* Extract first address of the MPU region as encoded in the
|
||||
* RBAR (Region Base Address Register) value. */
|
||||
#define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \
|
||||
( ( rbar ) & portMPU_RBAR_ADDRESS_MASK )
|
||||
|
||||
/* Extract last address of the MPU region as encoded in the
|
||||
* RLAR (Region Limit Address Register) value. */
|
||||
#define portEXTRACT_LAST_ADDRESS_FROM_RLAR( rlar ) \
|
||||
( ( ( rlar ) & portMPU_RLAR_ADDRESS_MASK ) | ~portMPU_RLAR_ADDRESS_MASK )
|
||||
|
||||
/* Does addr lies within [start, end] address range? */
|
||||
#define portIS_ADDRESS_WITHIN_RANGE( addr, start, end ) \
|
||||
( ( ( addr ) >= ( start ) ) && ( ( addr ) <= ( end ) ) )
|
||||
|
||||
/* Is the access request satisfied by the available permissions? */
|
||||
#define portIS_AUTHORIZED( accessRequest, permissions ) \
|
||||
( ( ( permissions ) & ( accessRequest ) ) == accessRequest )
|
||||
|
||||
/* Max value that fits in a uint32_t type. */
|
||||
#define portUINT32_MAX ( ~( ( uint32_t ) 0 ) )
|
||||
|
||||
/* Check if adding a and b will result in overflow. */
|
||||
#define portADD_UINT32_WILL_OVERFLOW( a, b ) ( ( a ) > ( portUINT32_MAX - ( b ) ) )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
|
@ -311,6 +352,19 @@ static void prvTaskExitError( void );
|
|||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
|
||||
/**
|
||||
* @brief Extract MPU region's access permissions from the Region Base Address
|
||||
* Register (RBAR) value.
|
||||
*
|
||||
* @param ulRBARValue RBAR value for the MPU region.
|
||||
*
|
||||
* @return uint32_t Access permissions.
|
||||
*/
|
||||
static uint32_t prvGetRegionAccessPermissions( uint32_t ulRBARValue ) PRIVILEGED_FUNCTION;
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
|
||||
/**
|
||||
* @brief Setup the Memory Protection Unit (MPU).
|
||||
*/
|
||||
|
@ -365,6 +419,60 @@ void SysTick_Handler( void ) PRIVILEGED_FUNCTION;
|
|||
* @brief C part of SVC handler.
|
||||
*/
|
||||
portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIVILEGED_FUNCTION;
|
||||
|
||||
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
|
||||
|
||||
/**
|
||||
* @brief Sets up the system call stack so that upon returning from
|
||||
* SVC, the system call stack is used.
|
||||
*
|
||||
* It is used for the system calls with up to 4 parameters.
|
||||
*
|
||||
* @param pulTaskStack The current SP when the SVC was raised.
|
||||
* @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
|
||||
*/
|
||||
void vSystemCallEnter( uint32_t * pulTaskStack, uint32_t ulLR ) PRIVILEGED_FUNCTION;
|
||||
|
||||
#endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||
|
||||
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
|
||||
|
||||
/**
|
||||
* @brief Sets up the system call stack so that upon returning from
|
||||
* SVC, the system call stack is used.
|
||||
*
|
||||
* It is used for the system calls with 5 parameters.
|
||||
*
|
||||
* @param pulTaskStack The current SP when the SVC was raised.
|
||||
* @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
|
||||
*/
|
||||
void vSystemCallEnter_1( uint32_t * pulTaskStack, uint32_t ulLR ) PRIVILEGED_FUNCTION;
|
||||
|
||||
#endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||
|
||||
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
|
||||
|
||||
/**
|
||||
* @brief Sets up the task stack so that upon returning from
|
||||
* SVC, the task stack is used again.
|
||||
*
|
||||
* @param pulSystemCallStack The current SP when the SVC was raised.
|
||||
* @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
|
||||
*/
|
||||
void vSystemCallExit( uint32_t * pulSystemCallStack, uint32_t ulLR ) PRIVILEGED_FUNCTION;
|
||||
|
||||
#endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
|
||||
/**
|
||||
* @brief Checks whether or not the calling task is privileged.
|
||||
*
|
||||
* @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
|
||||
*/
|
||||
BaseType_t xPortIsTaskPrivileged( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
#endif /* configENABLE_MPU == 1 */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
|
@ -681,6 +789,26 @@ static void prvTaskExitError( void )
|
|||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
static uint32_t prvGetRegionAccessPermissions( uint32_t ulRBARValue ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
uint32_t ulAccessPermissions = 0;
|
||||
|
||||
if( ( ulRBARValue & portMPU_RBAR_ACCESS_PERMISSIONS_MASK ) == portMPU_REGION_READ_ONLY )
|
||||
{
|
||||
ulAccessPermissions = tskMPU_READ_PERMISSION;
|
||||
}
|
||||
|
||||
if( ( ulRBARValue & portMPU_RBAR_ACCESS_PERMISSIONS_MASK ) == portMPU_REGION_READ_WRITE )
|
||||
{
|
||||
ulAccessPermissions = ( tskMPU_READ_PERMISSION | tskMPU_WRITE_PERMISSION );
|
||||
}
|
||||
|
||||
return ulAccessPermissions;
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
static void prvSetupMPU( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
|
@ -853,7 +981,7 @@ void SysTick_Handler( void ) /* PRIVILEGED_FUNCTION */
|
|||
|
||||
void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTION portDONT_DISCARD */
|
||||
{
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
|
||||
#if defined( __ARMCC_VERSION )
|
||||
|
||||
/* Declaration when these variable are defined in code instead of being
|
||||
|
@ -865,7 +993,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
|
|||
extern uint32_t __syscalls_flash_start__[];
|
||||
extern uint32_t __syscalls_flash_end__[];
|
||||
#endif /* defined( __ARMCC_VERSION ) */
|
||||
#endif /* configENABLE_MPU */
|
||||
#endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
|
||||
|
||||
uint32_t ulPC;
|
||||
|
||||
|
@ -880,7 +1008,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
|
|||
|
||||
/* Register are stored on the stack in the following order - R0, R1, R2, R3,
|
||||
* R12, LR, PC, xPSR. */
|
||||
ulPC = pulCallerStackAddress[ 6 ];
|
||||
ulPC = pulCallerStackAddress[ portOFFSET_TO_PC ];
|
||||
ucSVCNumber = ( ( uint8_t * ) ulPC )[ -2 ];
|
||||
|
||||
switch( ucSVCNumber )
|
||||
|
@ -951,18 +1079,18 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
|
|||
vRestoreContextOfFirstTask();
|
||||
break;
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
case portSVC_RAISE_PRIVILEGE:
|
||||
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
|
||||
case portSVC_RAISE_PRIVILEGE:
|
||||
|
||||
/* Only raise the privilege, if the svc was raised from any of
|
||||
* the system calls. */
|
||||
if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) &&
|
||||
( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) )
|
||||
{
|
||||
vRaisePrivilege();
|
||||
}
|
||||
break;
|
||||
#endif /* configENABLE_MPU */
|
||||
/* Only raise the privilege, if the svc was raised from any of
|
||||
* the system calls. */
|
||||
if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) &&
|
||||
( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) )
|
||||
{
|
||||
vRaisePrivilege();
|
||||
}
|
||||
break;
|
||||
#endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
|
||||
|
||||
default:
|
||||
/* Incorrect SVC call. */
|
||||
|
@ -971,51 +1099,455 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
|
|||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
|
||||
|
||||
void vSystemCallEnter( uint32_t * pulTaskStack, uint32_t ulLR ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
extern TaskHandle_t pxCurrentTCB;
|
||||
xMPU_SETTINGS * pxMpuSettings;
|
||||
uint32_t * pulSystemCallStack;
|
||||
uint32_t ulStackFrameSize, ulSystemCallLocation, i;
|
||||
#if defined( __ARMCC_VERSION )
|
||||
/* Declaration when these variable are defined in code instead of being
|
||||
* exported from linker scripts. */
|
||||
extern uint32_t * __syscalls_flash_start__;
|
||||
extern uint32_t * __syscalls_flash_end__;
|
||||
#else
|
||||
/* Declaration when these variable are exported from linker scripts. */
|
||||
extern uint32_t __syscalls_flash_start__[];
|
||||
extern uint32_t __syscalls_flash_end__[];
|
||||
#endif /* #if defined( __ARMCC_VERSION ) */
|
||||
|
||||
ulSystemCallLocation = pulTaskStack[ portOFFSET_TO_PC ];
|
||||
|
||||
/* If the request did not come from the system call section, do nothing. */
|
||||
if( ( ulSystemCallLocation >= ( uint32_t ) __syscalls_flash_start__ ) &&
|
||||
( ulSystemCallLocation <= ( uint32_t ) __syscalls_flash_end__ ) )
|
||||
{
|
||||
pxMpuSettings = xTaskGetMPUSettings( pxCurrentTCB );
|
||||
pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack;
|
||||
|
||||
/* This is not NULL only for the duration of the system call. */
|
||||
configASSERT( pxMpuSettings->xSystemCallStackInfo.pulTaskStack == NULL );
|
||||
|
||||
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||
{
|
||||
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
|
||||
{
|
||||
/* Extended frame i.e. FPU in use. */
|
||||
ulStackFrameSize = 26;
|
||||
__asm volatile (
|
||||
" vpush {s0} \n" /* Trigger lazy stacking. */
|
||||
" vpop {s0} \n" /* Nullify the affect of the above instruction. */
|
||||
::: "memory"
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Standard frame i.e. FPU not in use. */
|
||||
ulStackFrameSize = 8;
|
||||
}
|
||||
}
|
||||
#else
|
||||
{
|
||||
ulStackFrameSize = 8;
|
||||
}
|
||||
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||
|
||||
/* Make space on the system call stack for the stack frame. */
|
||||
pulSystemCallStack = pulSystemCallStack - ulStackFrameSize;
|
||||
|
||||
/* Copy the stack frame. */
|
||||
for( i = 0; i < ulStackFrameSize; i++ )
|
||||
{
|
||||
pulSystemCallStack[ i ] = pulTaskStack[ i ];
|
||||
}
|
||||
|
||||
/* Store the value of the LR and PSPLIM registers before the SVC was raised. We need to
|
||||
* restore it when we exit from the system call. */
|
||||
pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ];
|
||||
__asm volatile ( "mrs %0, psplim" : "=r" ( pxMpuSettings->xSystemCallStackInfo.ulStackLimitRegisterAtSystemCallEntry ) );
|
||||
|
||||
/* Use the pulSystemCallStack in thread mode. */
|
||||
__asm volatile ( "msr psp, %0" : : "r" ( pulSystemCallStack ) );
|
||||
__asm volatile ( "msr psplim, %0" : : "r" ( pxMpuSettings->xSystemCallStackInfo.pulSystemCallStackLimit ) );
|
||||
|
||||
/* Remember the location where we should copy the stack frame when we exit from
|
||||
* the system call. */
|
||||
pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize;
|
||||
|
||||
/* Record if the hardware used padding to force the stack pointer
|
||||
* to be double word aligned. */
|
||||
if( ( pulTaskStack[ portOFFSET_TO_PSR ] & portPSR_STACK_PADDING_MASK ) == portPSR_STACK_PADDING_MASK )
|
||||
{
|
||||
pxMpuSettings->ulTaskFlags |= portSTACK_FRAME_HAS_PADDING_FLAG;
|
||||
}
|
||||
else
|
||||
{
|
||||
pxMpuSettings->ulTaskFlags &= ( ~portSTACK_FRAME_HAS_PADDING_FLAG );
|
||||
}
|
||||
|
||||
/* We ensure in pxPortInitialiseStack that the system call stack is
|
||||
* double word aligned and therefore, there is no need of padding.
|
||||
* Clear the bit[9] of stacked xPSR. */
|
||||
pulSystemCallStack[ portOFFSET_TO_PSR ] &= ( ~portPSR_STACK_PADDING_MASK );
|
||||
|
||||
/* Raise the privilege for the duration of the system call. */
|
||||
__asm volatile (
|
||||
" mrs r0, control \n" /* Obtain current control value. */
|
||||
" movs r1, #1 \n" /* r1 = 1. */
|
||||
" bics r0, r1 \n" /* Clear nPRIV bit. */
|
||||
" msr control, r0 \n" /* Write back new control value. */
|
||||
::: "r0", "r1", "memory"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
|
||||
|
||||
void vSystemCallEnter_1( uint32_t * pulTaskStack, uint32_t ulLR ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
extern TaskHandle_t pxCurrentTCB;
|
||||
xMPU_SETTINGS * pxMpuSettings;
|
||||
uint32_t * pulSystemCallStack;
|
||||
uint32_t ulStackFrameSize, ulSystemCallLocation, i;
|
||||
#if defined( __ARMCC_VERSION )
|
||||
/* Declaration when these variable are defined in code instead of being
|
||||
* exported from linker scripts. */
|
||||
extern uint32_t * __syscalls_flash_start__;
|
||||
extern uint32_t * __syscalls_flash_end__;
|
||||
#else
|
||||
/* Declaration when these variable are exported from linker scripts. */
|
||||
extern uint32_t __syscalls_flash_start__[];
|
||||
extern uint32_t __syscalls_flash_end__[];
|
||||
#endif /* #if defined( __ARMCC_VERSION ) */
|
||||
|
||||
ulSystemCallLocation = pulTaskStack[ portOFFSET_TO_PC ];
|
||||
|
||||
/* If the request did not come from the system call section, do nothing. */
|
||||
if( ( ulSystemCallLocation >= ( uint32_t ) __syscalls_flash_start__ ) &&
|
||||
( ulSystemCallLocation <= ( uint32_t ) __syscalls_flash_end__ ) )
|
||||
{
|
||||
pxMpuSettings = xTaskGetMPUSettings( pxCurrentTCB );
|
||||
pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack;
|
||||
|
||||
/* This is not NULL only for the duration of the system call. */
|
||||
configASSERT( pxMpuSettings->xSystemCallStackInfo.pulTaskStack == NULL );
|
||||
|
||||
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||
{
|
||||
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
|
||||
{
|
||||
/* Extended frame i.e. FPU in use. */
|
||||
ulStackFrameSize = 26;
|
||||
__asm volatile (
|
||||
" vpush {s0} \n" /* Trigger lazy stacking. */
|
||||
" vpop {s0} \n" /* Nullify the affect of the above instruction. */
|
||||
::: "memory"
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Standard frame i.e. FPU not in use. */
|
||||
ulStackFrameSize = 8;
|
||||
}
|
||||
}
|
||||
#else
|
||||
{
|
||||
ulStackFrameSize = 8;
|
||||
}
|
||||
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||
|
||||
/* Make space on the system call stack for the stack frame and
|
||||
* the parameter passed on the stack. We only need to copy one
|
||||
* parameter but we still reserve 2 spaces to keep the stack
|
||||
* double word aligned. */
|
||||
pulSystemCallStack = pulSystemCallStack - ulStackFrameSize - 2UL;
|
||||
|
||||
/* Copy the stack frame. */
|
||||
for( i = 0; i < ulStackFrameSize; i++ )
|
||||
{
|
||||
pulSystemCallStack[ i ] = pulTaskStack[ i ];
|
||||
}
|
||||
|
||||
/* Copy the parameter which is passed the stack. */
|
||||
if( ( pulTaskStack[ portOFFSET_TO_PSR ] & portPSR_STACK_PADDING_MASK ) == portPSR_STACK_PADDING_MASK )
|
||||
{
|
||||
pulSystemCallStack[ ulStackFrameSize ] = pulTaskStack[ ulStackFrameSize + 1 ];
|
||||
/* Record if the hardware used padding to force the stack pointer
|
||||
* to be double word aligned. */
|
||||
pxMpuSettings->ulTaskFlags |= portSTACK_FRAME_HAS_PADDING_FLAG;
|
||||
}
|
||||
else
|
||||
{
|
||||
pulSystemCallStack[ ulStackFrameSize ] = pulTaskStack[ ulStackFrameSize ];
|
||||
/* Record if the hardware used padding to force the stack pointer
|
||||
* to be double word aligned. */
|
||||
pxMpuSettings->ulTaskFlags &= ( ~portSTACK_FRAME_HAS_PADDING_FLAG );
|
||||
}
|
||||
|
||||
/* Store the value of the LR and PSPLIM registers before the SVC was raised.
|
||||
* We need to restore it when we exit from the system call. */
|
||||
pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ];
|
||||
__asm volatile ( "mrs %0, psplim" : "=r" ( pxMpuSettings->xSystemCallStackInfo.ulStackLimitRegisterAtSystemCallEntry ) );
|
||||
|
||||
/* Use the pulSystemCallStack in thread mode. */
|
||||
__asm volatile ( "msr psp, %0" : : "r" ( pulSystemCallStack ) );
|
||||
__asm volatile ( "msr psplim, %0" : : "r" ( pxMpuSettings->xSystemCallStackInfo.pulSystemCallStackLimit ) );
|
||||
|
||||
/* Remember the location where we should copy the stack frame when we exit from
|
||||
* the system call. */
|
||||
pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize;
|
||||
|
||||
/* We ensure in pxPortInitialiseStack that the system call stack is
|
||||
* double word aligned and therefore, there is no need of padding.
|
||||
* Clear the bit[9] of stacked xPSR. */
|
||||
pulSystemCallStack[ portOFFSET_TO_PSR ] &= ( ~portPSR_STACK_PADDING_MASK );
|
||||
|
||||
/* Raise the privilege for the duration of the system call. */
|
||||
__asm volatile (
|
||||
" mrs r0, control \n" /* Obtain current control value. */
|
||||
" movs r1, #1 \n" /* r1 = 1. */
|
||||
" bics r0, r1 \n" /* Clear nPRIV bit. */
|
||||
" msr control, r0 \n" /* Write back new control value. */
|
||||
::: "r0", "r1", "memory"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
|
||||
|
||||
void vSystemCallExit( uint32_t * pulSystemCallStack, uint32_t ulLR ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
extern TaskHandle_t pxCurrentTCB;
|
||||
xMPU_SETTINGS * pxMpuSettings;
|
||||
uint32_t * pulTaskStack;
|
||||
uint32_t ulStackFrameSize, ulSystemCallLocation, i;
|
||||
#if defined( __ARMCC_VERSION )
|
||||
/* Declaration when these variable are defined in code instead of being
|
||||
* exported from linker scripts. */
|
||||
extern uint32_t * __syscalls_flash_start__;
|
||||
extern uint32_t * __syscalls_flash_end__;
|
||||
#else
|
||||
/* Declaration when these variable are exported from linker scripts. */
|
||||
extern uint32_t __syscalls_flash_start__[];
|
||||
extern uint32_t __syscalls_flash_end__[];
|
||||
#endif /* #if defined( __ARMCC_VERSION ) */
|
||||
|
||||
ulSystemCallLocation = pulSystemCallStack[ portOFFSET_TO_PC ];
|
||||
|
||||
/* If the request did not come from the system call section, do nothing. */
|
||||
if( ( ulSystemCallLocation >= ( uint32_t ) __syscalls_flash_start__ ) &&
|
||||
( ulSystemCallLocation <= ( uint32_t ) __syscalls_flash_end__ ) )
|
||||
{
|
||||
pxMpuSettings = xTaskGetMPUSettings( pxCurrentTCB );
|
||||
pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack;
|
||||
|
||||
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||
{
|
||||
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
|
||||
{
|
||||
/* Extended frame i.e. FPU in use. */
|
||||
ulStackFrameSize = 26;
|
||||
__asm volatile (
|
||||
" vpush {s0} \n" /* Trigger lazy stacking. */
|
||||
" vpop {s0} \n" /* Nullify the affect of the above instruction. */
|
||||
::: "memory"
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Standard frame i.e. FPU not in use. */
|
||||
ulStackFrameSize = 8;
|
||||
}
|
||||
}
|
||||
#else
|
||||
{
|
||||
ulStackFrameSize = 8;
|
||||
}
|
||||
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||
|
||||
/* Make space on the task stack for the stack frame. */
|
||||
pulTaskStack = pulTaskStack - ulStackFrameSize;
|
||||
|
||||
/* Copy the stack frame. */
|
||||
for( i = 0; i < ulStackFrameSize; i++ )
|
||||
{
|
||||
pulTaskStack[ i ] = pulSystemCallStack[ i ];
|
||||
}
|
||||
|
||||
/* Use the pulTaskStack in thread mode. */
|
||||
__asm volatile ( "msr psp, %0" : : "r" ( pulTaskStack ) );
|
||||
|
||||
/* Restore the LR and PSPLIM to what they were at the time of
|
||||
* system call entry. */
|
||||
pulTaskStack[ portOFFSET_TO_LR ] = pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry;
|
||||
__asm volatile ( "msr psplim, %0" : : "r" ( pxMpuSettings->xSystemCallStackInfo.ulStackLimitRegisterAtSystemCallEntry ) );
|
||||
|
||||
/* If the hardware used padding to force the stack pointer
|
||||
* to be double word aligned, set the stacked xPSR bit[9],
|
||||
* otherwise clear it. */
|
||||
if( ( pxMpuSettings->ulTaskFlags & portSTACK_FRAME_HAS_PADDING_FLAG ) == portSTACK_FRAME_HAS_PADDING_FLAG )
|
||||
{
|
||||
pulTaskStack[ portOFFSET_TO_PSR ] |= portPSR_STACK_PADDING_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
pulTaskStack[ portOFFSET_TO_PSR ] &= ( ~portPSR_STACK_PADDING_MASK );
|
||||
}
|
||||
|
||||
/* This is not NULL only for the duration of the system call. */
|
||||
pxMpuSettings->xSystemCallStackInfo.pulTaskStack = NULL;
|
||||
|
||||
/* Drop the privilege before returning to the thread mode. */
|
||||
__asm volatile (
|
||||
" mrs r0, control \n" /* Obtain current control value. */
|
||||
" movs r1, #1 \n" /* r1 = 1. */
|
||||
" orrs r0, r1 \n" /* Set nPRIV bit. */
|
||||
" msr control, r0 \n" /* Write back new control value. */
|
||||
::: "r0", "r1", "memory"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
|
||||
StackType_t * pxEndOfStack,
|
||||
TaskFunction_t pxCode,
|
||||
void * pvParameters,
|
||||
BaseType_t xRunPrivileged ) /* PRIVILEGED_FUNCTION */
|
||||
#else
|
||||
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
|
||||
StackType_t * pxEndOfStack,
|
||||
TaskFunction_t pxCode,
|
||||
void * pvParameters ) /* PRIVILEGED_FUNCTION */
|
||||
#endif /* configENABLE_MPU */
|
||||
/* *INDENT-ON* */
|
||||
|
||||
BaseType_t xPortIsTaskPrivileged( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
BaseType_t xTaskIsPrivileged = pdFALSE;
|
||||
const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */
|
||||
|
||||
if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG )
|
||||
{
|
||||
xTaskIsPrivileged = pdTRUE;
|
||||
}
|
||||
|
||||
return xTaskIsPrivileged;
|
||||
}
|
||||
|
||||
#endif /* configENABLE_MPU == 1 */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
|
||||
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
|
||||
StackType_t * pxEndOfStack,
|
||||
TaskFunction_t pxCode,
|
||||
void * pvParameters,
|
||||
BaseType_t xRunPrivileged,
|
||||
xMPU_SETTINGS * xMPUSettings ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
uint32_t ulIndex = 0;
|
||||
|
||||
xMPUSettings->ulContext[ ulIndex ] = 0x04040404; /* r4. */
|
||||
ulIndex++;
|
||||
xMPUSettings->ulContext[ ulIndex ] = 0x05050505; /* r5. */
|
||||
ulIndex++;
|
||||
xMPUSettings->ulContext[ ulIndex ] = 0x06060606; /* r6. */
|
||||
ulIndex++;
|
||||
xMPUSettings->ulContext[ ulIndex ] = 0x07070707; /* r7. */
|
||||
ulIndex++;
|
||||
xMPUSettings->ulContext[ ulIndex ] = 0x08080808; /* r8. */
|
||||
ulIndex++;
|
||||
xMPUSettings->ulContext[ ulIndex ] = 0x09090909; /* r9. */
|
||||
ulIndex++;
|
||||
xMPUSettings->ulContext[ ulIndex ] = 0x10101010; /* r10. */
|
||||
ulIndex++;
|
||||
xMPUSettings->ulContext[ ulIndex ] = 0x11111111; /* r11. */
|
||||
ulIndex++;
|
||||
|
||||
xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pvParameters; /* r0. */
|
||||
ulIndex++;
|
||||
xMPUSettings->ulContext[ ulIndex ] = 0x01010101; /* r1. */
|
||||
ulIndex++;
|
||||
xMPUSettings->ulContext[ ulIndex ] = 0x02020202; /* r2. */
|
||||
ulIndex++;
|
||||
xMPUSettings->ulContext[ ulIndex ] = 0x03030303; /* r3. */
|
||||
ulIndex++;
|
||||
xMPUSettings->ulContext[ ulIndex ] = 0x12121212; /* r12. */
|
||||
ulIndex++;
|
||||
xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) portTASK_RETURN_ADDRESS; /* LR. */
|
||||
ulIndex++;
|
||||
xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxCode; /* PC. */
|
||||
ulIndex++;
|
||||
xMPUSettings->ulContext[ ulIndex ] = portINITIAL_XPSR; /* xPSR. */
|
||||
ulIndex++;
|
||||
|
||||
#if ( configENABLE_TRUSTZONE == 1 )
|
||||
{
|
||||
xMPUSettings->ulContext[ ulIndex ] = portNO_SECURE_CONTEXT; /* xSecureContext. */
|
||||
ulIndex++;
|
||||
}
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) ( pxTopOfStack - 8 ); /* PSP with the hardware saved stack. */
|
||||
ulIndex++;
|
||||
xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxEndOfStack; /* PSPLIM. */
|
||||
ulIndex++;
|
||||
if( xRunPrivileged == pdTRUE )
|
||||
{
|
||||
xMPUSettings->ulTaskFlags |= portTASK_IS_PRIVILEGED_FLAG;
|
||||
xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) portINITIAL_CONTROL_PRIVILEGED; /* CONTROL. */
|
||||
ulIndex++;
|
||||
}
|
||||
else
|
||||
{
|
||||
xMPUSettings->ulTaskFlags &= ( ~portTASK_IS_PRIVILEGED_FLAG );
|
||||
xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) portINITIAL_CONTROL_UNPRIVILEGED; /* CONTROL. */
|
||||
ulIndex++;
|
||||
}
|
||||
xMPUSettings->ulContext[ ulIndex ] = portINITIAL_EXC_RETURN; /* LR (EXC_RETURN). */
|
||||
ulIndex++;
|
||||
|
||||
#if ( configUSE_MPU_WRAPPERS_V1 == 0 )
|
||||
{
|
||||
/* Ensure that the system call stack is double word aligned. */
|
||||
xMPUSettings->xSystemCallStackInfo.pulSystemCallStack = &( xMPUSettings->xSystemCallStackInfo.ulSystemCallStackBuffer[ configSYSTEM_CALL_STACK_SIZE - 1 ] );
|
||||
xMPUSettings->xSystemCallStackInfo.pulSystemCallStack = ( uint32_t * ) ( ( uint32_t ) ( xMPUSettings->xSystemCallStackInfo.pulSystemCallStack ) &
|
||||
( uint32_t ) ( ~( portBYTE_ALIGNMENT_MASK ) ) );
|
||||
|
||||
xMPUSettings->xSystemCallStackInfo.pulSystemCallStackLimit = &( xMPUSettings->xSystemCallStackInfo.ulSystemCallStackBuffer[ 0 ] );
|
||||
xMPUSettings->xSystemCallStackInfo.pulSystemCallStackLimit = ( uint32_t * ) ( ( ( uint32_t ) ( xMPUSettings->xSystemCallStackInfo.pulSystemCallStackLimit ) +
|
||||
( uint32_t ) ( portBYTE_ALIGNMENT - 1 ) ) &
|
||||
( uint32_t ) ( ~( portBYTE_ALIGNMENT_MASK ) ) );
|
||||
|
||||
/* This is not NULL only for the duration of a system call. */
|
||||
xMPUSettings->xSystemCallStackInfo.pulTaskStack = NULL;
|
||||
}
|
||||
#endif /* configUSE_MPU_WRAPPERS_V1 == 0 */
|
||||
|
||||
return &( xMPUSettings->ulContext[ ulIndex ] );
|
||||
}
|
||||
|
||||
#else /* configENABLE_MPU */
|
||||
|
||||
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
|
||||
StackType_t * pxEndOfStack,
|
||||
TaskFunction_t pxCode,
|
||||
void * pvParameters ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
/* Simulate the stack frame as it would be created by a context switch
|
||||
* interrupt. */
|
||||
#if ( portPRELOAD_REGISTERS == 0 )
|
||||
{
|
||||
pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
|
||||
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
|
||||
*pxTopOfStack = portINITIAL_XPSR; /* xPSR. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxCode; /* PC */
|
||||
*pxTopOfStack = ( StackType_t ) pxCode; /* PC. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */
|
||||
*pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR. */
|
||||
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0. */
|
||||
pxTopOfStack -= 9; /* R11..R4, EXC_RETURN. */
|
||||
*pxTopOfStack = portINITIAL_EXC_RETURN;
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
{
|
||||
pxTopOfStack--;
|
||||
|
||||
if( xRunPrivileged == pdTRUE )
|
||||
{
|
||||
*pxTopOfStack = portINITIAL_CONTROL_PRIVILEGED; /* Slot used to hold this task's CONTROL value. */
|
||||
}
|
||||
else
|
||||
{
|
||||
*pxTopOfStack = portINITIAL_CONTROL_UNPRIVILEGED; /* Slot used to hold this task's CONTROL value. */
|
||||
}
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
|
||||
|
||||
|
@ -1029,55 +1561,39 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
|
|||
#else /* portPRELOAD_REGISTERS */
|
||||
{
|
||||
pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
|
||||
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
|
||||
*pxTopOfStack = portINITIAL_XPSR; /* xPSR. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxCode; /* PC */
|
||||
*pxTopOfStack = ( StackType_t ) pxCode; /* PC. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */
|
||||
*pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x12121212UL; /* R12 */
|
||||
*pxTopOfStack = ( StackType_t ) 0x12121212UL; /* R12. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x03030303UL; /* R3 */
|
||||
*pxTopOfStack = ( StackType_t ) 0x03030303UL; /* R3. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x02020202UL; /* R2 */
|
||||
*pxTopOfStack = ( StackType_t ) 0x02020202UL; /* R2. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x01010101UL; /* R1 */
|
||||
*pxTopOfStack = ( StackType_t ) 0x01010101UL; /* R1. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x11111111UL; /* R11 */
|
||||
*pxTopOfStack = ( StackType_t ) 0x11111111UL; /* R11. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x10101010UL; /* R10 */
|
||||
*pxTopOfStack = ( StackType_t ) 0x10101010UL; /* R10. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x09090909UL; /* R09 */
|
||||
*pxTopOfStack = ( StackType_t ) 0x09090909UL; /* R09. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x08080808UL; /* R08 */
|
||||
*pxTopOfStack = ( StackType_t ) 0x08080808UL; /* R08. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x07070707UL; /* R07 */
|
||||
*pxTopOfStack = ( StackType_t ) 0x07070707UL; /* R07. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x06060606UL; /* R06 */
|
||||
*pxTopOfStack = ( StackType_t ) 0x06060606UL; /* R06. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x05050505UL; /* R05 */
|
||||
*pxTopOfStack = ( StackType_t ) 0x05050505UL; /* R05. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x04040404UL; /* R04 */
|
||||
*pxTopOfStack = ( StackType_t ) 0x04040404UL; /* R04. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = portINITIAL_EXC_RETURN; /* EXC_RETURN */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
{
|
||||
pxTopOfStack--;
|
||||
|
||||
if( xRunPrivileged == pdTRUE )
|
||||
{
|
||||
*pxTopOfStack = portINITIAL_CONTROL_PRIVILEGED; /* Slot used to hold this task's CONTROL value. */
|
||||
}
|
||||
else
|
||||
{
|
||||
*pxTopOfStack = portINITIAL_CONTROL_UNPRIVILEGED; /* Slot used to hold this task's CONTROL value. */
|
||||
}
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
*pxTopOfStack = portINITIAL_EXC_RETURN; /* EXC_RETURN. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
|
||||
|
||||
|
@ -1092,6 +1608,8 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
|
|||
|
||||
return pxTopOfStack;
|
||||
}
|
||||
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
|
||||
|
@ -1347,6 +1865,54 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
|
|||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
BaseType_t xPortIsAuthorizedToAccessBuffer( const void * pvBuffer,
|
||||
uint32_t ulBufferLength,
|
||||
uint32_t ulAccessRequested ) /* PRIVILEGED_FUNCTION */
|
||||
|
||||
{
|
||||
uint32_t i, ulBufferStartAddress, ulBufferEndAddress;
|
||||
BaseType_t xAccessGranted = pdFALSE;
|
||||
const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */
|
||||
|
||||
if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG )
|
||||
{
|
||||
xAccessGranted = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( portADD_UINT32_WILL_OVERFLOW( ( ( uint32_t ) pvBuffer ), ( ulBufferLength - 1UL ) ) == pdFALSE )
|
||||
{
|
||||
ulBufferStartAddress = ( uint32_t ) pvBuffer;
|
||||
ulBufferEndAddress = ( ( ( uint32_t ) pvBuffer ) + ulBufferLength - 1UL );
|
||||
|
||||
for( i = 0; i < portTOTAL_NUM_REGIONS; i++ )
|
||||
{
|
||||
/* Is the MPU region enabled? */
|
||||
if( ( xTaskMpuSettings->xRegionsSettings[ i ].ulRLAR & portMPU_RLAR_REGION_ENABLE ) == portMPU_RLAR_REGION_ENABLE )
|
||||
{
|
||||
if( portIS_ADDRESS_WITHIN_RANGE( ulBufferStartAddress,
|
||||
portEXTRACT_FIRST_ADDRESS_FROM_RBAR( xTaskMpuSettings->xRegionsSettings[ i ].ulRBAR ),
|
||||
portEXTRACT_LAST_ADDRESS_FROM_RLAR( xTaskMpuSettings->xRegionsSettings[ i ].ulRLAR ) ) &&
|
||||
portIS_ADDRESS_WITHIN_RANGE( ulBufferEndAddress,
|
||||
portEXTRACT_FIRST_ADDRESS_FROM_RBAR( xTaskMpuSettings->xRegionsSettings[ i ].ulRBAR ),
|
||||
portEXTRACT_LAST_ADDRESS_FROM_RLAR( xTaskMpuSettings->xRegionsSettings[ i ].ulRLAR ) ) &&
|
||||
portIS_AUTHORIZED( ulAccessRequested,
|
||||
prvGetRegionAccessPermissions( xTaskMpuSettings->xRegionsSettings[ i ].ulRBAR ) ) )
|
||||
{
|
||||
xAccessGranted = pdTRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return xAccessGranted;
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortIsInsideInterrupt( void )
|
||||
{
|
||||
uint32_t ulCurrentInterrupt;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue