Update system call entry mechanism (#896)

Earlier the System Call entry from an unprivileged task looked like:

1. SVC for entering system call.
2. System call implementation.
3. SVC for exiting system call.

Now, the system call entry needs to make only one system call
and everything else is handled internally.

This PR also makes the following small changes:

1. Add one struct param for system calls with 5 parameters. This
   removes the need for special handling for system calls with 5
   parameters.
2. Remove raise privilege SVC when MPU wrapper v2 is used.
3. Add additional run time parameter checks to MPU wrappers
   for xTaskGenericNotify and xQueueTakeMutexRecursive APIs.

These changes are tested on the following platforms:
1. STM32H743ZI (Cortex-M7)
2. STM32L152RE (Cortex-M3)
3. Nuvoton M2351 (Cortex-M23)
4. NXP LPC55S69 (Cortex-M33)
This commit is contained in:
Gaurav-Aggarwal-AWS 2023-11-21 18:42:23 +05:30 committed by GitHub
parent 52c1c6e578
commit 9bfd85a253
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
115 changed files with 46168 additions and 54704 deletions

596
portable/IAR/ARM_CM4F_MPU/port.c Executable file → Normal file
View file

@ -41,6 +41,7 @@
/* Scheduler includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "mpu_syscall_numbers.h"
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
@ -232,31 +233,26 @@ extern void vPortRestoreContextOfFirstTask( void ) PRIVILEGED_FUNCTION;
#if ( 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;
/**
* @brief Sets up the system call stack so that upon returning from
* SVC, the system call stack is used.
*
* @param pulTaskStack The current SP when the SVC was raised.
* @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
* @param ucSystemCallNumber The system call number of the system call.
*/
void vSystemCallEnter( uint32_t * pulTaskStack,
uint32_t ulLR,
uint8_t ucSystemCallNumber ) PRIVILEGED_FUNCTION;
#endif /* #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
#if ( 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;
/**
* @brief Raise SVC for exiting from a system call.
*/
void vRequestSystemCallExit( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
#endif /* #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
@ -269,7 +265,8 @@ extern void vPortRestoreContextOfFirstTask( void ) PRIVILEGED_FUNCTION;
* @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;
void vSystemCallExit( uint32_t * pulSystemCallStack,
uint32_t ulLR ) PRIVILEGED_FUNCTION;
#endif /* #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
@ -359,10 +356,10 @@ void vPortSVCHandler_C( uint32_t * pulParam ) /* PRIVILEGED_FUNCTION */
uint8_t ucSVCNumber;
uint32_t ulPC;
#if ( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 )
#if ( ( configUSE_MPU_WRAPPERS_V1 == 1 ) && ( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 ) )
extern uint32_t __syscalls_flash_start__[];
extern uint32_t __syscalls_flash_end__[];
#endif /* #if( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 ) */
#endif /* #if ( ( configUSE_MPU_WRAPPERS_V1 == 1 ) && ( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 ) ) */
/* The stack contains: r0, r1, r2, r3, r12, LR, PC and xPSR. The first
* argument (r0) is pulParam[ 0 ]. */
@ -388,26 +385,15 @@ void vPortSVCHandler_C( uint32_t * pulParam ) /* PRIVILEGED_FUNCTION */
break;
#if ( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 )
case portSVC_RAISE_PRIVILEGE: /* Only raise the privilege, if the
* svc was raised from any of the
* system calls. */
#if ( configUSE_MPU_WRAPPERS_V1 == 1 )
#if ( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 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__ ) )
{
__asm volatile
(
" mrs r1, control \n" /* Obtain current control value. */
" bic r1, r1, #1 \n" /* Set privilege bit. */
" msr control, r1 \n" /* Write back new control value. */
::: "r1", "memory"
);
}
break;
#else /* if ( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 ) */
case portSVC_RAISE_PRIVILEGE:
if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) &&
( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) )
{
__asm volatile
(
" mrs r1, control \n" /* Obtain current control value. */
@ -415,299 +401,259 @@ void vPortSVCHandler_C( uint32_t * pulParam ) /* PRIVILEGED_FUNCTION */
" msr control, r1 \n" /* Write back new control value. */
::: "r1", "memory"
);
break;
#endif /* #if( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 ) */
}
default: /* Unknown SVC call. */
break;
break;
#else /* if ( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 ) */
case portSVC_RAISE_PRIVILEGE:
__asm volatile
(
" mrs r1, control \n" /* Obtain current control value. */
" bic r1, r1, #1 \n" /* Set privilege bit. */
" msr control, r1 \n" /* Write back new control value. */
::: "r1", "memory"
);
break;
#endif /* #if( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 ) */
#endif /* #if ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
default: /* Unknown SVC call. */
break;
}
}
/*-----------------------------------------------------------*/
#if ( 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__ ) )
void vSystemCallEnter( uint32_t * pulTaskStack,
uint32_t ulLR,
uint8_t ucSystemCallNumber ) /* PRIVILEGED_FUNCTION */
{
extern TaskHandle_t pxCurrentTCB;
extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ];
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 ];
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( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
/* Checks:
* 1. SVC is raised from the system call section (i.e. application is
* not raising SVC directly).
* 2. pxMpuSettings->xSystemCallStackInfo.pulTaskStack must be NULL as
* it is non-NULL only during the execution of a system call (i.e.
* between system call enter and exit).
* 3. System call is not for a kernel API disabled by the configuration
* in FreeRTOSConfig.h.
* 4. We do not need to check that ucSystemCallNumber is within range
* because the assembly SVC handler checks that before calling
* this function.
*/
if( ( ulSystemCallLocation >= ( uint32_t ) __syscalls_flash_start__ ) &&
( ulSystemCallLocation <= ( uint32_t ) __syscalls_flash_end__ ) &&
( pxMpuSettings->xSystemCallStackInfo.pulTaskStack == NULL ) &&
( uxSystemCallImplementations[ ucSystemCallNumber ] != ( UBaseType_t ) 0 ) )
{
/* 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"
);
pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack;
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;
}
/* 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 ];
}
/* Use the pulSystemCallStack in thread mode. */
__asm volatile ( "msr psp, %0" : : "r" ( pulSystemCallStack ) );
/* Raise the privilege for the duration of the system call. */
__asm volatile
(
" mrs r1, control \n" /* Obtain current control value. */
" bic r1, #1 \n" /* Clear nPRIV bit. */
" msr control, r1 \n" /* Write back new control value. */
::: "r1", "memory"
);
/* Remember the location where we should copy the stack frame when we exit from
* the system call. */
pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize;
/* Store the value of the Link Register before the SVC was raised.
* It contains the address of the caller of the System Call entry
* point (i.e. the caller of the MPU_<API>). We need to restore it
* when we exit from the system call. */
pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ];
/* Start executing the system call upon returning from this handler. */
pulSystemCallStack[ portOFFSET_TO_PC ] = uxSystemCallImplementations[ ucSystemCallNumber ];
/* Raise a request to exit from the system call upon finishing the
* system call. */
pulSystemCallStack[ portOFFSET_TO_LR ] = ( uint32_t ) vRequestSystemCallExit;
/* 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 );
}
else
{
/* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8;
}
/* 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 ];
}
/* Use the pulSystemCallStack in thread mode. */
__asm volatile ( "msr psp, %0" : : "r" ( pulSystemCallStack ) );
/* Raise the privilege for the duration of the system call. */
__asm volatile (
" mrs r1, control \n" /* Obtain current control value. */
" bic r1, #1 \n" /* Clear nPRIV bit. */
" msr control, r1 \n" /* Write back new control value. */
::: "r1", "memory"
);
/* Remember the location where we should copy the stack frame when we exit from
* the system call. */
pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize;
/* Store the value of the Link Register before the SVC was raised. We need to
* restore it when we exit from the system call. */
pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ];
/* 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 );
}
}
#endif /* #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
/*-----------------------------------------------------------*/
#if ( 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__ ) )
void vRequestSystemCallExit( void ) /* __attribute__( ( naked ) ) PRIVILEGED_FUNCTION */
{
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( ( 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;
}
/* 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 );
}
/* Use the pulSystemCallStack in thread mode. */
__asm volatile ( "msr psp, %0" : : "r" ( pulSystemCallStack ) );
/* Raise the privilege for the duration of the system call. */
__asm volatile (
" mrs r1, control \n" /* Obtain current control value. */
" bic r1, #1 \n" /* Clear nPRIV bit. */
" msr control, r1 \n" /* Write back new control value. */
::: "r1", "memory"
);
/* Remember the location where we should copy the stack frame when we exit from
* the system call. */
pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize;
/* Store the value of the Link Register before the SVC was raised. We need to
* restore it when we exit from the system call. */
pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ];
/* 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 );
__asm volatile ( "svc %0 \n" ::"i" ( portSVC_SYSTEM_CALL_EXIT ) : "memory" );
}
}
#endif /* #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
/*-----------------------------------------------------------*/
#if ( 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__ ) )
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 * __privileged_functions_start__;
extern uint32_t * __privileged_functions_end__;
#else
/* Declaration when these variable are exported from linker scripts. */
extern uint32_t __privileged_functions_start__[];
extern uint32_t __privileged_functions_end__[];
#endif /* #if defined( __ARMCC_VERSION ) */
ulSystemCallLocation = pulSystemCallStack[ portOFFSET_TO_PC ];
pxMpuSettings = xTaskGetMPUSettings( pxCurrentTCB );
pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack;
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
/* Checks:
* 1. SVC is raised from the privileged code (i.e. application is not
* raising SVC directly). This SVC is only raised from
* vRequestSystemCallExit which is in the privileged code section.
* 2. pxMpuSettings->xSystemCallStackInfo.pulTaskStack must not be NULL -
* this means that we previously entered a system call and the
* application is not attempting to exit without entering a system
* call.
*/
if( ( ulSystemCallLocation >= ( uint32_t ) __privileged_functions_start__ ) &&
( ulSystemCallLocation <= ( uint32_t ) __privileged_functions_end__ ) &&
( pxMpuSettings->xSystemCallStackInfo.pulTaskStack != NULL ) )
{
/* 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"
);
pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack;
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;
}
/* 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 ) );
/* Drop the privilege before returning to the thread mode. */
__asm volatile
(
" mrs r1, control \n" /* Obtain current control value. */
" orr r1, #1 \n" /* Set nPRIV bit. */
" msr control, r1 \n" /* Write back new control value. */
::: "r1", "memory"
);
/* Return to the caller of the System Call entry point (i.e. the
* caller of the MPU_<API>). */
pulTaskStack[ portOFFSET_TO_PC ] = pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry;
/* Ensure that LR has a valid value.*/
pulTaskStack[ portOFFSET_TO_LR ] = pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry;
/* 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;
}
else
{
/* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8;
}
/* 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 ) );
/* Drop the privilege before returning to the thread mode. */
__asm volatile (
" mrs r1, control \n" /* Obtain current control value. */
" orr r1, #1 \n" /* Set nPRIV bit. */
" msr control, r1 \n" /* Write back new control value. */
::: "r1", "memory"
);
/* Restore the stacked link register to what it was at the time of
* system call entry. */
pulTaskStack[ portOFFSET_TO_LR ] = pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry;
/* 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;
}
}
#endif /* #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
/*-----------------------------------------------------------*/
@ -736,7 +682,6 @@ BaseType_t xPortStartScheduler( void )
#if ( configENABLE_ERRATA_837070_WORKAROUND == 1 )
configASSERT( ( portCPUID == portCORTEX_M7_r0p1_ID ) || ( portCPUID == portCORTEX_M7_r0p0_ID ) );
#else
/* When using this port on a Cortex-M7 r0p0 or r0p1 core, define
* configENABLE_ERRATA_837070_WORKAROUND to 1 in your
* FreeRTOSConfig.h. */
@ -793,22 +738,22 @@ BaseType_t xPortStartScheduler( void )
if( ulImplementedPrioBits == 8 )
{
/* When the hardware implements 8 priority bits, there is no way for
* the software to configure PRIGROUP to not have sub-priorities. As
* a result, the least significant bit is always used for sub-priority
* and there are 128 preemption priorities and 2 sub-priorities.
*
* This may cause some confusion in some cases - for example, if
* configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4
* priority interrupts will be masked in Critical Sections as those
* are at the same preemption priority. This may appear confusing as
* 4 is higher (numerically lower) priority than
* configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not
* have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY
* to 4, this confusion does not happen and the behaviour remains the same.
*
* The following assert ensures that the sub-priority bit in the
* configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned
* confusion. */
* the software to configure PRIGROUP to not have sub-priorities. As
* a result, the least significant bit is always used for sub-priority
* and there are 128 preemption priorities and 2 sub-priorities.
*
* This may cause some confusion in some cases - for example, if
* configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4
* priority interrupts will be masked in Critical Sections as those
* are at the same preemption priority. This may appear confusing as
* 4 is higher (numerically lower) priority than
* configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not
* have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY
* to 4, this confusion does not happen and the behaviour remains the same.
*
* The following assert ensures that the sub-priority bit in the
* configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned
* confusion. */
configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U );
ulMaxPRIGROUPValue = 0;
}
@ -1122,10 +1067,10 @@ void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,
( prvGetMPURegionSizeSetting( ( uint32_t ) __SRAM_segment_end__ - ( uint32_t ) __SRAM_segment_start__ ) ) |
( portMPU_REGION_ENABLE );
xMPUSettings->xRegionSettings[ 0 ].ulRegionStartAddress = ( uint32_t ) __SRAM_segment_start__;
xMPUSettings->xRegionSettings[ 0 ].ulRegionEndAddress = ( uint32_t ) __SRAM_segment_end__;
xMPUSettings->xRegionSettings[ 0 ].ulRegionPermissions = ( tskMPU_READ_PERMISSION |
tskMPU_WRITE_PERMISSION );
xMPUSettings->xRegionSettings[ 0 ].ulRegionStartAddress = ( uint32_t ) __SRAM_segment_start__;
xMPUSettings->xRegionSettings[ 0 ].ulRegionEndAddress = ( uint32_t ) __SRAM_segment_end__;
xMPUSettings->xRegionSettings[ 0 ].ulRegionPermissions = ( tskMPU_READ_PERMISSION |
tskMPU_WRITE_PERMISSION );
/* Invalidate user configurable regions. */
for( ul = 1UL; ul <= portNUM_CONFIGURABLE_REGIONS; ul++ )
@ -1163,7 +1108,6 @@ void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,
( ulStackDepth * ( uint32_t ) sizeof( StackType_t ) ) - 1UL );
xMPUSettings->xRegionSettings[ 0 ].ulRegionPermissions = ( tskMPU_READ_PERMISSION |
tskMPU_WRITE_PERMISSION );
}
lIndex = 0;
@ -1185,14 +1129,16 @@ void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,
( xRegions[ lIndex ].ulParameters ) |
( portMPU_REGION_ENABLE );
xMPUSettings->xRegionSettings[ ul ].ulRegionStartAddress = ( uint32_t) xRegions[ lIndex ].pvBaseAddress;
xMPUSettings->xRegionSettings[ ul ].ulRegionStartAddress = ( uint32_t ) xRegions[ lIndex ].pvBaseAddress;
xMPUSettings->xRegionSettings[ ul ].ulRegionEndAddress = ( uint32_t ) ( ( uint32_t ) xRegions[ lIndex ].pvBaseAddress + xRegions[ lIndex ].ulLengthInBytes - 1UL );
xMPUSettings->xRegionSettings[ ul ].ulRegionPermissions = 0UL;
if( ( ( xRegions[ lIndex ].ulParameters & portMPU_REGION_READ_ONLY ) == portMPU_REGION_READ_ONLY ) ||
( ( xRegions[ lIndex ].ulParameters & portMPU_REGION_PRIVILEGED_READ_WRITE_UNPRIV_READ_ONLY ) == portMPU_REGION_PRIVILEGED_READ_WRITE_UNPRIV_READ_ONLY ) )
{
xMPUSettings->xRegionSettings[ ul ].ulRegionPermissions = tskMPU_READ_PERMISSION;
}
if( ( xRegions[ lIndex ].ulParameters & portMPU_REGION_READ_WRITE ) == portMPU_REGION_READ_WRITE )
{
xMPUSettings->xRegionSettings[ ul ].ulRegionPermissions = ( tskMPU_READ_PERMISSION | tskMPU_WRITE_PERMISSION );