mirror of
				https://github.com/FreeRTOS/FreeRTOS-Kernel.git
				synced 2025-11-04 11:09:01 +01:00 
			
		
		
		
	Updates to CM3_MPU GCC 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.
This commit is contained in:
		
							parent
							
								
									42a0eaafdc
								
							
						
					
					
						commit
						e058a65b16
					
				@ -30,8 +30,8 @@
 | 
			
		||||
 *----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/* 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
 | 
			
		||||
task.h is included from an application file. */
 | 
			
		||||
 * all the API functions to use the MPU wrappers.  That should only be done when
 | 
			
		||||
 * task.h is included from an application file. */
 | 
			
		||||
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
 | 
			
		||||
 | 
			
		||||
/* Scheduler includes. */
 | 
			
		||||
@ -46,7 +46,7 @@ task.h is included from an application file. */
 | 
			
		||||
	#define portNVIC_SYSTICK_CLK	( 1UL << 2UL )
 | 
			
		||||
#else
 | 
			
		||||
	/* The way the SysTick is clocked is not modified in case it is not the same
 | 
			
		||||
	as the core. */
 | 
			
		||||
	 * as the core. */
 | 
			
		||||
	#define portNVIC_SYSTICK_CLK	( 0 )
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@ -86,21 +86,22 @@ task.h is included from an application file. */
 | 
			
		||||
#define portINITIAL_CONTROL_IF_PRIVILEGED		( 0x02 )
 | 
			
		||||
 | 
			
		||||
/* Constants required to check the validity of an interrupt priority. */
 | 
			
		||||
#define portFIRST_USER_INTERRUPT_NUMBER		( 16 )
 | 
			
		||||
#define portNVIC_IP_REGISTERS_OFFSET_16 	( 0xE000E3F0 )
 | 
			
		||||
#define portAIRCR_REG						( * ( ( volatile uint32_t * ) 0xE000ED0C ) )
 | 
			
		||||
#define portMAX_8_BIT_VALUE					( ( uint8_t ) 0xff )
 | 
			
		||||
#define portTOP_BIT_OF_BYTE					( ( uint8_t ) 0x80 )
 | 
			
		||||
#define portMAX_PRIGROUP_BITS				( ( uint8_t ) 7 )
 | 
			
		||||
#define portPRIORITY_GROUP_MASK				( 0x07UL << 8UL )
 | 
			
		||||
#define portPRIGROUP_SHIFT					( 8UL )
 | 
			
		||||
#define portFIRST_USER_INTERRUPT_NUMBER			( 16 )
 | 
			
		||||
#define portNVIC_IP_REGISTERS_OFFSET_16 		( 0xE000E3F0 )
 | 
			
		||||
#define portAIRCR_REG							( * ( ( volatile uint32_t * ) 0xE000ED0C ) )
 | 
			
		||||
#define portMAX_8_BIT_VALUE						( ( uint8_t ) 0xff )
 | 
			
		||||
#define portTOP_BIT_OF_BYTE						( ( uint8_t ) 0x80 )
 | 
			
		||||
#define portMAX_PRIGROUP_BITS					( ( uint8_t ) 7 )
 | 
			
		||||
#define portPRIORITY_GROUP_MASK					( 0x07UL << 8UL )
 | 
			
		||||
#define portPRIGROUP_SHIFT						( 8UL )
 | 
			
		||||
 | 
			
		||||
/* Offsets in the stack to the parameters when inside the SVC handler. */
 | 
			
		||||
#define portOFFSET_TO_PC						( 6 )
 | 
			
		||||
 | 
			
		||||
/* For strict compliance with the Cortex-M spec the task start address should
 | 
			
		||||
have bit-0 clear, as it is loaded into the PC on exit from an ISR. */
 | 
			
		||||
#define portSTART_ADDRESS_MASK				( ( StackType_t ) 0xfffffffeUL )
 | 
			
		||||
 * have bit-0 clear, as it is loaded into the PC on exit from an ISR. */
 | 
			
		||||
#define portSTART_ADDRESS_MASK					( ( StackType_t ) 0xfffffffeUL )
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Configure a number of standard MPU regions that are used by all tasks.
 | 
			
		||||
