summaryrefslogtreecommitdiff
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
parent61d8a57e974548c1c7ef65e9546976053f6c5a9e (diff)
downloadnuttx-d4c848e5f49652dcb4b38506d3700d8a1e8c2dff.tar.gz
nuttx-d4c848e5f49652dcb4b38506d3700d8a1e8c2dff.tar.bz2
nuttx-d4c848e5f49652dcb4b38506d3700d8a1e8c2dff.zip
Finishes coding of ARMv7-M high priority nested interrupt logic. Still undocumented; still not fully tested
-rw-r--r--nuttx/ChangeLog8
-rw-r--r--nuttx/arch/Kconfig17
-rw-r--r--nuttx/arch/arm/src/armv7-m/up_exception.S67
-rw-r--r--nuttx/arch/arm/src/kinetis/kinetis_vectors.S58
-rw-r--r--nuttx/arch/arm/src/lm/lm_vectors.S61
-rw-r--r--nuttx/arch/arm/src/lpc17xx/lpc17_vectors.S58
-rw-r--r--nuttx/arch/arm/src/sam34/sam_vectors.S57
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_vectors.S60
8 files changed, 351 insertions, 35 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index 3320f5250..0976030f3 100644
--- a/nuttx/ChangeLog
+++ b/nuttx/ChangeLog
@@ -6250,7 +6250,11 @@
autogenerated Documentation/NuttXConfigVariables.html file.
This old configuration variable documentation is now a liability
and, hence, was removed (2013-12-20).
- * nuttx/arch/Kconfig, nuttx/arch/arm/Kconfig, nuttx/arch/arm/include/x/chip.h,
- and nuttx/arch/arm/src/x/x_irq.c where x={kinetis, lm, lpc17xx, lpc43xx,
+ * arch/Kconfig, arch/arm/Kconfig, arch/arm/include/x/chip.h, and
+ and arch/arm/src/x/x_irq.c where x={kinetis, lm, lpc17xx, lpc43xx,
sam34, or stm32}: Beginning of support for nested, high priority
interrupts. Lots more still needs to be done (2013-12-21).
+ * arch/arm/src/armv7-m/up_exception.S and arch/arm/src/x/x_vectors.S:
+ where x={kinetis, lm, lpc17xx, lpc43xx, sam34, or stm32}: completes
+ the basic implementation of nested, high priority interreupts.
+ Still untested and need documentation (2013-12-21).
diff --git a/nuttx/arch/Kconfig b/nuttx/arch/Kconfig
index e9fc690ab..5b3fee8b7 100644
--- a/nuttx/arch/Kconfig
+++ b/nuttx/arch/Kconfig
@@ -281,6 +281,23 @@ config ARCH_HIPRI_INTERRUPT
int up_prioritize_irq(int irq, int priority)
+ NOTE: ARCH_INTERRUPTSTACK must be set in kernel mode (NUTTX_KERNEL).
+ In kernel mode without an interrupt stack, the 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
+
config ARCH_INT_DISABLEALL
bool "Disable high priority interrupts"
default y
diff --git a/nuttx/arch/arm/src/armv7-m/up_exception.S b/nuttx/arch/arm/src/armv7-m/up_exception.S
index a40ddf66f..3eb8f97e3 100644
--- a/nuttx/arch/arm/src/armv7-m/up_exception.S
+++ b/nuttx/arch/arm/src/armv7-m/up_exception.S
@@ -46,6 +46,40 @@
#include "chip.h"
/************************************************************************************
+ * Pre-processor 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
+
+/************************************************************************************
* Global Symbols
************************************************************************************/
@@ -76,7 +110,7 @@
* R14 Contains the EXC_RETURN value
* We are in handler mode and the current SP is the MSP
*
- * If CONFIG_ARCH_FPU is defined, the volatile FP registers and FPSCR are on the
+ * If CONFIG_ARCH_FPU is defined, the volatile FP registers and FPSCR are on the
* return stack immediately above REG_XPSR.
*/
@@ -114,8 +148,8 @@ exception_common:
* as they are restored before returning, so we can't assume that we can get at the
* true values of these registers in any routine called from here.
*
- * XXX we could do all this saving lazily on the context switch side if we knew where to put
- * the registers.
+ * REVISIT: we could do all this saving lazily on the context switch side if we knew
+ * where to put the registers.
*/
vstmdb r1!, {s16-s31} /* Save the non-volatile FP context */
@@ -124,23 +158,39 @@ exception_common:
stmdb r1!, {r2-r11,r14} /* Save the remaining registers plus the SP/PRIMASK values */
+#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 use the stack that was current when the interrupt was taken.
+#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
push {r1} /* Save the MSP on the interrupt stack */
bl up_doirq /* R0=IRQ, R1=register save area on stack */
pop {r1} /* 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).
+ */
+
msr msp, r1 /* We are using the main stack pointer */
bl up_doirq /* R0=IRQ, R1=register save area on stack */
mrs r1, msp /* Recover R1=main stack pointer */
@@ -198,7 +248,7 @@ exception_common:
#endif
2:
- /* The EXC_RETURN value tells us whether we are returning on the MSP or PSP
+ /* The EXC_RETURN value tells us whether we are returning on the MSP or PSP
*/
#ifdef CONFIG_NUTTX_KERNEL
@@ -230,7 +280,10 @@ exception_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
diff --git a/nuttx/arch/arm/src/kinetis/kinetis_vectors.S b/nuttx/arch/arm/src/kinetis/kinetis_vectors.S
index 7508d077a..5bf9ce3ba 100644
--- a/nuttx/arch/arm/src/kinetis/kinetis_vectors.S
+++ b/nuttx/arch/arm/src/kinetis/kinetis_vectors.S
@@ -47,8 +47,37 @@
/************************************************************************************************
* Preprocessor Definitions
************************************************************************************************/
-/* Memory Map:
- *
+/* 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 ***********************************************************************************/
+/*
* 0x0000:0000 - Beginning of FLASH. Address of vectors
* 0x1800:0000 - Start of CPU SRAM and start of .data (_sdata)
* - End of .data (_edata) and start of .bss (_sbss)
@@ -637,23 +666,39 @@ kinetis_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 */
@@ -766,7 +811,10 @@ kinetis_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
diff --git a/nuttx/arch/arm/src/lm/lm_vectors.S b/nuttx/arch/arm/src/lm/lm_vectors.S
index e48f8833b..6635fa906 100644
--- a/nuttx/arch/arm/src/lm/lm_vectors.S
+++ b/nuttx/arch/arm/src/lm/lm_vectors.S
@@ -2,7 +2,7 @@
* arch/arm/src/lm/lm_vectors.S
* arch/arm/src/chip/lm_vectors.S
*
- * Copyright (C) 2009-2010 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2009-2010, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -52,9 +52,39 @@
/************************************************************************************
* 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 ***********************************************************************/
+/*
* 0x0000:0000 - Beginning of FLASH. Address of vectors (if not using bootloader)
* 0x0002:0000 - Address of vectors if using bootloader
* 0x0003:ffff - End of flash
@@ -240,23 +270,39 @@ lm_irqcommon:
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 */
@@ -369,7 +415,10 @@ lm_irqcommon:
#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
diff --git a/nuttx/arch/arm/src/lpc17xx/lpc17_vectors.S b/nuttx/arch/arm/src/lpc17xx/lpc17_vectors.S
index c0b79b048..beb44d5e6 100644
--- a/nuttx/arch/arm/src/lpc17xx/lpc17_vectors.S
+++ b/nuttx/arch/arm/src/lpc17xx/lpc17_vectors.S
@@ -48,8 +48,37 @@
/************************************************************************************************
* Preprocessor Definitions
************************************************************************************************/
-/* Memory Map:
- *
+/* 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 ***********************************************************************************/
+/*
* 0x0000:0000 - Beginning of FLASH. Address of vectors
* 0x0003:ffff - End of flash
* 0x1000:0000 - Start of CPU SRAM and start of .data (_sdata)
@@ -249,23 +278,39 @@ lpc17_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 */
@@ -378,7 +423,10 @@ lpc17_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
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
diff --git a/nuttx/arch/arm/src/stm32/stm32_vectors.S b/nuttx/arch/arm/src/stm32/stm32_vectors.S
index d16192f71..e6e6d31dd 100644
--- a/nuttx/arch/arm/src/stm32/stm32_vectors.S
+++ b/nuttx/arch/arm/src/stm32/stm32_vectors.S
@@ -52,8 +52,39 @@
/************************************************************************************
* Preprocessor Definitions
************************************************************************************/
-/* Memory Map:
- *
+/* 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 ***********************************************************************/
+/*
* 0x0800:0000 - Beginning of FLASH. Address of vectors (if not using bootloader)
* Mapped to address 0x0000:0000 at boot time.
* 0x0800:3000 - Address of vectors if using bootloader
@@ -262,23 +293,39 @@ stm32_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 */
@@ -391,7 +438,10 @@ stm32_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