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

@ -76,6 +76,9 @@
* Implementation of functions defined in portable.h for the ARM CM0 port.
*----------------------------------------------------------*/
/* IAR includes. */
#include "intrinsics.h"
/* Scheduler includes. */
#include "FreeRTOS.h"
#include "task.h"
@ -83,12 +86,10 @@
/* Constants required to manipulate the NVIC. */
#define portNVIC_SYSTICK_CTRL ( ( volatile unsigned long *) 0xe000e010 )
#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_SYSTICK_CLK 0x00000004
#define portNVIC_SYSTICK_INT 0x00000002
#define portNVIC_SYSTICK_ENABLE 0x00000001
#define portNVIC_PENDSVSET 0x10000000
#define portMIN_INTERRUPT_PRIORITY ( 255UL )
#define portNVIC_PENDSV_PRI ( portMIN_INTERRUPT_PRIORITY << 16UL )
#define portNVIC_SYSTICK_PRI ( portMIN_INTERRUPT_PRIORITY << 24UL )
@ -174,10 +175,15 @@ void vPortEndScheduler( void )
}
/*-----------------------------------------------------------*/
void vPortYieldFromISR( void )
void vPortYield( void )
{
/* Set a PendSV to request a context switch. */
*(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();
uxCriticalNesting++;
__DSB();
__ISB();
}
/*-----------------------------------------------------------*/

View file

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

View file

@ -95,14 +95,12 @@
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile unsigned long * ) 0xe000e010 ) )
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile unsigned long * ) 0xe000e014 ) )
#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 ) )
/* ...then bits in the registers. */
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL )
#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. */
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();
uxCriticalNesting++;
__DSB();
__ISB();
}
/*-----------------------------------------------------------*/
@ -336,6 +341,8 @@ void xPortSysTickHandler( void )
if( xModifiableIdleTime > 0 )
{
__WFI();
__DSB();
__ISB();
}
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );

View file

@ -115,9 +115,11 @@ extern "C" {
/*-----------------------------------------------------------*/
/* Scheduler utilities. */
extern void vPortYieldFromISR( void );
#define portYIELD() vPortYieldFromISR()
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vPortYieldFromISR()
extern void vPortYield( void );
#define portNVIC_INT_CTRL_REG ( * ( ( volatile unsigned long * ) 0xe000ed04 ) )
#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. */

View file

@ -99,14 +99,12 @@
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile unsigned long * ) 0xe000e010 ) )
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile unsigned long * ) 0xe000e014 ) )
#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 ) )
/* ...then bits in the registers. */
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL )
#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. */
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();
uxCriticalNesting++;
__DSB();
__ISB();
}
/*-----------------------------------------------------------*/
@ -361,6 +366,8 @@ void xPortSysTickHandler( void )
if( xModifiableIdleTime > 0 )
{
__WFI();
__DSB();
__ISB();
}
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );

View file

@ -115,9 +115,11 @@ extern "C" {
/*-----------------------------------------------------------*/
/* Scheduler utilities. */
extern void vPortYieldFromISR( void );
#define portYIELD() vPortYieldFromISR()
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vPortYieldFromISR()
extern void vPortYield( void );
#define portNVIC_INT_CTRL_REG ( * ( ( volatile unsigned long * ) 0xe000ed04 ) )
#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. */

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.
* 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
* in place of prvSetupTimerInterrupt().
*/
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 definition in this file (which uses the interval timer). */
#define configSETUP_TIMER_INTERRUPT() prvSetupTimerInterrupt()
#endif /* configSETUP_TIMER_INTERRUPT */
#define configSETUP_TICK_INTERRUPT() prvSetupTimerInterrupt()
#endif /* configSETUP_TICK_INTERRUPT */
/*
* 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
this function is called. */
configSETUP_TIMER_INTERRUPT();
configSETUP_TICK_INTERRUPT();
/* Restore the context of the first task that is going to run. */
vPortStartFirstTask();
@ -227,7 +227,7 @@ portBASE_TYPE xPortStartScheduler( void )
prvSetupTimerInterrupt() is called here to prevent the compiler outputting
a warning about a statically declared function not being referenced in the
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()). */
prvSetupTimerInterrupt();
return pdTRUE;