@ -171,8 +172,8 @@ extern void vPortResetPrivilege( BaseType_t xRunningPrivileged );
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/* Each task maintains its own interrupt status in the critical nesting
 | 
			
		||||
variable.  Note this is not saved as part of the task context as context
 | 
			
		||||
switches can only occur when uxCriticalNesting is zero. */
 | 
			
		||||
 * variable.  Note this is not saved as part of the task context as context
 | 
			
		||||
 * switches can only occur when uxCriticalNesting is zero. */
 | 
			
		||||
static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
@ -185,7 +186,6 @@ static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
 | 
			
		||||
	 static uint32_t ulMaxPRIGROUPValue = 0;
 | 
			
		||||
	 static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * const ) portNVIC_IP_REGISTERS_OFFSET_16;
 | 
			
		||||
#endif /* configASSERT_DEFINED */
 | 
			
		||||
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
@ -194,7 +194,7 @@ static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
 | 
			
		||||
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
 | 
			
		||||
	interrupt. */
 | 
			
		||||
	 * interrupt. */
 | 
			
		||||
	pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
 | 
			
		||||
	*pxTopOfStack = portINITIAL_XPSR;	/* xPSR */
 | 
			
		||||
	pxTopOfStack--;
 | 
			
		||||
@ -240,10 +240,25 @@ void vPortSVCHandler( void )
 | 
			
		||||
static void prvSVCHandler(	uint32_t *pulParam )
 | 
			
		||||
{
 | 
			
		||||
uint8_t ucSVCNumber;
 | 
			
		||||
uint32_t ulPC;
 | 
			
		||||
#if( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 )
 | 
			
		||||
	#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 ) */
 | 
			
		||||
#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 ];
 | 
			
		||||
 | 
			
		||||
	/* The stack contains: r0, r1, r2, r3, r12, r14, the return address and
 | 
			
		||||
	xPSR.  The first argument (r0) is pulParam[ 0 ]. */
 | 
			
		||||
	ucSVCNumber = ( ( uint8_t * ) pulParam[ portOFFSET_TO_PC ] )[ -2 ];
 | 
			
		||||
	switch( ucSVCNumber )
 | 
			
		||||
	{
 | 
			
		||||
		case portSVC_START_SCHEDULER	:	portNVIC_SYSPRI1_REG |= portNVIC_SVC_PRI;
 | 
			
		||||
@ -252,14 +267,32 @@ uint8_t ucSVCNumber;
 | 
			
		||||
 | 
			
		||||
		case portSVC_YIELD				:	portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
 | 
			
		||||
											/* Barriers are normally not required
 | 
			
		||||
											but do ensure the code is completely
 | 
			
		||||
											within the specified behaviour for the
 | 
			
		||||
											architecture. */
 | 
			
		||||
											 * but do ensure the code is completely
 | 
			
		||||
											 * within the specified behaviour for the
 | 
			
		||||
											 * architecture. */
 | 
			
		||||
											__asm volatile( "dsb" ::: "memory" );
 | 
			
		||||
											__asm volatile( "isb" );
 | 
			
		||||
 | 
			
		||||
											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, #1			\n" /* Set privilege bit. */
 | 
			
		||||
													"	msr control, r1		\n" /* Write back new control value. */
 | 
			
		||||
													::: "r1", "memory"
 | 
			
		||||
												);
 | 
			
		||||
											}
 | 
			
		||||
											break;
 | 
			
		||||
	#else
 | 
			
		||||
		case portSVC_RAISE_PRIVILEGE	:	__asm volatile
 | 
			
		||||
											(
 | 
			
		||||
												"	mrs r1, control		\n" /* Obtain current control value. */
 | 
			
		||||
@ -268,6 +301,7 @@ uint8_t ucSVCNumber;
 | 
			
		||||
												::: "r1", "memory"
 | 
			
		||||
											);
 | 
			
		||||
											break;
 | 
			
		||||
	#endif /* #if( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 ) */
 | 
			
		||||
 | 
			
		||||
		default							:	/* Unknown SVC call. */
 | 
			
		||||
											break;
 | 
			
		||||
