summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2013-12-23 14:11:32 -0600
committerGregory Nutt <gnutt@nuttx.org>2013-12-23 14:11:32 -0600
commit92fd02fcc98084502fad0d251b50d6f9261da353 (patch)
treed00ad3c287176d5cc5e5d6a20284de9c9e9f4ab2
parent510b3dc3b44605010d2a1434f8cbe5e6f5e45a2b (diff)
downloadnuttx-92fd02fcc98084502fad0d251b50d6f9261da353.tar.gz
nuttx-92fd02fcc98084502fad0d251b50d6f9261da353.tar.bz2
nuttx-92fd02fcc98084502fad0d251b50d6f9261da353.zip
Need to protect state on stack to do nested interrupt handling
-rw-r--r--nuttx/ChangeLog6
-rw-r--r--nuttx/arch/arm/src/armv7-m/up_exception.S40
-rw-r--r--nuttx/arch/arm/src/kinetis/kinetis_vectors.S29
-rw-r--r--nuttx/arch/arm/src/lm/lm_vectors.S29
-rw-r--r--nuttx/arch/arm/src/lpc17xx/lpc17_vectors.S29
-rw-r--r--nuttx/arch/arm/src/sam34/sam_vectors.S29
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_vectors.S29
7 files changed, 120 insertions, 71 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index ba2493b8b..ea4f976a6 100644
--- a/nuttx/ChangeLog
+++ b/nuttx/ChangeLog
@@ -6283,3 +6283,9 @@
beginning of SRAM. It seems to require this alignament. Also, we
don't need different scripts for the CMNVECTOR case now that the vector
table has a common name.
+ * arch/arm/src: armv-7/up_exception.S and xxx/xxx_vectors.S where
+ xxx={kinetis, lm, lpc17xx, sam34, and stm32}: Modified register usage
+ when saving the context on the stack: In order to handler nested
+ interrupts, the stack pointer must be used so that when it is
+ decremented, the contents on the stack are protected from the nested
+ interrupt handling (2013-12-23).
diff --git a/nuttx/arch/arm/src/armv7-m/up_exception.S b/nuttx/arch/arm/src/armv7-m/up_exception.S
index 3eb8f97e3..517525415 100644
--- a/nuttx/arch/arm/src/armv7-m/up_exception.S
+++ b/nuttx/arch/arm/src/armv7-m/up_exception.S
@@ -126,11 +126,12 @@ exception_common:
/* The EXC_RETURN value tells us whether the context is on the MSP or PSP */
tst r14, #EXC_RETURN_PROCESS_STACK /* nonzero if context on process stack */
- ite eq /* next two instructions conditional */
- mrseq r1, msp /* R1=The main stack pointer */
- mrsne r1, psp /* R1=The process stack pointer */
+ beq 1f /* Branch if context already on the MSP */
+ mrs r1, psp /* R1=The process stack pointer (PSP) */
+ mov sp, r1 /* Set the MSP to the PSP */
- mov r2, r1 /* R2=Copy of the main/process stack pointer */
+1:
+ mov r2, sp /* R2=Copy of the main/process stack pointer */
add r2, #HW_XCPT_SIZE /* R2=MSP/PSP before the interrupt was taken */
/* (ignoring the xPSR[9] alignment bit) */
#ifdef CONFIG_ARMV7M_USEBASEPRI
@@ -152,11 +153,11 @@ exception_common:
* where to put the registers.
*/
- vstmdb r1!, {s16-s31} /* Save the non-volatile FP context */
+ vstmdb sp!, {s16-s31} /* Save the non-volatile FP context */
#endif
- stmdb r1!, {r2-r11,r14} /* Save the remaining registers plus the SP/PRIMASK values */
+ stmdb sp!, {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
@@ -174,6 +175,14 @@ exception_common:
msr basepri, r2 /* Set the BASEPRI */
#endif
+ /* There are two arguments to up_doirq:
+ *
+ * R0 = The IRQ number
+ * R1 = The top of the stack points to the saved state
+ */
+
+ mov r1, sp
+
#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
@@ -191,9 +200,8 @@ exception_common:
* 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 */
+ mrs r1, msp /* Get R1=main stack pointer */
#endif
/* On return from up_doirq, R0 will hold a pointer to register context
@@ -202,7 +210,7 @@ exception_common:
*/
cmp r0, r1 /* Context switch? */
- beq 1f /* Branch if no context switch */
+ beq 2f /* Branch if no context switch */
/* We are returning with a pending context switch. This case is different
* because in this case, the register save structure does not lie on the
@@ -235,9 +243,9 @@ exception_common:
vldmia r0, {s16-s31} /* Recover S16-S31 */
#endif
- b 2f /* Re-join common logic */
+ b 3f /* Re-join common logic */
-1:
+2:
/* We are returning with no context switch. We simply need to "unwind"
* the same stack frame that we created at entry.
*/
@@ -247,7 +255,7 @@ exception_common:
vldmia r1!, {s16-s31} /* Recover S16-S31 */
#endif
-2:
+3:
/* The EXC_RETURN value tells us whether we are returning on the MSP or PSP
*/
@@ -259,15 +267,15 @@ exception_common:
mrs r2, control /* R2=Contents of the control register */
tst r14, #EXC_RETURN_PROCESS_STACK /* nonzero if context on process stack */
- beq 3f /* Branch if privileged */
+ beq 4f /* Branch if privileged */
orr r2, r2, #1 /* Unprivileged mode */
msr psp, r1 /* R1=The process stack pointer */
- b 4f
-3:
+ b 5f
+4:
bic r2, r2, #1 /* Privileged mode */
msr msp, r1 /* R1=The main stack pointer */
-4:
+5:
msr control, r2 /* Save the updated control register */
#else
tst r14, #EXC_RETURN_PROCESS_STACK /* nonzero if context on process stack */
diff --git a/nuttx/arch/arm/src/kinetis/kinetis_vectors.S b/nuttx/arch/arm/src/kinetis/kinetis_vectors.S
index 619f133a2..be597cfa9 100644
--- a/nuttx/arch/arm/src/kinetis/kinetis_vectors.S
+++ b/nuttx/arch/arm/src/kinetis/kinetis_vectors.S
@@ -627,12 +627,12 @@ exception_common:
* EXC_RETURN is 0xfffffffd (unprivileged thread)
*/
- adds r2, r14, #3 /* If R14=0xfffffffd, then r2 == 0 */
- ite ne /* Next two instructions are conditional */
- mrsne r1, msp /* R1=The main stack pointer */
- mrseq r1, psp /* R1=The process stack pointer */
-#else
- mrs r1, msp /* R1=The main stack pointer */
+ tst r14, #EXC_RETURN_PROCESS_STACK /* nonzero if context on process stack */
+ beq 1f /* Branch if context already on the MSP */
+ mrs r1, psp /* R1=The process stack pointer (PSP) */
+ mov sp, r1 /* Set the MSP to the PSP */
+
+1:
#endif
/* r1 holds the value of the stack pointer AFTER the excption handling logic
@@ -640,7 +640,7 @@ exception_common:
* stack pointer BEFORE the interrupt modified it.
*/
- mov r2, r1 /* R2=Copy of the main/process stack pointer */
+ mov r2, sp /* R2=Copy of the main/process stack pointer */
add r2, #HW_XCPT_SIZE /* R2=MSP/PSP before the interrupt was taken */
#ifdef CONFIG_ARMV7M_USEBASEPRI
mrs r3, basepri /* R3=Current BASEPRI setting */
@@ -655,7 +655,7 @@ exception_common:
* cannot be used in interrupt processing).
*/
- sub r1, #(4*SW_FPU_REGS)
+ sub sp, #(4*SW_FPU_REGS)
#endif
/* Save the remaining registers on the stack after the registers pushed
@@ -664,9 +664,9 @@ exception_common:
*/
#ifdef CONFIG_NUTTX_KERNEL
- stmdb r1!, {r2-r11,r14} /* Save the remaining registers plus the SP value */
+ stmdb sp!, {r2-r11,r14} /* Save the remaining registers plus the SP value */
#else
- stmdb r1!, {r2-r11} /* Save the remaining registers plus the SP value */
+ stmdb sp!, {r2-r11} /* Save the remaining registers plus the SP value */
#endif
#ifndef CONFIG_ARCH_HIPRI_INTERRUPT
@@ -685,6 +685,14 @@ exception_common:
msr basepri, r2 /* Set the BASEPRI */
#endif
+ /* There are two arguments to up_doirq:
+ *
+ * R0 = The IRQ number
+ * R1 = The top of the stack points to the saved state
+ */
+
+ mov r1, sp
+
#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
@@ -702,7 +710,6 @@ exception_common:
* 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 */
#endif
diff --git a/nuttx/arch/arm/src/lm/lm_vectors.S b/nuttx/arch/arm/src/lm/lm_vectors.S
index 796ad5554..bdd65a543 100644
--- a/nuttx/arch/arm/src/lm/lm_vectors.S
+++ b/nuttx/arch/arm/src/lm/lm_vectors.S
@@ -230,12 +230,12 @@ exception_common:
* EXC_RETURN is 0xfffffffd (unprivileged thread)
*/
- adds r2, r14, #3 /* If R14=0xfffffffd, then r2 == 0 */
- ite ne /* Next two instructions are conditional */
- mrsne r1, msp /* R1=The main stack pointer */
- mrseq r1, psp /* R1=The process stack pointer */
-#else
- mrs r1, msp /* R1=The main stack pointer */
+ tst r14, #EXC_RETURN_PROCESS_STACK /* nonzero if context on process stack */
+ beq 1f /* Branch if context already on the MSP */
+ mrs r1, psp /* R1=The process stack pointer (PSP) */
+ mov sp, r1 /* Set the MSP to the PSP */
+
+1:
#endif
/* r1 holds the value of the stack pointer AFTER the excption handling logic
@@ -243,7 +243,7 @@ exception_common:
* stack pointer BEFORE the interrupt modified it.
*/
- mov r2, r1 /* R2=Copy of the main/process stack pointer */
+ mov r2, sp /* R2=Copy of the main/process stack pointer */
add r2, #HW_XCPT_SIZE /* R2=MSP/PSP before the interrupt was taken */
#ifdef CONFIG_ARMV7M_USEBASEPRI
mrs r3, basepri /* R3=Current BASEPRI setting */
@@ -258,7 +258,7 @@ exception_common:
* cannot be used in interrupt processing).
*/
- sub r1, #(4*SW_FPU_REGS)
+ sub sp, #(4*SW_FPU_REGS)
#endif
/* Save the remaining registers on the stack after the registers pushed
@@ -267,9 +267,9 @@ exception_common:
*/
#ifdef CONFIG_NUTTX_KERNEL
- stmdb r1!, {r2-r11,r14} /* Save the remaining registers plus the SP value */
+ stmdb sp!, {r2-r11,r14} /* Save the remaining registers plus the SP value */
#else
- stmdb r1!, {r2-r11} /* Save the remaining registers plus the SP value */
+ stmdb sp!, {r2-r11} /* Save the remaining registers plus the SP value */
#endif
#ifndef CONFIG_ARCH_HIPRI_INTERRUPT
@@ -288,6 +288,14 @@ exception_common:
msr basepri, r2 /* Set the BASEPRI */
#endif
+ /* There are two arguments to up_doirq:
+ *
+ * R0 = The IRQ number
+ * R1 = The top of the stack points to the saved state
+ */
+
+ mov r1, sp
+
#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
@@ -305,7 +313,6 @@ exception_common:
* 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 */
#endif
diff --git a/nuttx/arch/arm/src/lpc17xx/lpc17_vectors.S b/nuttx/arch/arm/src/lpc17xx/lpc17_vectors.S
index 4be59a4d6..dc4a7a305 100644
--- a/nuttx/arch/arm/src/lpc17xx/lpc17_vectors.S
+++ b/nuttx/arch/arm/src/lpc17xx/lpc17_vectors.S
@@ -239,12 +239,12 @@ exception_common:
* EXC_RETURN is 0xfffffffd (unprivileged thread)
*/
- adds r2, r14, #3 /* If R14=0xfffffffd, then r2 == 0 */
- ite ne /* Next two instructions are conditional */
- mrsne r1, msp /* R1=The main stack pointer */
- mrseq r1, psp /* R1=The process stack pointer */
-#else
- mrs r1, msp /* R1=The main stack pointer */
+ tst r14, #EXC_RETURN_PROCESS_STACK /* nonzero if context on process stack */
+ beq 1f /* Branch if context already on the MSP */
+ mrs r1, psp /* R1=The process stack pointer (PSP) */
+ mov sp, r1 /* Set the MSP to the PSP */
+
+1:
#endif
/* r1 holds the value of the stack pointer AFTER the excption handling logic
@@ -252,7 +252,7 @@ exception_common:
* stack pointer BEFORE the interrupt modified it.
*/
- mov r2, r1 /* R2=Copy of the main/process stack pointer */
+ mov r2, sp /* R2=Copy of the main/process stack pointer */
add r2, #HW_XCPT_SIZE /* R2=MSP/PSP before the interrupt was taken */
#ifdef CONFIG_ARMV7M_USEBASEPRI
mrs r3, basepri /* R3=Current BASEPRI setting */
@@ -267,7 +267,7 @@ exception_common:
* cannot be used in interrupt processing).
*/
- sub r1, #(4*SW_FPU_REGS)
+ sub sp, #(4*SW_FPU_REGS)
#endif
/* Save the remaining registers on the stack after the registers pushed
@@ -276,9 +276,9 @@ exception_common:
*/
#ifdef CONFIG_NUTTX_KERNEL
- stmdb r1!, {r2-r11,r14} /* Save the remaining registers plus the SP value */
+ stmdb sp!, {r2-r11,r14} /* Save the remaining registers plus the SP value */
#else
- stmdb r1!, {r2-r11} /* Save the remaining registers plus the SP value */
+ stmdb sp!, {r2-r11} /* Save the remaining registers plus the SP value */
#endif
#ifndef CONFIG_ARCH_HIPRI_INTERRUPT
@@ -297,6 +297,14 @@ exception_common:
msr basepri, r2 /* Set the BASEPRI */
#endif
+ /* There are two arguments to up_doirq:
+ *
+ * R0 = The IRQ number
+ * R1 = The top of the stack points to the saved state
+ */
+
+ mov r1, sp
+
#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
@@ -314,7 +322,6 @@ exception_common:
* 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 */
#endif
diff --git a/nuttx/arch/arm/src/sam34/sam_vectors.S b/nuttx/arch/arm/src/sam34/sam_vectors.S
index 4631ad13e..6ef3e2b80 100644
--- a/nuttx/arch/arm/src/sam34/sam_vectors.S
+++ b/nuttx/arch/arm/src/sam34/sam_vectors.S
@@ -244,12 +244,12 @@ exception_common:
* EXC_RETURN is 0xfffffffd (unprivileged thread)
*/
- adds r2, r14, #3 /* If R14=0xfffffffd, then r2 == 0 */
- ite ne /* Next two instructions are conditional */
- mrsne r1, msp /* R1=The main stack pointer */
- mrseq r1, psp /* R1=The process stack pointer */
-#else
- mrs r1, msp /* R1=The main stack pointer */
+ tst r14, #EXC_RETURN_PROCESS_STACK /* nonzero if context on process stack */
+ beq 1f /* Branch if context already on the MSP */
+ mrs r1, psp /* R1=The process stack pointer (PSP) */
+ mov sp, r1 /* Set the MSP to the PSP */
+
+1:
#endif
/* r1 holds the value of the stack pointer AFTER the excption handling logic
@@ -257,7 +257,7 @@ exception_common:
* stack pointer BEFORE the interrupt modified it.
*/
- mov r2, r1 /* R2=Copy of the main/process stack pointer */
+ mov r2, sp /* R2=Copy of the main/process stack pointer */
add r2, #HW_XCPT_SIZE /* R2=MSP/PSP before the interrupt was taken */
#ifdef CONFIG_ARMV7M_USEBASEPRI
mrs r3, basepri /* R3=Current BASEPRI setting */
@@ -272,7 +272,7 @@ exception_common:
* cannot be used in interrupt processing).
*/
- sub r1, #(4*SW_FPU_REGS)
+ sub sp, #(4*SW_FPU_REGS)
#endif
/* Save the remaining registers on the stack after the registers pushed
@@ -281,9 +281,9 @@ exception_common:
*/
#ifdef CONFIG_NUTTX_KERNEL
- stmdb r1!, {r2-r11,r14} /* Save the remaining registers plus the SP value */
+ stmdb sp!, {r2-r11,r14} /* Save the remaining registers plus the SP value */
#else
- stmdb r1!, {r2-r11} /* Save the remaining registers plus the SP value */
+ stmdb sp!, {r2-r11} /* Save the remaining registers plus the SP value */
#endif
#ifndef CONFIG_ARCH_HIPRI_INTERRUPT
@@ -302,6 +302,14 @@ exception_common:
msr basepri, r2 /* Set the BASEPRI */
#endif
+ /* There are two arguments to up_doirq:
+ *
+ * R0 = The IRQ number
+ * R1 = The top of the stack points to the saved state
+ */
+
+ mov r1, sp
+
#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
@@ -319,7 +327,6 @@ exception_common:
* 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 */
#endif
diff --git a/nuttx/arch/arm/src/stm32/stm32_vectors.S b/nuttx/arch/arm/src/stm32/stm32_vectors.S
index 00f4ebf59..da9eea46c 100644
--- a/nuttx/arch/arm/src/stm32/stm32_vectors.S
+++ b/nuttx/arch/arm/src/stm32/stm32_vectors.S
@@ -254,12 +254,12 @@ exception_common:
* EXC_RETURN is 0xfffffffd (unprivileged thread)
*/
- adds r2, r14, #3 /* If R14=0xfffffffd, then r2 == 0 */
- ite ne /* Next two instructions are conditional */
- mrsne r1, msp /* R1=The main stack pointer */
- mrseq r1, psp /* R1=The process stack pointer */
-#else
- mrs r1, msp /* R1=The main stack pointer */
+ tst r14, #EXC_RETURN_PROCESS_STACK /* nonzero if context on process stack */
+ beq 1f /* Branch if context already on the MSP */
+ mrs r1, psp /* R1=The process stack pointer (PSP) */
+ mov sp, r1 /* Set the MSP to the PSP */
+
+1:
#endif
/* r1 holds the value of the stack pointer AFTER the excption handling logic
@@ -267,7 +267,7 @@ exception_common:
* stack pointer BEFORE the interrupt modified it.
*/
- mov r2, r1 /* R2=Copy of the main/process stack pointer */
+ mov r2, sp /* R2=Copy of the main/process stack pointer */
add r2, #HW_XCPT_SIZE /* R2=MSP/PSP before the interrupt was taken */
#ifdef CONFIG_ARMV7M_USEBASEPRI
mrs r3, basepri /* R3=Current BASEPRI setting */
@@ -282,7 +282,7 @@ exception_common:
* cannot be used in interrupt processing).
*/
- sub r1, #(4*SW_FPU_REGS)
+ sub sp, #(4*SW_FPU_REGS)
#endif
/* Save the remaining registers on the stack after the registers pushed
@@ -291,9 +291,9 @@ exception_common:
*/
#ifdef CONFIG_NUTTX_KERNEL
- stmdb r1!, {r2-r11,r14} /* Save the remaining registers plus the SP value */
+ stmdb sp!, {r2-r11,r14} /* Save the remaining registers plus the SP value */
#else
- stmdb r1!, {r2-r11} /* Save the remaining registers plus the SP value */
+ stmdb sp!, {r2-r11} /* Save the remaining registers plus the SP value */
#endif
#ifndef CONFIG_ARCH_HIPRI_INTERRUPT
@@ -312,6 +312,14 @@ exception_common:
msr basepri, r2 /* Set the BASEPRI */
#endif
+ /* There are two arguments to up_doirq:
+ *
+ * R0 = The IRQ number
+ * R1 = The top of the stack points to the saved state
+ */
+
+ mov r1, sp
+
#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
@@ -329,7 +337,6 @@ exception_common:
* 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 */
#endif