summaryrefslogtreecommitdiff
path: root/nuttx/arch/arm/src/sam34/sam_vectors.S
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2013-12-21 15:05:48 -0600
committerGregory Nutt <gnutt@nuttx.org>2013-12-21 15:05:48 -0600
commitd4c848e5f49652dcb4b38506d3700d8a1e8c2dff (patch)
tree07874b7800338a66451b897bdc5fa7175d4b649e /nuttx/arch/arm/src/sam34/sam_vectors.S
parent61d8a57e974548c1c7ef65e9546976053f6c5a9e (diff)
downloadpx4-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.S57
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