From a031ddc39f404f63f9286c4523a3bcaa159a93ab Mon Sep 17 00:00:00 2001 From: patacongo Date: Sat, 20 Nov 2010 00:39:29 +0000 Subject: [PATCH] Fix Cortex-M3 nested interrupt hard fault git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3119 42af7a65-404d-4744-a932-0658087f49c3 --- arch/arm/include/cortexm3/irq.h | 12 +++++++++++- arch/arm/src/lm3s/lm3s_vectors.S | 15 ++++++++------- arch/arm/src/lpc17xx/lpc17_ethernet.c | 1 - arch/arm/src/lpc17xx/lpc17_vectors.S | 13 +++++++------ arch/arm/src/sam3u/sam3u_vectors.S | 15 ++++++++------- arch/arm/src/stm32/stm32_vectors.S | 13 +++++++------ 6 files changed, 41 insertions(+), 28 deletions(-) diff --git a/arch/arm/include/cortexm3/irq.h b/arch/arm/include/cortexm3/irq.h index de38585c39b..3f731385b46 100644 --- a/arch/arm/include/cortexm3/irq.h +++ b/arch/arm/include/cortexm3/irq.h @@ -244,7 +244,7 @@ static inline void setbasepri(uint32_t basepri) : "memory"); } -/* Get IPSR */ +/* Get/set IPSR */ static inline uint32_t getipsr(void) { @@ -258,6 +258,16 @@ static inline uint32_t getipsr(void) return ipsr; } +static inline void setipsr(uint32_t ipsr) +{ + __asm__ __volatile__ + ( + "\tmsr ipsr, %0\n" + : + : "r" (ipsr) + : "memory"); +} + /* SVC system call */ static inline void svcall(uint32_t cmd, uint32_t arg) diff --git a/arch/arm/src/lm3s/lm3s_vectors.S b/arch/arm/src/lm3s/lm3s_vectors.S index 5d6f7962e9b..b88b52c8b08 100644 --- a/arch/arm/src/lm3s/lm3s_vectors.S +++ b/arch/arm/src/lm3s/lm3s_vectors.S @@ -607,7 +607,7 @@ lm3s_irqcommon: * values to the stack. */ - add r1, r0, #SW_XCPT_SIZE /* R1=Address of HW save area in reg array */ + add r1, r0, #SW_XCPT_SIZE /* R1=Address of HW save area in reg array */ ldmia r1, {r4-r11} /* Fetch eight registers in HW save area */ ldr r1, [r0, #(4*REG_SP)] /* R1=Value of SP before interrupt */ stmdb r1!, {r4-r11} /* Store eight registers in HW save area */ @@ -622,17 +622,18 @@ lm3s_irqcommon: 2: msr msp, r1 /* Recover the return MSP value */ - /* Do we need to restore interrupts? */ + /* Restore the interrupt state. Preload r14 with the special return + * value first (so that the return actually occurs with interrupts + * still disabled). + */ - tst r3, #1 /* PRIMASK bit 1=1 means that interrupts are masked */ - bne 3f - cpsie i /* Restore interrupts */ + ldr r14, =EXC_RETURN /* Load the special value */ + msr primask, r3 /* Restore interrupts */ /* Always return with R14 containing the special value that will: (1) * return to thread mode, and (2) continue to use the MSP */ -3: - ldr r14, =EXC_RETURN /* Load the special value */ + bx r14 /* And return */ .size handlers, .-handlers diff --git a/arch/arm/src/lpc17xx/lpc17_ethernet.c b/arch/arm/src/lpc17xx/lpc17_ethernet.c index dc9c8b2c6b3..6742b33a283 100644 --- a/arch/arm/src/lpc17xx/lpc17_ethernet.c +++ b/arch/arm/src/lpc17xx/lpc17_ethernet.c @@ -1124,7 +1124,6 @@ static int lpc17_interrupt(int irq, void *context) lpc17_putreg(ETH_INT_WKUP, LPC17_ETH_INTCLR); EMAC_STAT(priv, wol); # warning "Missing logic" - goto intexit; } else #endif diff --git a/arch/arm/src/lpc17xx/lpc17_vectors.S b/arch/arm/src/lpc17xx/lpc17_vectors.S index ae36da345f9..ed0f10fad68 100755 --- a/arch/arm/src/lpc17xx/lpc17_vectors.S +++ b/arch/arm/src/lpc17xx/lpc17_vectors.S @@ -295,17 +295,18 @@ lpc17_common: 2: msr msp, r1 /* Recover the return MSP value */ - /* Do we need to restore interrupts? Why not just: msr primask, r3 */ + /* Restore the interrupt state. Preload r14 with the special return + * value first (so that the return actually occurs with interrupts + * still disabled). + */ - tst r3, #1 /* PRIMASK bit 1=1 means that interrupts are masked */ - bne 3f - cpsie i /* Restore interrupts */ + ldr r14, =EXC_RETURN /* Load the special value */ + msr primask, r3 /* Restore interrupts */ /* Always return with R14 containing the special value that will: (1) * return to thread mode, and (2) continue to use the MSP */ -3: - ldr r14, =EXC_RETURN /* Load the special value */ + bx r14 /* And return */ .size handlers, .-handlers diff --git a/arch/arm/src/sam3u/sam3u_vectors.S b/arch/arm/src/sam3u/sam3u_vectors.S index efa7e0a5507..4411cc5b557 100755 --- a/arch/arm/src/sam3u/sam3u_vectors.S +++ b/arch/arm/src/sam3u/sam3u_vectors.S @@ -284,19 +284,20 @@ sam3u_common: 1: ldmia r1!, {r2-r11} /* Recover R4-R11 + 2 temp values */ 2: - msr msp, r1 /* Recover the return MSP value */ + msr msp, r1 /* Recover the return MSP value */ - /* Do we need to restore interrupts? */ + /* Restore the interrupt state. Preload r14 with the special return + * value first (so that the return actually occurs with interrupts + * still disabled). + */ - tst r3, #1 /* PRIMASK bit 1=1 means that interrupts are masked */ - bne 3f - cpsie i /* Restore interrupts */ + ldr r14, =EXC_RETURN /* Load the special value */ + msr primask, r3 /* Restore interrupts */ /* Always return with R14 containing the special value that will: (1) * return to thread mode, and (2) continue to use the MSP */ -3: - ldr r14, =EXC_RETURN /* Load the special value */ + bx r14 /* And return */ .size handlers, .-handlers diff --git a/arch/arm/src/stm32/stm32_vectors.S b/arch/arm/src/stm32/stm32_vectors.S index 7d119f326b9..e0055962ef0 100644 --- a/arch/arm/src/stm32/stm32_vectors.S +++ b/arch/arm/src/stm32/stm32_vectors.S @@ -478,17 +478,18 @@ stm32_common: 2: msr msp, r1 /* Recover the return MSP value */ - /* Do we need to restore interrupts? */ + /* Restore the interrupt state. Preload r14 with the special return + * value first (so that the return actually occurs with interrupts + * still disabled). + */ - tst r3, #1 /* PRIMASK bit 1=1 means that interrupts are masked */ - bne 3f - cpsie i /* Restore interrupts */ + ldr r14, =EXC_RETURN /* Load the special value */ + msr primask, r3 /* Restore interrupts */ /* Always return with R14 containing the special value that will: (1) * return to thread mode, and (2) continue to use the MSP */ -3: - ldr r14, =EXC_RETURN /* Load the special value */ + bx r14 /* And return */ .size handlers, .-handlers