Add barrier instructions to IAR CM3 ports.

This commit is contained in:
Richard Barry 2013-04-16 14:56:49 +00:00
parent be7cae575d
commit 895ee2bb3e
7 changed files with 72 additions and 46 deletions

View file

@ -56,19 +56,19 @@
*************************************************************************** ***************************************************************************
http://www.FreeRTOS.org - Documentation, books, training, latest versions, http://www.FreeRTOS.org - Documentation, books, training, latest versions,
license and Real Time Engineers Ltd. contact details. license and Real Time Engineers Ltd. contact details.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool, and our new including FreeRTOS+Trace - an indispensable productivity tool, and our new
fully thread aware and reentrant UDP/IP stack. fully thread aware and reentrant UDP/IP stack.
http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
Integrity Systems, who sell the code with commercial support, Integrity Systems, who sell the code with commercial support,
indemnification and middleware, under the OpenRTOS brand. indemnification and middleware, under the OpenRTOS brand.
http://www.SafeRTOS.com - High Integrity Systems also provide a safety http://www.SafeRTOS.com - High Integrity Systems also provide a safety
engineered and independently SIL3 certified version for use in safety and engineered and independently SIL3 certified version for use in safety and
mission critical applications that require provable dependability. mission critical applications that require provable dependability.
*/ */
@ -76,6 +76,9 @@
* Implementation of functions defined in portable.h for the ARM CM0 port. * Implementation of functions defined in portable.h for the ARM CM0 port.
*----------------------------------------------------------*/ *----------------------------------------------------------*/
/* IAR includes. */
#include "intrinsics.h"
/* Scheduler includes. */ /* Scheduler includes. */
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "task.h" #include "task.h"
@ -83,12 +86,10 @@
/* Constants required to manipulate the NVIC. */ /* Constants required to manipulate the NVIC. */
#define portNVIC_SYSTICK_CTRL ( ( volatile unsigned long *) 0xe000e010 ) #define portNVIC_SYSTICK_CTRL ( ( volatile unsigned long *) 0xe000e010 )
#define portNVIC_SYSTICK_LOAD ( ( volatile unsigned long *) 0xe000e014 ) #define portNVIC_SYSTICK_LOAD ( ( volatile unsigned long *) 0xe000e014 )
#define portNVIC_INT_CTRL ( ( volatile unsigned long *) 0xe000ed04 )
#define portNVIC_SYSPRI2 ( ( volatile unsigned long *) 0xe000ed20 ) #define portNVIC_SYSPRI2 ( ( volatile unsigned long *) 0xe000ed20 )
#define portNVIC_SYSTICK_CLK 0x00000004 #define portNVIC_SYSTICK_CLK 0x00000004
#define portNVIC_SYSTICK_INT 0x00000002 #define portNVIC_SYSTICK_INT 0x00000002
#define portNVIC_SYSTICK_ENABLE 0x00000001 #define portNVIC_SYSTICK_ENABLE 0x00000001
#define portNVIC_PENDSVSET 0x10000000
#define portMIN_INTERRUPT_PRIORITY ( 255UL ) #define portMIN_INTERRUPT_PRIORITY ( 255UL )
#define portNVIC_PENDSV_PRI ( portMIN_INTERRUPT_PRIORITY << 16UL ) #define portNVIC_PENDSV_PRI ( portMIN_INTERRUPT_PRIORITY << 16UL )
#define portNVIC_SYSTICK_PRI ( portMIN_INTERRUPT_PRIORITY << 24UL ) #define portNVIC_SYSTICK_PRI ( portMIN_INTERRUPT_PRIORITY << 24UL )
@ -155,7 +156,7 @@ portBASE_TYPE xPortStartScheduler( void )
/* 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. */
prvSetupTimerInterrupt(); prvSetupTimerInterrupt();
/* Initialise the critical nesting count ready for the first task. */ /* Initialise the critical nesting count ready for the first task. */
uxCriticalNesting = 0; uxCriticalNesting = 0;
@ -174,10 +175,15 @@ void vPortEndScheduler( void )
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortYieldFromISR( void ) void vPortYield( void )
{ {
/* Set a PendSV to request a context switch. */ /* Set a PendSV to request a context switch. */
*(portNVIC_INT_CTRL) = portNVIC_PENDSVSET; *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET;
/* Barriers are normally not required but do ensure the code is completely
within the specified behaviour for the architecture. */
__DSB();
__ISB();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -185,6 +191,8 @@ void vPortEnterCritical( void )
{ {
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
uxCriticalNesting++; uxCriticalNesting++;
__DSB();
__ISB();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -204,7 +212,7 @@ unsigned long ulDummy;
/* If using preemption, also force a context switch. */ /* If using preemption, also force a context switch. */
#if configUSE_PREEMPTION == 1 #if configUSE_PREEMPTION == 1
*(portNVIC_INT_CTRL) = portNVIC_PENDSVSET; *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET;
#endif #endif
ulDummy = portSET_INTERRUPT_MASK_FROM_ISR(); ulDummy = portSET_INTERRUPT_MASK_FROM_ISR();

View file

@ -116,11 +116,11 @@ extern "C" {
/* Scheduler utilities. */ /* Scheduler utilities. */
extern void vPortYieldFromISR( void ); extern void vPortYield( void );
#define portNVIC_INT_CTRL ( ( volatile unsigned long *) 0xe000ed04 )
#define portYIELD() vPortYieldFromISR() #define portNVIC_PENDSVSET 0x10000000
#define portYIELD() vPortYield()
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vPortYieldFromISR() #define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -56,19 +56,19 @@
*************************************************************************** ***************************************************************************
http://www.FreeRTOS.org - Documentation, books, training, latest versions, http://www.FreeRTOS.org - Documentation, books, training, latest versions,
license and Real Time Engineers Ltd. contact details. license and Real Time Engineers Ltd. contact details.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool, and our new including FreeRTOS+Trace - an indispensable productivity tool, and our new
fully thread aware and reentrant UDP/IP stack. fully thread aware and reentrant UDP/IP stack.
http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
Integrity Systems, who sell the code with commercial support, Integrity Systems, who sell the code with commercial support,
indemnification and middleware, under the OpenRTOS brand. indemnification and middleware, under the OpenRTOS brand.
http://www.SafeRTOS.com - High Integrity Systems also provide a safety http://www.SafeRTOS.com - High Integrity Systems also provide a safety
engineered and independently SIL3 certified version for use in safety and engineered and independently SIL3 certified version for use in safety and
mission critical applications that require provable dependability. mission critical applications that require provable dependability.
*/ */
@ -95,14 +95,12 @@
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile unsigned long * ) 0xe000e010 ) ) #define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile unsigned long * ) 0xe000e010 ) )
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile unsigned long * ) 0xe000e014 ) ) #define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile unsigned long * ) 0xe000e014 ) )
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile unsigned long * ) 0xe000e018 ) ) #define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile unsigned long * ) 0xe000e018 ) )
#define portNVIC_INT_CTRL_REG ( * ( ( volatile unsigned long * ) 0xe000ed04 ) )
#define portNVIC_SYSPRI2_REG ( * ( ( volatile unsigned long * ) 0xe000ed20 ) ) #define portNVIC_SYSPRI2_REG ( * ( ( volatile unsigned long * ) 0xe000ed20 ) )
/* ...then bits in the registers. */ /* ...then bits in the registers. */
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL ) #define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL ) #define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL ) #define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL ) #define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL ) #define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL )
#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL ) #define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL )
@ -219,10 +217,15 @@ void vPortEndScheduler( void )
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortYieldFromISR( void ) void vPortYield( void )
{ {
/* Set a PendSV to request a context switch. */ /* Set a PendSV to request a context switch. */
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; 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. */
__DSB();
__ISB();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -230,6 +233,8 @@ void vPortEnterCritical( void )
{ {
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
uxCriticalNesting++; uxCriticalNesting++;
__DSB();
__ISB();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -336,6 +341,8 @@ void xPortSysTickHandler( void )
if( xModifiableIdleTime > 0 ) if( xModifiableIdleTime > 0 )
{ {
__WFI(); __WFI();
__DSB();
__ISB();
} }
configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); configPOST_SLEEP_PROCESSING( xExpectedIdleTime );

View file

@ -115,9 +115,11 @@ extern "C" {
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Scheduler utilities. */ /* Scheduler utilities. */
extern void vPortYieldFromISR( void ); extern void vPortYield( void );
#define portYIELD() vPortYieldFromISR() #define portNVIC_INT_CTRL_REG ( * ( ( volatile unsigned long * ) 0xe000ed04 ) )
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vPortYieldFromISR() #define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
#define portYIELD() vPortYield()
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Architecture specific optimisations. */ /* Architecture specific optimisations. */

View file

@ -56,19 +56,19 @@
*************************************************************************** ***************************************************************************
http://www.FreeRTOS.org - Documentation, books, training, latest versions, http://www.FreeRTOS.org - Documentation, books, training, latest versions,
license and Real Time Engineers Ltd. contact details. license and Real Time Engineers Ltd. contact details.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool, and our new including FreeRTOS+Trace - an indispensable productivity tool, and our new
fully thread aware and reentrant UDP/IP stack. fully thread aware and reentrant UDP/IP stack.
http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
Integrity Systems, who sell the code with commercial support, Integrity Systems, who sell the code with commercial support,
indemnification and middleware, under the OpenRTOS brand. indemnification and middleware, under the OpenRTOS brand.
http://www.SafeRTOS.com - High Integrity Systems also provide a safety http://www.SafeRTOS.com - High Integrity Systems also provide a safety
engineered and independently SIL3 certified version for use in safety and engineered and independently SIL3 certified version for use in safety and
mission critical applications that require provable dependability. mission critical applications that require provable dependability.
*/ */
@ -99,14 +99,12 @@
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile unsigned long * ) 0xe000e010 ) ) #define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile unsigned long * ) 0xe000e010 ) )
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile unsigned long * ) 0xe000e014 ) ) #define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile unsigned long * ) 0xe000e014 ) )
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile unsigned long * ) 0xe000e018 ) ) #define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile unsigned long * ) 0xe000e018 ) )
#define portNVIC_INT_CTRL_REG ( * ( ( volatile unsigned long * ) 0xe000ed04 ) )
#define portNVIC_SYSPRI2_REG ( * ( ( volatile unsigned long * ) 0xe000ed20 ) ) #define portNVIC_SYSPRI2_REG ( * ( ( volatile unsigned long * ) 0xe000ed20 ) )
/* ...then bits in the registers. */ /* ...then bits in the registers. */
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL ) #define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL ) #define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL ) #define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL ) #define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL ) #define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL )
#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL ) #define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL )
@ -244,10 +242,15 @@ void vPortEndScheduler( void )
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortYieldFromISR( void ) void vPortYield( void )
{ {
/* Set a PendSV to request a context switch. */ /* Set a PendSV to request a context switch. */
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; 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. */
__DSB();
__ISB();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -255,6 +258,8 @@ void vPortEnterCritical( void )
{ {
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
uxCriticalNesting++; uxCriticalNesting++;
__DSB();
__ISB();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -361,6 +366,8 @@ void xPortSysTickHandler( void )
if( xModifiableIdleTime > 0 ) if( xModifiableIdleTime > 0 )
{ {
__WFI(); __WFI();
__DSB();
__ISB();
} }
configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); configPOST_SLEEP_PROCESSING( xExpectedIdleTime );

View file

@ -115,9 +115,11 @@ extern "C" {
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Scheduler utilities. */ /* Scheduler utilities. */
extern void vPortYieldFromISR( void ); extern void vPortYield( void );
#define portYIELD() vPortYieldFromISR() #define portNVIC_INT_CTRL_REG ( * ( ( volatile unsigned long * ) 0xe000ed04 ) )
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vPortYieldFromISR() #define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
#define portYIELD() vPortYield()
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Architecture specific optimisations. */ /* Architecture specific optimisations. */

View file

@ -112,16 +112,16 @@ volatile unsigned short usCriticalNesting = portINITIAL_CRITICAL_NESTING;
/* /*
* Sets up the periodic ISR used for the RTOS tick using the interval timer. * Sets up the periodic ISR used for the RTOS tick using the interval timer.
* The application writer can define configSETUP_TIMER_INTERRUPT() (in * The application writer can define configSETUP_TICK_INTERRUPT() (in
* FreeRTOSConfig.h) such that their own tick interrupt configuration is used * FreeRTOSConfig.h) such that their own tick interrupt configuration is used
* in place of prvSetupTimerInterrupt(). * in place of prvSetupTimerInterrupt().
*/ */
static void prvSetupTimerInterrupt( void ); static void prvSetupTimerInterrupt( void );
#ifndef configSETUP_TIMER_INTERRUPT #ifndef configSETUP_TICK_INTERRUPT
/* The user has not provided their own tick interrupt configuration so use /* The user has not provided their own tick interrupt configuration so use
the definition in this file (which uses the interval timer). */ the definition in this file (which uses the interval timer). */
#define configSETUP_TIMER_INTERRUPT() prvSetupTimerInterrupt() #define configSETUP_TICK_INTERRUPT() prvSetupTimerInterrupt()
#endif /* configSETUP_TIMER_INTERRUPT */ #endif /* configSETUP_TICK_INTERRUPT */
/* /*
* Defined in portasm.s87, this function starts the scheduler by loading the * Defined in portasm.s87, this function starts the scheduler by loading the
@ -218,7 +218,7 @@ portBASE_TYPE xPortStartScheduler( void )
{ {
/* Setup the hardware to generate the tick. Interrupts are disabled when /* Setup the hardware to generate the tick. Interrupts are disabled when
this function is called. */ this function is called. */
configSETUP_TIMER_INTERRUPT(); configSETUP_TICK_INTERRUPT();
/* Restore the context of the first task that is going to run. */ /* Restore the context of the first task that is going to run. */
vPortStartFirstTask(); vPortStartFirstTask();
@ -227,7 +227,7 @@ portBASE_TYPE xPortStartScheduler( void )
prvSetupTimerInterrupt() is called here to prevent the compiler outputting prvSetupTimerInterrupt() is called here to prevent the compiler outputting
a warning about a statically declared function not being referenced in the a warning about a statically declared function not being referenced in the
case that the application writer has provided their own tick interrupt case that the application writer has provided their own tick interrupt
configuration routine (and defined configSETUP_TIMER_INTERRUPT() such that configuration routine (and defined configSETUP_TICK_INTERRUPT() such that
their own routine will be called in place of prvSetupTimerInterrupt()). */ their own routine will be called in place of prvSetupTimerInterrupt()). */
prvSetupTimerInterrupt(); prvSetupTimerInterrupt();
return pdTRUE; return pdTRUE;