@ -287,9 +321,23 @@ static void prvRestoreContextOfFirstTask( void )
 | 
			
		||||
		"	ldr r1, [r3]					\n"
 | 
			
		||||
		"	ldr r0, [r1]					\n" /* The first item in the TCB is the task top of stack. */
 | 
			
		||||
		"	add r1, r1, #4					\n" /* Move onto the second item in the TCB... */
 | 
			
		||||
		"									\n"
 | 
			
		||||
		"	dmb								\n" /* Complete outstanding transfers before disabling MPU. */
 | 
			
		||||
		"	ldr r2, =0xe000ed94				\n" /* MPU_CTRL register. */
 | 
			
		||||
		"	ldr r3, [r2]					\n" /* Read the value of MPU_CTRL. */
 | 
			
		||||
		"	bic r3, #1						\n" /* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */
 | 
			
		||||
		"	str r3, [r2]					\n" /* Disable MPU. */
 | 
			
		||||
		"									\n"
 | 
			
		||||
		"	ldr r2, =0xe000ed9c				\n" /* Region Base Address register. */
 | 
			
		||||
		"	ldmia r1!, {r4-r11}				\n" /* Read 4 sets of MPU registers. */
 | 
			
		||||
		"	stmia r2!, {r4-r11}				\n" /* Write 4 sets of MPU registers. */
 | 
			
		||||
		"									\n"
 | 
			
		||||
		"	ldr r2, =0xe000ed94				\n" /* MPU_CTRL register. */
 | 
			
		||||
		"	ldr r3, [r2]					\n" /* Read the value of MPU_CTRL. */
 | 
			
		||||
		"	orr r3, #1						\n" /* r3 = r3 | 1 i.e. Set the bit 0 in r3. */
 | 
			
		||||
		"	str r3, [r2]					\n" /* Enable MPU. */
 | 
			
		||||
		"	dsb								\n" /* Force memory writes before continuing. */
 | 
			
		||||
		"									\n"
 | 
			
		||||
		"	ldmia r0!, {r3, r4-r11}			\n" /* Pop the registers that are not automatically saved on exception entry. */
 | 
			
		||||
		"	msr control, r3					\n"
 | 
			
		||||
		"	msr psp, r0						\n" /* Restore the task stack pointer. */
 | 
			
		||||
@ -310,7 +358,7 @@ static void prvRestoreContextOfFirstTask( void )
 | 
			
		||||
