diff options
Diffstat (limited to 'portable/IAR/ARM_CM7/r0p1/port.c')
-rw-r--r-- | portable/IAR/ARM_CM7/r0p1/port.c | 52 |
1 files changed, 51 insertions, 1 deletions
diff --git a/portable/IAR/ARM_CM7/r0p1/port.c b/portable/IAR/ARM_CM7/r0p1/port.c index 58129a4df..2790028f4 100644 --- a/portable/IAR/ARM_CM7/r0p1/port.c +++ b/portable/IAR/ARM_CM7/r0p1/port.c @@ -45,10 +45,14 @@ #error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http: /*www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ #endif +/* Prototype of all Interrupt Service Routines (ISRs). */ +typedef void ( * portISR_t )( void ); + /* Constants required to manipulate the core. Registers first... */ #define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) ) #define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) ) #define portNVIC_SYSTICK_CURRENT_VALUE_REG ( *( ( volatile uint32_t * ) 0xe000e018 ) ) +#define portNVIC_SHPR2_REG ( *( ( volatile uint32_t * ) 0xe000ed1c ) ) #define portNVIC_SHPR3_REG ( *( ( volatile uint32_t * ) 0xe000ed20 ) ) /* ...then bits in the registers. */ #define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL ) @@ -63,6 +67,11 @@ #define portNVIC_PENDSV_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 16UL ) #define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 24UL ) +/* Constants used to check the installation of the FreeRTOS interrupt handlers. */ +#define portSCB_VTOR_REG ( *( ( portISR_t ** ) 0xE000ED08 ) ) +#define portVECTOR_INDEX_SVC ( 11 ) +#define portVECTOR_INDEX_PENDSV ( 14 ) + /* Constants required to check the validity of an interrupt priority. */ #define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) #define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) @@ -135,6 +144,11 @@ extern void vPortEnableVFP( void ); */ static void prvTaskExitError( void ); +/* + * FreeRTOS handlers implemented in assembly. + */ +extern void vPortSVCHandler( void ); +extern void xPortPendSVHandler( void ); /*-----------------------------------------------------------*/ /* Each task maintains its own interrupt status in the critical nesting @@ -234,6 +248,40 @@ static void prvTaskExitError( void ) */ BaseType_t xPortStartScheduler( void ) { + /* An application can install FreeRTOS interrupt handlers in one of the + * folllowing ways: + * 1. Direct Routing - Install the functions vPortSVCHandler and + * xPortPendSVHandler for SVCall and PendSV interrupts respectively. + * 2. Indirect Routing - Install separate handlers for SVCall and PendSV + * interrupts and route program control from those handlers to + * vPortSVCHandler and xPortPendSVHandler functions. + * + * Applications that use Indirect Routing must set + * configCHECK_HANDLER_INSTALLATION to 0 in their FreeRTOSConfig.h. Direct + * routing, which is validated here when configCHECK_HANDLER_INSTALLATION + * is 1, should be preferred when possible. */ + #if ( configCHECK_HANDLER_INSTALLATION == 1 ) + { + const portISR_t * const pxVectorTable = portSCB_VTOR_REG; + + /* Validate that the application has correctly installed the FreeRTOS + * handlers for SVCall and PendSV interrupts. We do not check the + * installation of the SysTick handler because the application may + * choose to drive the RTOS tick using a timer other than the SysTick + * timer by overriding the weak function vPortSetupTimerInterrupt(). + * + * Assertion failures here indicate incorrect installation of the + * FreeRTOS handlers. For help installing the FreeRTOS handlers, see + * https://www.FreeRTOS.org/FAQHelp.html. + * + * Systems with a configurable address for the interrupt vector table + * can also encounter assertion failures or even system faults here if + * VTOR is not set correctly to point to the application's vector table. */ + configASSERT( pxVectorTable[ portVECTOR_INDEX_SVC ] == vPortSVCHandler ); + configASSERT( pxVectorTable[ portVECTOR_INDEX_PENDSV ] == xPortPendSVHandler ); + } + #endif /* configCHECK_HANDLER_INSTALLATION */ + #if ( configASSERT_DEFINED == 1 ) { volatile uint8_t ucOriginalPriority; @@ -318,9 +366,11 @@ BaseType_t xPortStartScheduler( void ) } #endif /* configASSERT_DEFINED */ - /* Make PendSV and SysTick the lowest priority interrupts. */ + /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall + * the highest priority. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; + portNVIC_SHPR2_REG = 0; /* Start the timer that generates the tick ISR. Interrupts are disabled * here already. */ |