summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrtel <rtel@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>2017-04-10 01:58:01 +0000
committerrtel <rtel@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>2017-04-10 01:58:01 +0000
commit4770c8551244e937cb70a14d87341449f472ca7c (patch)
tree931d28d79e9ac67bfe2827854a31b9a6292394fb
parentb9ab67007726b33f90cd68432b78dbde56bd85e6 (diff)
downloadfreertos-4770c8551244e937cb70a14d87341449f472ca7c.tar.gz
Add more "memory" clobbers into the MPU ports to make them robust to more aggressive optimisation in newer GCC version.
git-svn-id: http://svn.code.sf.net/p/freertos/code/trunk@2500 1d2547de-c912-0410-9cb9-b8ca96c0e9e2
-rw-r--r--FreeRTOS/Source/portable/GCC/ARM_CM3_MPU/port.c77
-rw-r--r--FreeRTOS/Source/portable/GCC/ARM_CM4_MPU/port.c63
2 files changed, 93 insertions, 47 deletions
diff --git a/FreeRTOS/Source/portable/GCC/ARM_CM3_MPU/port.c b/FreeRTOS/Source/portable/GCC/ARM_CM3_MPU/port.c
index be041538d..e95e8c95b 100644
--- a/FreeRTOS/Source/portable/GCC/ARM_CM3_MPU/port.c
+++ b/FreeRTOS/Source/portable/GCC/ARM_CM3_MPU/port.c
@@ -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.
*/
@@ -169,6 +168,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.
*/
void xPortPendSVHandler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
@@ -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 )
diff --git a/FreeRTOS/Source/portable/GCC/ARM_CM4_MPU/port.c b/FreeRTOS/Source/portable/GCC/ARM_CM4_MPU/port.c
index c52078ed1..32943ff59 100644
--- a/FreeRTOS/Source/portable/GCC/ARM_CM4_MPU/port.c
+++ b/FreeRTOS/Source/portable/GCC/ARM_CM4_MPU/port.c
@@ -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.
*/
@@ -176,6 +175,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.
*/
void xPortPendSVHandler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
@@ -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 )