BaseType_t xPortStartScheduler( void )
 | 
			
		||||
{
 | 
			
		||||
	/* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0.  See
 | 
			
		||||
	http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
 | 
			
		||||
	 * http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
 | 
			
		||||
	configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) );
 | 
			
		||||
 | 
			
		||||
	#if( configASSERT_DEFINED == 1 )
 | 
			
		||||
@ -320,15 +368,15 @@ BaseType_t xPortStartScheduler( void )
 | 
			
		||||
		volatile uint8_t ucMaxPriorityValue;
 | 
			
		||||
 | 
			
		||||
		/* Determine the maximum priority from which ISR safe FreeRTOS API
 | 
			
		||||
		functions can be called.  ISR safe functions are those that end in
 | 
			
		||||
		"FromISR".  FreeRTOS maintains separate thread and ISR API functions to
 | 
			
		||||
		ensure interrupt entry is as fast and simple as possible.
 | 
			
		||||
		 * functions can be called.  ISR safe functions are those that end in
 | 
			
		||||
		 * "FromISR".  FreeRTOS maintains separate thread and ISR API functions
 | 
			
		||||
		 * to 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;
 | 
			
		||||
 | 
			
		||||
		/* Determine the number of priority bits available.  First write to all
 | 
			
		||||
		possible bits. */
 | 
			
		||||
		 * possible bits. */
 | 
			
		||||
		*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
 | 
			
		||||
 | 
			
		||||
		/* Read the value back to see how many bits stuck. */
 | 
			
		||||
@ -338,7 +386,7 @@ BaseType_t xPortStartScheduler( void )
 | 
			
		||||
		ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
 | 
			
		||||
 | 
			
		||||
		/* Calculate the maximum acceptable priority group value for the number
 | 
			
		||||
		of bits read back. */
 | 
			
		||||
		 * of bits read back. */
 | 
			
		||||
		ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS;
 | 
			
		||||
		while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
 | 
			
		||||
		{
 | 
			
		||||
@ -349,8 +397,8 @@ BaseType_t xPortStartScheduler( void )
 | 
			
		||||
		#ifdef __NVIC_PRIO_BITS
 | 
			
		||||
		{
 | 
			
		||||
			/* Check the CMSIS configuration that defines the number of
 | 
			
		||||
			priority bits matches the number of priority bits actually queried
 | 
			
		||||
			from the hardware. */
 | 
			
		||||
			 * priority bits matches the number of priority bits actually queried
 | 
			
		||||
			 * from the hardware. */
 | 
			
		||||
			configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == __NVIC_PRIO_BITS );
 | 
			
		||||
		}
 | 
			
		||||
		#endif
 | 
			
		||||
@ -358,26 +406,26 @@ BaseType_t xPortStartScheduler( void )
 | 
			
		||||
		#ifdef configPRIO_BITS
 | 
			
		||||
		{
 | 
			
		||||
			/* Check the FreeRTOS configuration that defines the number of
 | 
			
		||||
			priority bits matches the number of priority bits actually queried
 | 
			
		||||
			from the hardware. */
 | 
			
		||||
			 * priority bits matches the number of priority bits actually queried
 | 
			
		||||
			 * from the hardware. */
 | 
			
		||||
			configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == configPRIO_BITS );
 | 
			
		||||
		}
 | 
			
		||||
		#endif
 | 
			
		||||
 | 
			
		||||
		/* Shift the priority group value back to its position within the AIRCR
 | 
			
		||||
		register. */
 | 
			
		||||
		 * register. */
 | 
			
		||||
		ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
 | 
			
		||||
		ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
 | 
			
		||||
 | 
			
		||||
		/* Restore the clobbered interrupt priority register to its original
 | 
			
		||||
		value. */
 | 
			
		||||
		 * value. */
 | 
			
		||||
		*pucFirstUserPriorityRegister = ulOriginalPriority;
 | 
			
		||||
	}
 | 
			
		||||
	#endif /* conifgASSERT_DEFINED */
 | 
			
		||||
 | 
			
		||||
	/* Make PendSV and SysTick the same priority as the kernel, and the SVC
 | 
			
		||||
	handler higher priority so it can be used to exit a critical section (where
 | 
			
		||||
	lower priorities are masked). */
 | 
			
		||||
	 * handler higher priority so it can be used to exit a critical section (where
 | 
			
		||||
	 * lower priorities are masked). */
 | 
			
		||||
	portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
 | 
			
		||||
	portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
 | 
			
		||||
 | 
			
		||||
@ -385,7 +433,7 @@ BaseType_t xPortStartScheduler( void )
 | 
			
		||||
	prvSetupMPU();
 | 
			
		||||
 | 
			
		||||
	/* Start the timer that generates the tick ISR.  Interrupts are disabled
 | 
			
		||||
	here already. */
 | 
			
		||||
	 * here already. */
 | 
			
		||||
	vPortSetupTimerInterrupt();
 | 
			
		||||
 | 
			
		||||
	/* Initialise the critical nesting count ready for the first task. */
 | 
			
		||||
@ -413,7 +461,7 @@ BaseType_t xPortStartScheduler( void )
 | 
			
		||||
