Updates to CM4_MPU IAR port

- System calls are now only allowed from kernel code. This change can be turned on
  or off using configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY.
- MPU is disabled before reprogramming it and enabled afterwards to be compliant
  with ARM recommendations.
pull/8/head
Gaurav Aggarwal 5 years ago
parent b27fb82bc1
commit 96b6746364

@ -33,8 +33,8 @@
#include <intrinsics.h> #include <intrinsics.h>
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
all the API functions to use the MPU wrappers. That should only be done when * all the API functions to use the MPU wrappers. That should only be done when
task.h is included from an application file. */ * task.h is included from an application file. */
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
/* Scheduler includes. */ /* Scheduler includes. */
@ -43,8 +43,6 @@ task.h is included from an application file. */
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
#warning This is not yet a documented port as it has not been fully tested, so no demo projects that use this port are provided.
#ifndef __ARMVFP__ #ifndef __ARMVFP__
#error This port can only be used when the project options are configured to enable hardware floating point support. #error This port can only be used when the project options are configured to enable hardware floating point support.
#endif #endif
@ -94,7 +92,7 @@ task.h is included from an application file. */
#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL ) #define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL )
/* Constants used to detect a Cortex-M7 r0p1 core, which should use the ARM_CM7 /* Constants used to detect a Cortex-M7 r0p1 core, which should use the ARM_CM7
r0p1 port. */ * r0p1 port. */
#define portCPUID ( * ( ( volatile uint32_t * ) 0xE000ed00 ) ) #define portCPUID ( * ( ( volatile uint32_t * ) 0xE000ed00 ) )
#define portCORTEX_M7_r0p1_ID ( 0x410FC271UL ) #define portCORTEX_M7_r0p1_ID ( 0x410FC271UL )
#define portCORTEX_M7_r0p0_ID ( 0x410FC270UL ) #define portCORTEX_M7_r0p0_ID ( 0x410FC270UL )
@ -222,10 +220,10 @@ static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged ) StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged )
{ {
/* Simulate the stack frame as it would be created by a context switch /* Simulate the stack frame as it would be created by a context switch
interrupt. */ * interrupt. */
/* Offset added to account for the way the MCU uses the stack on entry/exit /* Offset added to account for the way the MCU uses the stack on entry/exit
of interrupts, and to ensure alignment. */ * of interrupts, and to ensure alignment. */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */ *pxTopOfStack = portINITIAL_XPSR; /* xPSR */
@ -239,7 +237,7 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
/* A save method is being used that requires each task to maintain its /* A save method is being used that requires each task to maintain its
own exec return value. */ * own exec return value. */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = portINITIAL_EXC_RETURN; *pxTopOfStack = portINITIAL_EXC_RETURN;
@ -261,10 +259,16 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
void vPortSVCHandler_C( uint32_t *pulParam ) void vPortSVCHandler_C( uint32_t *pulParam )
{ {
uint8_t ucSVCNumber; uint8_t ucSVCNumber;
uint32_t ulPC;
/* The stack contains: r0, r1, r2, r3, r12, r14, the return address and #if( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 )
xPSR. The first argument (r0) is pulParam[ 0 ]. */ extern uint32_t __syscalls_flash_start__[];
ucSVCNumber = ( ( uint8_t * ) pulParam[ portOFFSET_TO_PC ] )[ -2 ]; extern uint32_t __syscalls_flash_end__[];
#endif /* #if( 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 ]. */
ulPC = pulParam[ portOFFSET_TO_PC ];
ucSVCNumber = ( ( uint8_t * ) ulPC )[ -2 ];
switch( ucSVCNumber ) switch( ucSVCNumber )
{ {
case portSVC_START_SCHEDULER : portNVIC_SYSPRI1_REG |= portNVIC_SVC_PRI; case portSVC_START_SCHEDULER : portNVIC_SYSPRI1_REG |= portNVIC_SVC_PRI;
@ -273,14 +277,31 @@ uint8_t ucSVCNumber;
case portSVC_YIELD : portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; case portSVC_YIELD : portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
/* Barriers are normally not required /* Barriers are normally not required
but do ensure the code is completely * but do ensure the code is completely
within the specified behaviour for the * within the specified behaviour for the
architecture. */ * architecture. */
__asm volatile( "dsb" ::: "memory" ); __asm volatile( "dsb" ::: "memory" );
__asm volatile( "isb" ); __asm volatile( "isb" );
break; 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( 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
case portSVC_RAISE_PRIVILEGE : __asm volatile case portSVC_RAISE_PRIVILEGE : __asm volatile
( (
" mrs r1, control \n" /* Obtain current control value. */ " mrs r1, control \n" /* Obtain current control value. */
@ -289,6 +310,7 @@ uint8_t ucSVCNumber;
::: "r1", "memory" ::: "r1", "memory"
); );
break; break;
#endif /* #if( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 ) */
default : /* Unknown SVC call. */ default : /* Unknown SVC call. */
break; break;
@ -302,12 +324,12 @@ uint8_t ucSVCNumber;
BaseType_t xPortStartScheduler( void ) BaseType_t xPortStartScheduler( void )
{ {
/* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. /* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0.
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ * See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
configASSERT( configMAX_SYSCALL_INTERRUPT_PRIORITY ); configASSERT( configMAX_SYSCALL_INTERRUPT_PRIORITY );
/* This port can be used on all revisions of the Cortex-M7 core other than /* This port can be used on all revisions of the Cortex-M7 core other than
the r0p1 parts. r0p1 parts should use the port from the * the r0p1 parts. r0p1 parts should use the port from the
/source/portable/GCC/ARM_CM7/r0p1 directory. */ * /source/portable/GCC/ARM_CM7/r0p1 directory. */
configASSERT( portCPUID != portCORTEX_M7_r0p1_ID ); configASSERT( portCPUID != portCORTEX_M7_r0p1_ID );
configASSERT( portCPUID != portCORTEX_M7_r0p0_ID ); configASSERT( portCPUID != portCORTEX_M7_r0p0_ID );
@ -318,15 +340,15 @@ BaseType_t xPortStartScheduler( void )
volatile uint8_t ucMaxPriorityValue; volatile uint8_t ucMaxPriorityValue;
/* Determine the maximum priority from which ISR safe FreeRTOS API /* Determine the maximum priority from which ISR safe FreeRTOS API
functions can be called. ISR safe functions are those that end in * functions can be called. ISR safe functions are those that end in
"FromISR". FreeRTOS maintains separate thread and ISR API functions to * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
ensure interrupt entry is as fast and simple as possible. * ensure interrupt entry is as fast and simple as possible.
Save the interrupt priority value that is about to be clobbered. */ Save the interrupt priority value that is about to be clobbered. */
ulOriginalPriority = *pucFirstUserPriorityRegister; ulOriginalPriority = *pucFirstUserPriorityRegister;
/* Determine the number of priority bits available. First write to all /* Determine the number of priority bits available. First write to all
possible bits. */ * possible bits. */
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE; *pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
/* Read the value back to see how many bits stuck. */ /* Read the value back to see how many bits stuck. */
@ -336,7 +358,7 @@ BaseType_t xPortStartScheduler( void )
ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
/* Calculate the maximum acceptable priority group value for the number /* Calculate the maximum acceptable priority group value for the number
of bits read back. */ * of bits read back. */
ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS; ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS;
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
{ {
@ -347,8 +369,8 @@ BaseType_t xPortStartScheduler( void )
#ifdef __NVIC_PRIO_BITS #ifdef __NVIC_PRIO_BITS
{ {
/* Check the CMSIS configuration that defines the number of /* Check the CMSIS configuration that defines the number of
priority bits matches the number of priority bits actually queried * priority bits matches the number of priority bits actually queried
from the hardware. */ * from the hardware. */
configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == __NVIC_PRIO_BITS ); configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == __NVIC_PRIO_BITS );
} }
#endif #endif
@ -356,19 +378,19 @@ BaseType_t xPortStartScheduler( void )
#ifdef configPRIO_BITS #ifdef configPRIO_BITS
{ {
/* Check the FreeRTOS configuration that defines the number of /* Check the FreeRTOS configuration that defines the number of
priority bits matches the number of priority bits actually queried * priority bits matches the number of priority bits actually queried
from the hardware. */ * from the hardware. */
configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == configPRIO_BITS ); configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == configPRIO_BITS );
} }
#endif #endif
/* Shift the priority group value back to its position within the AIRCR /* Shift the priority group value back to its position within the AIRCR
register. */ * register. */
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
/* Restore the clobbered interrupt priority register to its original /* Restore the clobbered interrupt priority register to its original
value. */ * value. */
*pucFirstUserPriorityRegister = ulOriginalPriority; *pucFirstUserPriorityRegister = ulOriginalPriority;
} }
#endif /* conifgASSERT_DEFINED */ #endif /* conifgASSERT_DEFINED */
@ -381,7 +403,7 @@ BaseType_t xPortStartScheduler( void )
prvSetupMPU(); prvSetupMPU();
/* Start the timer that generates the tick ISR. Interrupts are disabled /* Start the timer that generates the tick ISR. Interrupts are disabled
here already. */ * here already. */
vPortSetupTimerInterrupt(); vPortSetupTimerInterrupt();
/* Initialise the critical nesting count ready for the first task. */ /* Initialise the critical nesting count ready for the first task. */
@ -404,7 +426,7 @@ BaseType_t xPortStartScheduler( void )
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* Not implemented in ports where there is nothing to return to. /* Not implemented in ports where there is nothing to return to.
Artificially force an assert. */ * Artificially force an assert. */
configASSERT( uxCriticalNesting == 1000UL ); configASSERT( uxCriticalNesting == 1000UL );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -419,10 +441,10 @@ void vPortEnterCritical( void )
vPortResetPrivilege( xRunningPrivileged ); vPortResetPrivilege( xRunningPrivileged );
/* This is not the interrupt safe version of the enter critical function so /* This is not the interrupt safe version of the enter critical function so
assert() if it is being called from an interrupt context. Only API * assert() if it is being called from an interrupt context. Only API
functions that end in "FromISR" can be used in an interrupt. Only assert if * functions that end in "FromISR" can be used in an interrupt. Only assert if
the critical nesting count is 1 to protect against recursive calls if the * the critical nesting count is 1 to protect against recursive calls if the
assert function also uses a critical section. */ * assert function also uses a critical section. */
if( uxCriticalNesting == 1 ) if( uxCriticalNesting == 1 )
{ {
configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 ); configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );
@ -449,16 +471,16 @@ BaseType_t xRunningPrivileged = xPortRaisePrivilege();
void xPortSysTickHandler( void ) void xPortSysTickHandler( void )
{ {
/* The SysTick runs at the lowest interrupt priority, so when this interrupt /* The SysTick runs at the lowest interrupt priority, so when this interrupt
executes all interrupts must be unmasked. There is therefore no need to * executes all interrupts must be unmasked. There is therefore no need to
save and then restore the interrupt mask value as its value is already * save and then restore the interrupt mask value as its value is already
known. */ * known. */
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
{ {
/* Increment the RTOS tick. */ /* Increment the RTOS tick. */
if( xTaskIncrementTick() != pdFALSE ) if( xTaskIncrementTick() != pdFALSE )
{ {
/* A context switch is required. Context switching is performed in /* A context switch is required. Context switching is performed in
the PendSV interrupt. Pend the PendSV interrupt. */ * the PendSV interrupt. Pend the PendSV interrupt. */
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
} }
} }
@ -504,8 +526,8 @@ extern uint32_t __privileged_data_end__[];
( portMPU_REGION_ENABLE ); ( portMPU_REGION_ENABLE );
/* Setup the first 16K for privileged only access (even though less /* Setup the first 16K for privileged only access (even though less
than 10K is actually being used). This is where the kernel code is * than 10K is actually being used). This is where the kernel code is
placed. */ * placed. */
portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __FLASH_segment_start__ ) | /* Base address. */ portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __FLASH_segment_start__ ) | /* Base address. */
( portMPU_REGION_VALID ) | ( portMPU_REGION_VALID ) |
( portPRIVILEGED_FLASH_REGION ); ( portPRIVILEGED_FLASH_REGION );
@ -516,7 +538,7 @@ extern uint32_t __privileged_data_end__[];
( portMPU_REGION_ENABLE ); ( portMPU_REGION_ENABLE );
/* Setup the privileged data RAM region. This is where the kernel data /* Setup the privileged data RAM region. This is where the kernel data
is placed. */ * is placed. */
portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __privileged_data_start__ ) | /* Base address. */ portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __privileged_data_start__ ) | /* Base address. */
( portMPU_REGION_VALID ) | ( portMPU_REGION_VALID ) |
( portPRIVILEGED_RAM_REGION ); ( portPRIVILEGED_RAM_REGION );
@ -527,7 +549,7 @@ extern uint32_t __privileged_data_end__[];
( portMPU_REGION_ENABLE ); ( portMPU_REGION_ENABLE );
/* By default allow everything to access the general peripherals. The /* By default allow everything to access the general peripherals. The
system peripherals and registers are protected. */ * system peripherals and registers are protected. */
portMPU_REGION_BASE_ADDRESS_REG = ( portPERIPHERALS_START_ADDRESS ) | portMPU_REGION_BASE_ADDRESS_REG = ( portPERIPHERALS_START_ADDRESS ) |
( portMPU_REGION_VALID ) | ( portMPU_REGION_VALID ) |
( portGENERAL_PERIPHERALS_REGION ); ( portGENERAL_PERIPHERALS_REGION );
@ -550,7 +572,7 @@ static uint32_t prvGetMPURegionSizeSetting( uint32_t ulActualSizeInBytes )
uint32_t ulRegionSize, ulReturnValue = 4; uint32_t ulRegionSize, ulReturnValue = 4;
/* 32 is the smallest region size, 31 is the largest valid value for /* 32 is the smallest region size, 31 is the largest valid value for
ulReturnValue. */ * ulReturnValue. */
for( ulRegionSize = 32UL; ulReturnValue < 31UL; ( ulRegionSize <<= 1UL ) ) for( ulRegionSize = 32UL; ulReturnValue < 31UL; ( ulRegionSize <<= 1UL ) )
{ {
if( ulActualSizeInBytes <= ulRegionSize ) if( ulActualSizeInBytes <= ulRegionSize )
@ -564,7 +586,7 @@ uint32_t ulRegionSize, ulReturnValue = 4;
} }
/* Shift the code by one before returning so it can be written directly /* Shift the code by one before returning so it can be written directly
into the the correct bit position of the attribute register. */ * into the the correct bit position of the attribute register. */
return ( ulReturnValue << 1UL ); return ( ulReturnValue << 1UL );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -593,7 +615,7 @@ uint32_t ul;
( portMPU_REGION_ENABLE ); ( portMPU_REGION_ENABLE );
/* Re-instate the privileged only RAM region as xRegion[ 0 ] will have /* Re-instate the privileged only RAM region as xRegion[ 0 ] will have
just removed the privileged only parameters. */ * just removed the privileged only parameters. */
xMPUSettings->xRegion[ 1 ].ulRegionBaseAddress = xMPUSettings->xRegion[ 1 ].ulRegionBaseAddress =
( ( uint32_t ) __privileged_data_start__ ) | /* Base address. */ ( ( uint32_t ) __privileged_data_start__ ) | /* Base address. */
( portMPU_REGION_VALID ) | ( portMPU_REGION_VALID ) |
@ -615,9 +637,9 @@ uint32_t ul;
else else
{ {
/* This function is called automatically when the task is created - in /* This function is called automatically when the task is created - in
which case the stack region parameters will be valid. At all other * which case the stack region parameters will be valid. At all other
times the stack parameters will not be valid and it is assumed that the * times the stack parameters will not be valid and it is assumed that the
stack region has already been configured. */ * stack region has already been configured. */
if( ulStackDepth > 0 ) if( ulStackDepth > 0 )
{ {
/* Define the region that allows access to the stack. */ /* Define the region that allows access to the stack. */
@ -640,8 +662,8 @@ uint32_t ul;
if( ( xRegions[ lIndex ] ).ulLengthInBytes > 0UL ) if( ( xRegions[ lIndex ] ).ulLengthInBytes > 0UL )
{ {
/* Translate the generic region definition contained in /* Translate the generic region definition contained in
xRegions into the CM3 specific MPU settings that are then * xRegions into the CM3 specific MPU settings that are then
stored in xMPUSettings. */ * stored in xMPUSettings. */
xMPUSettings->xRegion[ ul ].ulRegionBaseAddress = xMPUSettings->xRegion[ ul ].ulRegionBaseAddress =
( ( uint32_t ) xRegions[ lIndex ].pvBaseAddress ) | ( ( uint32_t ) xRegions[ lIndex ].pvBaseAddress ) |
( portMPU_REGION_VALID ) | ( portMPU_REGION_VALID ) |
@ -682,66 +704,46 @@ uint32_t ul;
ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ]; ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
/* The following assertion will fail if a service routine (ISR) for /* The following assertion will fail if a service routine (ISR) for
an interrupt that has been assigned a priority above * an interrupt that has been assigned a priority above
configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API * configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
function. ISR safe FreeRTOS API functions must *only* be called * function. ISR safe FreeRTOS API functions must *only* be called
from interrupts that have been assigned a priority at or below * from interrupts that have been assigned a priority at or below
configMAX_SYSCALL_INTERRUPT_PRIORITY. * configMAX_SYSCALL_INTERRUPT_PRIORITY.
Numerically low interrupt priority numbers represent logically high * Numerically low interrupt priority numbers represent logically high
interrupt priorities, therefore the priority of the interrupt must * interrupt priorities, therefore the priority of the interrupt must
be set to a value equal to or numerically *higher* than * be set to a value equal to or numerically *higher* than
configMAX_SYSCALL_INTERRUPT_PRIORITY. * configMAX_SYSCALL_INTERRUPT_PRIORITY.
Interrupts that use the FreeRTOS API must not be left at their * Interrupts that use the FreeRTOS API must not be left at their
default priority of zero as that is the highest possible priority, * default priority of zero as that is the highest possible priority,
which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, * which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
and therefore also guaranteed to be invalid. * and therefore also guaranteed to be invalid.
FreeRTOS maintains separate thread and ISR API functions to ensure * FreeRTOS maintains separate thread and ISR API functions to ensure
interrupt entry is as fast and simple as possible. * interrupt entry is as fast and simple as possible.
The following links provide detailed information: * The following links provide detailed information:
http://www.freertos.org/RTOS-Cortex-M3-M4.html * http://www.freertos.org/RTOS-Cortex-M3-M4.html
http://www.freertos.org/FAQHelp.html */ * http://www.freertos.org/FAQHelp.html */
configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );
} }
/* Priority grouping: The interrupt controller (NVIC) allows the bits /* Priority grouping: The interrupt controller (NVIC) allows the bits
that define each interrupt's priority to be split between bits that * that define each interrupt's priority to be split between bits that
define the interrupt's pre-emption priority bits and bits that define * define the interrupt's pre-emption priority bits and bits that define
the interrupt's sub-priority. For simplicity all bits must be defined * the interrupt's sub-priority. For simplicity all bits must be defined
to be pre-emption priority bits. The following assertion will fail if * to be pre-emption priority bits. The following assertion will fail if
this is not the case (if some bits represent a sub-priority). * this is not the case (if some bits represent a sub-priority).
If the application only uses CMSIS libraries for interrupt * If the application only uses CMSIS libraries for interrupt
configuration then the correct setting can be achieved on all Cortex-M * configuration then the correct setting can be achieved on all Cortex-M
devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the * devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
scheduler. Note however that some vendor specific peripheral libraries * scheduler. Note however that some vendor specific peripheral libraries
assume a non-zero priority group setting, in which cases using a value * assume a non-zero priority group setting, in which cases using a value
of zero will result in unpredictable behaviour. */ * of zero will result in unpredictable behaviour. */
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
} }
#endif /* configASSERT_DEFINED */ #endif /* configASSERT_DEFINED */
/*-----------------------------------------------------------*/

@ -78,12 +78,26 @@ xPortPendSVHandler:
ldr r0, [r1] ldr r0, [r1]
/* Move onto the second item in the TCB... */ /* Move onto the second item in the TCB... */
add r1, r1, #4 add r1, r1, #4
dmb /* Complete outstanding transfers before disabling MPU. */
ldr r2, =0xe000ed94 /* MPU_CTRL register. */
ldr r3, [r2] /* Read the value of MPU_CTRL. */
bic r3, r3, #1 /* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */
str r3, [r2] /* Disable MPU. */
/* Region Base Address register. */ /* Region Base Address register. */
ldr r2, =0xe000ed9c ldr r2, =0xe000ed9c
/* Read 4 sets of MPU registers. */ /* Read 4 sets of MPU registers. */
ldmia r1!, {r4-r11} ldmia r1!, {r4-r11}
/* Write 4 sets of MPU registers. */ /* Write 4 sets of MPU registers. */
stmia r2!, {r4-r11} stmia r2!, {r4-r11}
ldr r2, =0xe000ed94 /* MPU_CTRL register. */
ldr r3, [r2] /* Read the value of MPU_CTRL. */
orr r3, r3, #1 /* r3 = r3 | 1 i.e. Set the bit 0 in r3. */
str r3, [r2] /* Enable MPU. */
dsb /* Force memory writes before continuing. */
/* Pop the registers that are not automatically saved on exception entry. */ /* Pop the registers that are not automatically saved on exception entry. */
ldmia r0!, {r3-r11, r14} ldmia r0!, {r3-r11, r14}
msr control, r3 msr control, r3
@ -151,12 +165,26 @@ vPortRestoreContextOfFirstTask:
ldr r0, [r1] ldr r0, [r1]
/* Move onto the second item in the TCB... */ /* Move onto the second item in the TCB... */
add r1, r1, #4 add r1, r1, #4
dmb /* Complete outstanding transfers before disabling MPU. */
ldr r2, =0xe000ed94 /* MPU_CTRL register. */
ldr r3, [r2] /* Read the value of MPU_CTRL. */
bic r3, r3, #1 /* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */
str r3, [r2] /* Disable MPU. */
/* Region Base Address register. */ /* Region Base Address register. */
ldr r2, =0xe000ed9c ldr r2, =0xe000ed9c
/* Read 4 sets of MPU registers. */ /* Read 4 sets of MPU registers. */
ldmia r1!, {r4-r11} ldmia r1!, {r4-r11}
/* Write 4 sets of MPU registers. */ /* Write 4 sets of MPU registers. */
stmia r2!, {r4-r11} stmia r2!, {r4-r11}
ldr r2, =0xe000ed94 /* MPU_CTRL register. */
ldr r3, [r2] /* Read the value of MPU_CTRL. */
orr r3, r3, #1 /* r3 = r3 | 1 i.e. Set the bit 0 in r3. */
str r3, [r2] /* Enable MPU. */
dsb /* Force memory writes before continuing. */
/* Pop the registers that are not automatically saved on exception entry. */ /* Pop the registers that are not automatically saved on exception entry. */
ldmia r0!, {r3-r11, r14} ldmia r0!, {r3-r11, r14}
msr control, r3 msr control, r3

@ -25,6 +25,7 @@
* 1 tab == 4 spaces! * 1 tab == 4 spaces!
*/ */
#ifndef PORTMACRO_H #ifndef PORTMACRO_H
#define PORTMACRO_H #define PORTMACRO_H
@ -75,12 +76,13 @@ typedef unsigned long UBaseType_t;
#define portUSING_MPU_WRAPPERS 1 #define portUSING_MPU_WRAPPERS 1
#define portPRIVILEGE_BIT ( 0x80000000UL ) #define portPRIVILEGE_BIT ( 0x80000000UL )
#define portMPU_REGION_READ_WRITE ( 0x03UL << 24UL ) #define portMPU_REGION_READ_WRITE ( 0x03UL << 24UL )
#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 0x05UL << 24UL ) #define portMPU_REGION_PRIVILEGED_READ_ONLY ( 0x05UL << 24UL )
#define portMPU_REGION_READ_ONLY ( 0x06UL << 24UL ) #define portMPU_REGION_READ_ONLY ( 0x06UL << 24UL )
#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0x01UL << 24UL ) #define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0x01UL << 24UL )
#define portMPU_REGION_CACHEABLE_BUFFERABLE ( 0x07UL << 16UL ) #define portMPU_REGION_PRIVILEGED_READ_WRITE_UNPRIV_READ_ONLY ( 0x02UL << 24UL )
#define portMPU_REGION_EXECUTE_NEVER ( 0x01UL << 28UL ) #define portMPU_REGION_CACHEABLE_BUFFERABLE ( 0x07UL << 16UL )
#define portMPU_REGION_EXECUTE_NEVER ( 0x01UL << 28UL )
#define portUNPRIVILEGED_FLASH_REGION ( 0UL ) #define portUNPRIVILEGED_FLASH_REGION ( 0UL )
#define portPRIVILEGED_FLASH_REGION ( 1UL ) #define portPRIVILEGED_FLASH_REGION ( 1UL )
@ -106,7 +108,6 @@ typedef struct MPU_SETTINGS
xMPU_REGION_REGISTERS xRegion[ portTOTAL_NUM_REGIONS ]; xMPU_REGION_REGISTERS xRegion[ portTOTAL_NUM_REGIONS ];
} xMPU_SETTINGS; } xMPU_SETTINGS;
/* Architecture specifics. */ /* Architecture specifics. */
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
@ -119,6 +120,7 @@ typedef struct MPU_SETTINGS
#define portSVC_RAISE_PRIVILEGE 2 #define portSVC_RAISE_PRIVILEGE 2
/* Scheduler utilities. */ /* Scheduler utilities. */
#define portYIELD() __asm volatile ( " SVC %0 \n" :: "i" (portSVC_YIELD) : "memory" ) #define portYIELD() __asm volatile ( " SVC %0 \n" :: "i" (portSVC_YIELD) : "memory" )
#define portYIELD_WITHIN_API() \ #define portYIELD_WITHIN_API() \
{ \ { \
@ -132,7 +134,6 @@ typedef struct MPU_SETTINGS
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) #define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired != pdFALSE ) portYIELD_WITHIN_API() #define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired != pdFALSE ) portYIELD_WITHIN_API()
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Architecture specific optimisations. */ /* Architecture specific optimisations. */
@ -214,11 +215,19 @@ extern void vResetPrivilege( void );
#define portRESET_PRIVILEGE() vResetPrivilege() #define portRESET_PRIVILEGE() vResetPrivilege()
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#ifndef configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY
#warning "configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY is not defined. We recommend defining it to 1 in FreeRTOSConfig.h for better security."
#define configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY 0
#endif
/*-----------------------------------------------------------*/
/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in /* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
the source code because to do so would cause other compilers to generate the source code because to do so would cause other compilers to generate
warnings. */ warnings. */
#pragma diag_suppress=Pe191 #pragma diag_suppress=Pe191
#pragma diag_suppress=Pa082 #pragma diag_suppress=Pa082
#pragma diag_suppress=Be006
/*-----------------------------------------------------------*/
#ifdef __cplusplus #ifdef __cplusplus
} }

Loading…
Cancel
Save