diff options
author | Gregory Nutt <gnutt@nuttx.org> | 2013-12-21 15:05:48 -0600 |
---|---|---|
committer | Gregory Nutt <gnutt@nuttx.org> | 2013-12-21 15:05:48 -0600 |
commit | d4c848e5f49652dcb4b38506d3700d8a1e8c2dff (patch) | |
tree | 07874b7800338a66451b897bdc5fa7175d4b649e /nuttx/arch/arm/src/sam34/sam_vectors.S | |
parent | 61d8a57e974548c1c7ef65e9546976053f6c5a9e (diff) | |
download | px4-nuttx-d4c848e5f49652dcb4b38506d3700d8a1e8c2dff.tar.gz px4-nuttx-d4c848e5f49652dcb4b38506d3700d8a1e8c2dff.tar.bz2 px4-nuttx-d4c848e5f49652dcb4b38506d3700d8a1e8c2dff.zip |
Finishes coding of ARMv7-M high priority nested interrupt logic. Still undocumented; still not fully tested
Diffstat (limited to 'nuttx/arch/arm/src/sam34/sam_vectors.S')
-rw-r--r-- | nuttx/arch/arm/src/sam34/sam_vectors.S | 57 |
1 files changed, 52 insertions, 5 deletions
diff --git a/nuttx/arch/arm/src/sam34/sam_vectors.S b/nuttx/arch/arm/src/sam34/sam_vectors.S index 490a81a7a..97e144388 100644 --- a/nuttx/arch/arm/src/sam34/sam_vectors.S +++ b/nuttx/arch/arm/src/sam34/sam_vectors.S @@ -46,9 +46,37 @@ /************************************************************************************************ * Preprocessor Definitions ************************************************************************************************/ +/* Configuration ********************************************************************************/ + +#ifdef CONFIG_ARCH_HIPRI_INTERRUPT + /* In kernel mode without an interrupt stack, this interrupt handler will set the MSP to the + * stack pointer of the interrupted thread. If the interrupted thread was a privileged + * thread, that will be the MSP otherwise it will be the PSP. If the PSP is used, then the + * value of the MSP will be invalid when the interrupt handler returns because it will be a + * pointer to an old position in the unprivileged stack. Then when the high priority + * interrupt occurs and uses this stale MSP, there will most likely be a system failure. + * + * If the interrupt stack is selected, on the other hand, then the interrupt handler will + * always set the the MSP to the interrupt stack. So when the high priority interrupt occurs, + * it will either use the MSP of the last privileged thread to run or, in the case of the + * nested interrupt, the interrupt stack if no privileged task has run. + */ + +# if defined(CONFIG_NUTTX_KERNEL) && CONFIG_ARCH_INTERRUPTSTACK < 4 +# error Interrupt stack must be used with high priority interrupts in kernel mode +# endif + + /* Use the the BASEPRI to control interrupts is required if nested, high + * priority interrupts are supported. + */ + +# ifndef CONFIG_ARMV7M_USEBASEPRI +# error CONFIG_ARMV7M_USEBASEPRI must be used with CONFIG_ARCH_HIPRI_INTERRUPT +# endif +#endif -/* Memory Map: - * +/* Memory Map ***********************************************************************************/ +/* * 0x0800:0000 - Beginning of FLASH. Address of vectors. Mapped to address 0x0000:0000 at boot * time. * 0x0803:ffff - End of flash @@ -255,23 +283,39 @@ sam_common: stmdb r1!, {r2-r11} /* Save the remaining registers plus the SP value */ #endif +#ifndef CONFIG_ARCH_HIPRI_INTERRUPT /* Disable interrupts, select the stack to use for interrupt handling * and call up_doirq to handle the interrupt */ cpsid i /* Disable further interrupts */ - /* If CONFIG_ARCH_INTERRUPTSTACK is defined, we will use a special interrupt - * stack pointer. The way that this is done here prohibits nested interrupts! - * Otherwise, we will re-use the main stack for interrupt level processing. +#else + /* Set the BASEPRI register so that further normal interrupts will be + * masked. Nested, high priority may still occur, however. */ + mov r2, #NVIC_SYSH_DISABLE_PRIORITY + msr basepri, r2 /* Set the BASEPRI */ +#endif + #if CONFIG_ARCH_INTERRUPTSTACK > 3 + /* If CONFIG_ARCH_INTERRUPTSTACK is defined, we will set the MSP to use + * a special special interrupt stack pointer. The way that this is done + * here prohibits nested interrupts without some additional logic! + */ + ldr sp, =g_intstackbase str r1, [sp, #-4]! /* Save the MSP on the interrupt stack */ bl up_doirq /* R0=IRQ, R1=register save (msp) */ ldr r1, [sp, #+4]! /* Recover R1=main stack pointer */ + #else + /* Otherwise, we will re-use the interrupted thread's stack. That may + * mean using either MSP or PSP stack for interrupt level processing (in + * kernel mode). + */ + mov sp, r1 /* We are using the main stack pointer */ bl up_doirq /* R0=IRQ, R1=register save (msp) */ mov r1, sp /* Recover R1=main stack pointer */ @@ -384,7 +428,10 @@ sam_common: #ifdef CONFIG_ARMV7M_USEBASEPRI msr basepri, r3 /* Restore interrupts priority masking */ +#ifndef CONFIG_ARCH_HIPRI_INTERRUPT cpsie i /* Re-enable interrupts */ +#endif + #else msr primask, r3 /* Restore interrupts */ #endif |