void vPortEndScheduler( void )
 | 
			
		||||
{
 | 
			
		||||
	/* Not implemented in ports where there is nothing to return to.
 | 
			
		||||
	Artificially force an assert. */
 | 
			
		||||
	 * Artificially force an assert. */
 | 
			
		||||
	configASSERT( uxCriticalNesting == 1000UL );
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
@ -471,9 +519,23 @@ void xPortPendSVHandler( void )
 | 
			
		||||
		"	ldr r1, [r3]						\n"
 | 
			
		||||
		"	ldr r0, [r1]						\n" /* The first item in the TCB is the task top of stack. */
 | 
			
		||||
		"	add r1, r1, #4						\n" /* Move onto the second item in the TCB... */
 | 
			
		||||
		"										\n"
 | 
			
		||||
		"	dmb									\n" /* Complete outstanding transfers before disabling MPU. */
 | 
			
		||||
		"	ldr r2, =0xe000ed94					\n" /* MPU_CTRL register. */
 | 
			
		||||
		"	ldr r3, [r2]						\n" /* Read the value of MPU_CTRL. */
 | 
			
		||||
		"	bic r3, #1							\n" /* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */
 | 
			
		||||
		"	str r3, [r2]						\n" /* Disable MPU. */
 | 
			
		||||
		"										\n"
 | 
			
		||||
		"	ldr r2, =0xe000ed9c					\n" /* Region Base Address register. */
 | 
			
		||||
		"	ldmia r1!, {r4-r11}					\n" /* Read 4 sets of MPU registers. */
 | 
			
		||||
		"	stmia r2!, {r4-r11}					\n" /* Write 4 sets of MPU registers. */
 | 
			
		||||
		"										\n"
 | 
			
		||||
		"	ldr r2, =0xe000ed94					\n" /* MPU_CTRL register. */
 | 
			
		||||
		"	ldr r3, [r2]						\n" /* Read the value of MPU_CTRL. */
 | 
			
		||||
		"	orr r3, #1							\n" /* r3 = r3 | 1 i.e. Set the bit 0 in r3. */
 | 
			
		||||
		"	str r3, [r2]						\n" /* Enable MPU. */
 | 
			
		||||
		"	dsb									\n" /* Force memory writes before continuing. */
 | 
			
		||||
		"										\n"
 | 
			
		||||
		"	ldmia r0!, {r3, r4-r11}				\n" /* Pop the registers that are not automatically saved on exception entry. */
 | 
			
		||||
		"	msr control, r3						\n"
 | 
			
		||||
		"										\n"
 | 
			
		||||
@ -542,8 +604,8 @@ extern uint32_t __privileged_data_end__[];
 | 
			
		||||
										( portMPU_REGION_ENABLE );
 | 
			
		||||
 | 
			
		||||
		/* Setup the first 16K for privileged only access (even though less
 | 
			
		||||
		than 10K is actually being used).  This is where the kernel code is
 | 
			
		||||
		placed. */
 | 
			
		||||
		 * than 10K is actually being used).  This is where the kernel code is
 | 
			
		||||
		 * placed. */
 | 
			
		||||
		portMPU_REGION_BASE_ADDRESS_REG =	( ( uint32_t ) __FLASH_segment_start__ ) | /* Base address. */
 | 
			
		||||
											( portMPU_REGION_VALID ) |
 | 
			
		||||
											( portPRIVILEGED_FLASH_REGION );
 | 
			
		||||
@ -554,7 +616,7 @@ extern uint32_t __privileged_data_end__[];
 | 
			
		||||
										( portMPU_REGION_ENABLE );
 | 
			
		||||
 | 
			
		||||
		/* 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_VALID ) |
 | 
			
		||||
											( portPRIVILEGED_RAM_REGION );
 | 
			
		||||
@ -565,7 +627,7 @@ extern uint32_t __privileged_data_end__[];
 | 
			
		||||
										( portMPU_REGION_ENABLE );
 | 
			
		||||
 | 
			
		||||
		/* 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_VALID ) |
 | 
			
		||||
											( portGENERAL_PERIPHERALS_REGION );
 | 
			
		||||
@ -588,7 +650,7 @@ static uint32_t prvGetMPURegionSizeSetting( uint32_t ulActualSizeInBytes )
 | 
			
		||||
uint32_t ulRegionSize, ulReturnValue = 4;
 | 
			
		||||
 | 
			
		||||
	/* 32 is the smallest region size, 31 is the largest valid value for
 | 
			
		||||
	ulReturnValue. */
 | 
			
		||||
	 * ulReturnValue. */
 | 
			
		||||
	for( ulRegionSize = 32UL; ulReturnValue < 31UL; ( ulRegionSize <<= 1UL ) )
 | 
			
		||||
	{
 | 
			
		||||
		if( ulActualSizeInBytes <= ulRegionSize )
 | 
			
		||||
@ -602,7 +664,7 @@ uint32_t ulRegionSize, ulReturnValue = 4;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* 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 );
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
@ -661,7 +723,7 @@ uint32_t ul;
 | 
			
		||||
				( portMPU_REGION_ENABLE );
 | 
			
		||||
 | 
			
		||||
		/* 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 =
 | 
			
		||||
				( ( uint32_t ) __privileged_data_start__ ) | /* Base address. */
 | 
			
		||||
				( portMPU_REGION_VALID ) |
 | 
			
		||||
