mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-04-19 21:11:57 -04:00
Add more "memory" clobbers into the MPU ports to make them robust to more aggressive optimisation in newer GCC version.
This commit is contained in:
parent
0f85ead175
commit
b080f13543
|
@ -86,6 +86,16 @@ task.h is included from an application file. */
|
|||
|
||||
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
#ifndef configSYSTICK_CLOCK_HZ
|
||||
#define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
|
||||
/* Ensure the SysTick is clocked at the same frequency as the core. */
|
||||
#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. */
|
||||
#define portNVIC_SYSTICK_CLK ( 0 )
|
||||
#endif
|
||||
|
||||
/* Constants required to access and manipulate the NVIC. */
|
||||
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) )
|
||||
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) )
|
||||
|
@ -110,7 +120,6 @@ task.h is included from an application file. */
|
|||
#define portPERIPHERALS_END_ADDRESS 0x5FFFFFFFUL
|
||||
|
||||
/* Constants required to access and manipulate the SysTick. */
|
||||
#define portNVIC_SYSTICK_CLK ( 0x00000004UL )
|
||||
#define portNVIC_SYSTICK_INT ( 0x00000002UL )
|
||||
#define portNVIC_SYSTICK_ENABLE ( 0x00000001UL )
|
||||
#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
|
||||
|
@ -139,16 +148,6 @@ task.h is included from an application file. */
|
|||
have bit-0 clear, as it is loaded into the PC on exit from an ISR. */
|
||||
#define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL )
|
||||
|
||||
/* 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. */
|
||||
static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
|
||||
|
||||
/*
|
||||
* Setup the timer to generate the tick interrupts.
|
||||
*/
|
||||
static void prvSetupTimerInterrupt( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* Configure a number of standard MPU regions that are used by all tasks.
|
||||
*/
|
||||
|
@ -168,6 +167,13 @@ static uint32_t prvGetMPURegionSizeSetting( uint32_t ulActualSizeInBytes ) PRIVI
|
|||
*/
|
||||
BaseType_t xPortRaisePrivilege( void ) __attribute__(( naked ));
|
||||
|
||||
/*
|
||||
* Setup the timer to generate the tick interrupts. The implementation in this
|
||||
* file is weak to allow application writers to change the timer used to
|
||||
* generate the tick interrupt.
|
||||
*/
|
||||
void vPortSetupTimerInterrupt( void );
|
||||
|
||||
/*
|
||||
* Standard FreeRTOS exception handlers.
|
||||
*/
|
||||
|
@ -186,6 +192,13 @@ static void prvRestoreContextOfFirstTask( void ) __attribute__(( naked )) PRIVIL
|
|||
*/
|
||||
static void prvSVCHandler( uint32_t *pulRegisters ) __attribute__(( noinline )) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* 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. */
|
||||
static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
|
||||
|
||||
/*
|
||||
* Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure
|
||||
* FreeRTOS API functions are not called from interrupts that have been assigned
|
||||
|
@ -243,7 +256,7 @@ void vPortSVCHandler( void )
|
|||
" mrs r0, psp \n"
|
||||
#endif
|
||||
" b %0 \n"
|
||||
::"i"(prvSVCHandler):"r0"
|
||||
::"i"(prvSVCHandler):"r0", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
@ -266,7 +279,7 @@ uint8_t ucSVCNumber;
|
|||
but do ensure the code is completely
|
||||
within the specified behaviour for the
|
||||
architecture. */
|
||||
__asm volatile( "dsb" );
|
||||
__asm volatile( "dsb" ::: "memory" );
|
||||
__asm volatile( "isb" );
|
||||
|
||||
break;
|
||||
|
@ -276,7 +289,7 @@ uint8_t ucSVCNumber;
|
|||
" 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"
|
||||
::: "r1", "memory"
|
||||
);
|
||||
break;
|
||||
|
||||
|
@ -357,6 +370,24 @@ BaseType_t xPortStartScheduler( void )
|
|||
ucMaxPriorityValue <<= ( uint8_t ) 0x01;
|
||||
}
|
||||
|
||||
#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. */
|
||||
configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == __NVIC_PRIO_BITS );
|
||||
}
|
||||
#endif
|
||||
|
||||
#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. */
|
||||
configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == configPRIO_BITS );
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Shift the priority group value back to its position within the AIRCR
|
||||
register. */
|
||||
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
|
||||
|
@ -379,7 +410,7 @@ BaseType_t xPortStartScheduler( void )
|
|||
|
||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||
here already. */
|
||||
prvSetupTimerInterrupt();
|
||||
vPortSetupTimerInterrupt();
|
||||
|
||||
/* Initialise the critical nesting count ready for the first task. */
|
||||
uxCriticalNesting = 0;
|
||||
|
@ -396,7 +427,7 @@ BaseType_t xPortStartScheduler( void )
|
|||
" isb \n"
|
||||
" svc %0 \n" /* System call to start first task. */
|
||||
" nop \n"
|
||||
:: "i" (portSVC_START_SCHEDULER) );
|
||||
:: "i" (portSVC_START_SCHEDULER) : "memory" );
|
||||
|
||||
/* Should not get here! */
|
||||
return 0;
|
||||
|
@ -454,6 +485,8 @@ void xPortPendSVHandler( void )
|
|||
" stmdb sp!, {r3, r14} \n"
|
||||
" mov r0, %0 \n"
|
||||
" msr basepri, r0 \n"
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" bl vTaskSwitchContext \n"
|
||||
" mov r0, #0 \n"
|
||||
" msr basepri, r0 \n"
|
||||
|
@ -499,15 +532,15 @@ uint32_t ulDummy;
|
|||
* Setup the systick timer to generate the tick interrupts at the required
|
||||
* frequency.
|
||||
*/
|
||||
static void prvSetupTimerInterrupt( void )
|
||||
__attribute__(( weak )) void vPortSetupTimerInterrupt( void )
|
||||
{
|
||||
/* Reset the SysTick timer. */
|
||||
/* Stop and clear the SysTick. */
|
||||
portNVIC_SYSTICK_CTRL_REG = 0UL;
|
||||
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||
|
||||
/* Configure SysTick to interrupt at the requested rate. */
|
||||
portNVIC_SYSTICK_LOAD_REG = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
|
||||
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE;
|
||||
portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
|
||||
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
@ -609,7 +642,7 @@ BaseType_t xPortRaisePrivilege( void )
|
|||
" svcne %0 \n" /* Switch to privileged. */
|
||||
" moveq r0, #1 \n" /* CONTROL[0]==0, return true. */
|
||||
" bx lr \n"
|
||||
:: "i" (portSVC_RAISE_PRIVILEGE) : "r0"
|
||||
:: "i" (portSVC_RAISE_PRIVILEGE) : "r0", "memory"
|
||||
);
|
||||
|
||||
return 0;
|
||||
|
@ -720,7 +753,7 @@ uint32_t ul;
|
|||
uint8_t ucCurrentPriority;
|
||||
|
||||
/* Obtain the number of the currently executing interrupt. */
|
||||
__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) );
|
||||
__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) :: "memory" );
|
||||
|
||||
/* Is the interrupt number a user defined interrupt? */
|
||||
if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
|
||||
|
|
|
@ -88,6 +88,16 @@ task.h is included from an application file. */
|
|||
|
||||
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
#ifndef configSYSTICK_CLOCK_HZ
|
||||
#define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
|
||||
/* Ensure the SysTick is clocked at the same frequency as the core. */
|
||||
#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. */
|
||||
#define portNVIC_SYSTICK_CLK ( 0 )
|
||||
#endif
|
||||
|
||||
/* Constants required to access and manipulate the NVIC. */
|
||||
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) )
|
||||
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) )
|
||||
|
@ -112,7 +122,6 @@ task.h is included from an application file. */
|
|||
#define portPERIPHERALS_END_ADDRESS 0x5FFFFFFFUL
|
||||
|
||||
/* Constants required to access and manipulate the SysTick. */
|
||||
#define portNVIC_SYSTICK_CLK ( 0x00000004UL )
|
||||
#define portNVIC_SYSTICK_INT ( 0x00000002UL )
|
||||
#define portNVIC_SYSTICK_ENABLE ( 0x00000001UL )
|
||||
#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
|
||||
|
@ -146,16 +155,6 @@ task.h is included from an application file. */
|
|||
have bit-0 clear, as it is loaded into the PC on exit from an ISR. */
|
||||
#define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL )
|
||||
|
||||
/* 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. */
|
||||
static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
|
||||
|
||||
/*
|
||||
* Setup the timer to generate the tick interrupts.
|
||||
*/
|
||||
static void prvSetupTimerInterrupt( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* Configure a number of standard MPU regions that are used by all tasks.
|
||||
*/
|
||||
|
@ -175,6 +174,13 @@ static uint32_t prvGetMPURegionSizeSetting( uint32_t ulActualSizeInBytes ) PRIVI
|
|||
*/
|
||||
BaseType_t xPortRaisePrivilege( void ) __attribute__(( naked ));
|
||||
|
||||
/*
|
||||
* Setup the timer to generate the tick interrupts. The implementation in this
|
||||
* file is weak to allow application writers to change the timer used to
|
||||
* generate the tick interrupt.
|
||||
*/
|
||||
void vPortSetupTimerInterrupt( void );
|
||||
|
||||
/*
|
||||
* Standard FreeRTOS exception handlers.
|
||||
*/
|
||||
|
@ -198,6 +204,13 @@ static void prvSVCHandler( uint32_t *pulRegisters ) __attribute__(( noinline ))
|
|||
*/
|
||||
static void vPortEnableVFP( void ) __attribute__ (( naked ));
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* 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. */
|
||||
static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
|
||||
|
||||
/*
|
||||
* Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure
|
||||
* FreeRTOS API functions are not called from interrupts that have been assigned
|
||||
|
@ -261,7 +274,7 @@ void vPortSVCHandler( void )
|
|||
" mrs r0, psp \n"
|
||||
#endif
|
||||
" b %0 \n"
|
||||
::"i"(prvSVCHandler):"r0"
|
||||
::"i"(prvSVCHandler):"r0", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
@ -284,7 +297,7 @@ uint8_t ucSVCNumber;
|
|||
but do ensure the code is completely
|
||||
within the specified behaviour for the
|
||||
architecture. */
|
||||
__asm volatile( "dsb" );
|
||||
__asm volatile( "dsb" ::: "memory" );
|
||||
__asm volatile( "isb" );
|
||||
|
||||
break;
|
||||
|
@ -294,7 +307,7 @@ uint8_t ucSVCNumber;
|
|||
" 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"
|
||||
::: "r1", "memory"
|
||||
);
|
||||
break;
|
||||
|
||||
|
@ -414,7 +427,7 @@ BaseType_t xPortStartScheduler( void )
|
|||
|
||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||
here already. */
|
||||
prvSetupTimerInterrupt();
|
||||
vPortSetupTimerInterrupt();
|
||||
|
||||
/* Initialise the critical nesting count ready for the first task. */
|
||||
uxCriticalNesting = 0;
|
||||
|
@ -425,9 +438,9 @@ BaseType_t xPortStartScheduler( void )
|
|||
/* Lazy save always. */
|
||||
*( portFPCCR ) |= portASPEN_AND_LSPEN_BITS;
|
||||
|
||||
/* Start the first task. This also clears the bit that indicates the FPU is
|
||||
in use in case the FPU was used before the scheduler was started - which
|
||||
would otherwise result in the unnecessary leaving of space in the SVC stack
|
||||
/* Start the first task. This also clears the bit that indicates the FPU is
|
||||
in use in case the FPU was used before the scheduler was started - which
|
||||
would otherwise result in the unnecessary leaving of space in the SVC stack
|
||||
for lazy saving of FPU registers. */
|
||||
__asm volatile(
|
||||
" ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */
|
||||
|
@ -442,7 +455,7 @@ BaseType_t xPortStartScheduler( void )
|
|||
" isb \n"
|
||||
" svc %0 \n" /* System call to start first task. */
|
||||
" nop \n"
|
||||
:: "i" (portSVC_START_SCHEDULER) );
|
||||
:: "i" (portSVC_START_SCHEDULER) : "memory" );
|
||||
|
||||
/* Should not get here! */
|
||||
return 0;
|
||||
|
@ -555,15 +568,15 @@ uint32_t ulDummy;
|
|||
* Setup the systick timer to generate the tick interrupts at the required
|
||||
* frequency.
|
||||
*/
|
||||
static void prvSetupTimerInterrupt( void )
|
||||
__attribute__(( weak )) void vPortSetupTimerInterrupt( void )
|
||||
{
|
||||
/* Clear the SysTick. */
|
||||
/* Stop and clear the SysTick. */
|
||||
portNVIC_SYSTICK_CTRL_REG = 0UL;
|
||||
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||
|
||||
/* Configure SysTick to interrupt at the requested rate. */
|
||||
portNVIC_SYSTICK_LOAD_REG = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
|
||||
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE;
|
||||
portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
|
||||
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
@ -680,7 +693,7 @@ BaseType_t xPortRaisePrivilege( void )
|
|||
" svcne %0 \n" /* Switch to privileged. */
|
||||
" moveq r0, #1 \n" /* CONTROL[0]==0, return true. */
|
||||
" bx lr \n"
|
||||
:: "i" (portSVC_RAISE_PRIVILEGE) : "r0"
|
||||
:: "i" (portSVC_RAISE_PRIVILEGE) : "r0", "memory"
|
||||
);
|
||||
|
||||
return 0;
|
||||
|
@ -791,7 +804,7 @@ uint32_t ul;
|
|||
uint8_t ucCurrentPriority;
|
||||
|
||||
/* Obtain the number of the currently executing interrupt. */
|
||||
__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) );
|
||||
__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) :: "memory" );
|
||||
|
||||
/* Is the interrupt number a user defined interrupt? */
|
||||
if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
|
||||
|
|
Loading…
Reference in a new issue