@ -683,9 +745,9 @@ uint32_t ul;
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		/* This function is called automatically when the task is created - in
 | 
			
		||||
		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
 | 
			
		||||
		stack region has already been configured. */
 | 
			
		||||
		 * 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
 | 
			
		||||
		 * stack region has already been configured. */
 | 
			
		||||
		if( ulStackDepth > 0 )
 | 
			
		||||
		{
 | 
			
		||||
			/* Define the region that allows access to the stack. */
 | 
			
		||||
@ -708,8 +770,8 @@ uint32_t ul;
 | 
			
		||||
			if( ( xRegions[ lIndex ] ).ulLengthInBytes > 0UL )
 | 
			
		||||
			{
 | 
			
		||||
				/* Translate the generic region definition contained in
 | 
			
		||||
				xRegions into the CM3 specific MPU settings that are then
 | 
			
		||||
				stored in xMPUSettings. */
 | 
			
		||||
				 * xRegions into the CM3 specific MPU settings that are then
 | 
			
		||||
				 * stored in xMPUSettings. */
 | 
			
		||||
				xMPUSettings->xRegion[ ul ].ulRegionBaseAddress =
 | 
			
		||||
						( ( uint32_t ) xRegions[ lIndex ].pvBaseAddress ) |
 | 
			
		||||
						( portMPU_REGION_VALID ) |
 | 
			
		||||
@ -750,48 +812,46 @@ uint32_t ul;
 | 
			
		||||
			ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
 | 
			
		||||
 | 
			
		||||
			/* The following assertion will fail if a service routine (ISR) for
 | 
			
		||||
			an interrupt that has been assigned a priority above
 | 
			
		||||
			configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
 | 
			
		||||
			function.  ISR safe FreeRTOS API functions must *only* be called
 | 
			
		||||
			from interrupts that have been assigned a priority at or below
 | 
			
		||||
			configMAX_SYSCALL_INTERRUPT_PRIORITY.
 | 
			
		||||
			 * an interrupt that has been assigned a priority above
 | 
			
		||||
			 * configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
 | 
			
		||||
			 * function.  ISR safe FreeRTOS API functions must *only* be called
 | 
			
		||||
			 * from interrupts that have been assigned a priority at or below
 | 
			
		||||
			 * configMAX_SYSCALL_INTERRUPT_PRIORITY.
 | 
			
		||||
 | 
			
		||||
			Numerically low interrupt priority numbers represent logically high
 | 
			
		||||
			interrupt priorities, therefore the priority of the interrupt must
 | 
			
		||||
			be set to a value equal to or numerically *higher* than
 | 
			
		||||
			configMAX_SYSCALL_INTERRUPT_PRIORITY.
 | 
			
		||||
			 * Numerically low interrupt priority numbers represent logically high
 | 
			
		||||
			 * interrupt priorities, therefore the priority of the interrupt must
 | 
			
		||||
			 * be set to a value equal to or numerically *higher* than
 | 
			
		||||
			 * configMAX_SYSCALL_INTERRUPT_PRIORITY.
 | 
			
		||||
 | 
			
		||||
			Interrupts that	use the FreeRTOS API must not be left at their
 | 
			
		||||
			default priority of	zero as that is the highest possible priority,
 | 
			
		||||
			which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
 | 
			
		||||
			and	therefore also guaranteed to be invalid.
 | 
			
		||||
			 * Interrupts that	use the FreeRTOS API must not be left at their
 | 
			
		||||
			 * default priority of	zero as that is the highest possible priority,
 | 
			
		||||
			 * which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
 | 
			
		||||
			 * and	therefore also guaranteed to be invalid.
 | 
			
		||||
 | 
			
		||||
			FreeRTOS maintains separate thread and ISR API functions to ensure
 | 
			
		||||
			interrupt entry is as fast and simple as possible.
 | 
			
		||||
			 * FreeRTOS maintains separate thread and ISR API functions to ensure
 | 
			
		||||
			 * interrupt entry is as fast and simple as possible.
 | 
			
		||||
 | 
			
		||||
			The following links provide detailed information:
 | 
			
		||||
			http://www.freertos.org/RTOS-Cortex-M3-M4.html
 | 
			
		||||
			http://www.freertos.org/FAQHelp.html */
 | 
			
		||||
			 * The following links provide detailed information:
 | 
			
		||||
			 * http://www.freertos.org/RTOS-Cortex-M3-M4.html
 | 
			
		||||
			 * http://www.freertos.org/FAQHelp.html */
 | 
			
		||||
			configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Priority grouping:  The interrupt controller (NVIC) allows the bits
 | 
			
		||||
		that define each interrupt's priority to be split between bits that
 | 
			
		||||
		define the interrupt's pre-emption priority bits and bits that define
 | 
			
		||||
		the interrupt's sub-priority.  For simplicity all bits must be defined
 | 
			
		||||
		to be pre-emption priority bits.  The following assertion will fail if
 | 
			
		||||
		this is not the case (if some bits represent a sub-priority).
 | 
			
		||||
		 * that define each interrupt's priority to be split between bits that
 | 
			
		||||
		 * define the interrupt's pre-emption priority bits and bits that define
 | 
			
		||||
		 * the interrupt's sub-priority.  For simplicity all bits must be defined
 | 
			
		||||
		 * to be pre-emption priority bits.  The following assertion will fail if
 | 
			
		||||
		 * this is not the case (if some bits represent a sub-priority).
 | 
			
		||||
 | 
			
		||||
		If the application only uses CMSIS libraries for interrupt
 | 
			
		||||
		configuration then the correct setting can be achieved on all Cortex-M
 | 
			
		||||
		devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
 | 
			
		||||
		scheduler.  Note however that some vendor specific peripheral libraries
 | 
			
		||||
		assume a non-zero priority group setting, in which cases using a value
 | 
			
		||||
		of zero will result in unpredicable behaviour. */
 | 
			
		||||
		 * If the application only uses CMSIS libraries for interrupt
 | 
			
		||||
		 * configuration then the correct setting can be achieved on all Cortex-M
 | 
			
		||||
		 * devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
 | 
			
		||||
		 * scheduler.  Note however that some vendor specific peripheral libraries
 | 
			
		||||
		 * assume a non-zero priority group setting, in which cases using a value
 | 
			
		||||
		 * of zero will result in unpredicable behaviour. */
 | 
			
		||||
		configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#endif /* configASSERT_DEFINED */
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -73,12 +73,13 @@ typedef unsigned long UBaseType_t;
 | 
			
		||||
#define portUSING_MPU_WRAPPERS		1
 | 
			
		||||
#define portPRIVILEGE_BIT			( 0x80000000UL )
 | 
			
		||||
 | 
			
		||||
#define portMPU_REGION_READ_WRITE				( 0x03UL << 24UL )
 | 
			
		||||
#define portMPU_REGION_PRIVILEGED_READ_ONLY		( 0x05UL << 24UL )
 | 
			
		||||
#define portMPU_REGION_READ_ONLY				( 0x06UL << 24UL )
 | 
			
		||||
#define portMPU_REGION_PRIVILEGED_READ_WRITE	( 0x01UL << 24UL )
 | 
			
		||||
#define portMPU_REGION_CACHEABLE_BUFFERABLE		( 0x07UL << 16UL )
 | 
			
		||||
#define portMPU_REGION_EXECUTE_NEVER			( 0x01UL << 28UL )
 | 
			
		||||
#define portMPU_REGION_READ_WRITE								( 0x03UL << 24UL )
 | 
			
		||||
#define portMPU_REGION_PRIVILEGED_READ_ONLY						( 0x05UL << 24UL )
 | 
			
		||||
#define portMPU_REGION_READ_ONLY								( 0x06UL << 24UL )
 | 
			
		||||
#define portMPU_REGION_PRIVILEGED_READ_WRITE					( 0x01UL << 24UL )
 | 
			
		||||
#define portMPU_REGION_PRIVILEGED_READ_WRITE_UNPRIV_READ_ONLY	( 0x02UL << 24UL )
 | 
			
		||||
#define portMPU_REGION_CACHEABLE_BUFFERABLE						( 0x07UL << 16UL )
 | 
			
		||||
#define portMPU_REGION_EXECUTE_NEVER							( 0x01UL << 28UL )
 | 
			
		||||
 | 
			
		||||
#define portUNPRIVILEGED_FLASH_REGION		( 0UL )
 | 
			
		||||
#define portPRIVILEGED_FLASH_REGION			( 1UL )
 | 
			
		||||
@ -293,6 +294,11 @@ portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue )
 | 
			
		||||
 | 
			
		||||
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
 | 
			
		||||
 | 
			
		||||
#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
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user