diff options
author | patacongo <patacongo@7fd9a85b-ad96-42d3-883c-3090e2eb8679> | 2011-04-08 01:33:21 +0000 |
---|---|---|
committer | patacongo <patacongo@7fd9a85b-ad96-42d3-883c-3090e2eb8679> | 2011-04-08 01:33:21 +0000 |
commit | b6d01fa79d26709eebdd36155eee798444743de3 (patch) | |
tree | 01f2eb0877f875664d664924e456d7187f71ee93 /nuttx/arch/arm/src/sam3u | |
parent | 5a102905ddf90ccddf7d6b1aa68cd0a68ff12825 (diff) |
Modify interrupt handling for privileged/unprivileged mode
git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@3480 7fd9a85b-ad96-42d3-883c-3090e2eb8679
Diffstat (limited to 'nuttx/arch/arm/src/sam3u')
-rwxr-xr-x | nuttx/arch/arm/src/sam3u/sam3u_vectors.S | 63 |
1 files changed, 53 insertions, 10 deletions
diff --git a/nuttx/arch/arm/src/sam3u/sam3u_vectors.S b/nuttx/arch/arm/src/sam3u/sam3u_vectors.S index d035932971..c4ab12ba01 100755 --- a/nuttx/arch/arm/src/sam3u/sam3u_vectors.S +++ b/nuttx/arch/arm/src/sam3u/sam3u_vectors.S @@ -211,7 +211,8 @@ handlers: HANDLER sam3u_dmac, SAM3U_IRQ_DMAC /* Vector 16+28: DMA Controller */ HANDLER sam3u_udphs, SAM3U_IRQ_UDPHS /* Vector 16+29: USB Device High Speed */ -/* Common IRQ handling logic. On entry here, the stack is like the following: +/* Common IRQ handling logic. On entry here, the return stack is on either + * the PSP or the MSP and looks like the following: * * REG_XPSR * REG_R15 @@ -222,18 +223,38 @@ handlers: * REG_R1 * MSP->REG_R0 * - * and R0 contains the IRQ number + * And + * R0 contains the IRQ number + * R14 Contains the EXC_RETURN value + * We are in handler mode and the current SP is the MSP */ sam3u_common: /* Complete the context save */ +#ifdef CONFIG_NUTTX_KERNEL + /* The EXC_RETURN value will be 0xfffffff9 (privileged thread) or 0xfffffff1 + * (handler mode) if the state is on the MSP. It can only be on the PSP if + * EXC_RETURN is 0xfffffffd (unprivileged thread) + */ + + adds r2, r14, #3 /* If R14=0xfffffffd, then r2 == 0 */ + ite ne /* Next two instructions are condition */ + 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 */ - mov r2, r1 /* R2=Copy of the main stack pointer */ - add r2, #HW_XCPT_SIZE /* R2=MSP before the interrupt was taken */ +#endif + + mov r2, r1 /* R2=Copy of the main/process stack pointer */ + add r2, #HW_XCPT_SIZE /* R2=MSP/PSP before the interrupt was taken */ mrs r3, primask /* R3=Current PRIMASK setting */ +#ifdef CONFIG_NUTTX_KERNEL + stmdb r1!, {r2-r11,r14} /* Save the remaining registers plus the SP value */ +#else stmdb r1!, {r2-r11} /* Save the remaining registers plus the SP value */ +#endif /* Disable interrupts, select the stack to use for interrupt handling * and call up_doirq to handle the interrupt @@ -246,7 +267,7 @@ sam3u_common: * Otherwise, we will re-use the main stack for interrupt level processing. */ -#ifdef CONFIG_ARCH_INTERRUPTSTACK +#if CONFIG_ARCH_INTERRUPTSTACK > 3 ldr sp, =g_intstackbase str r1, [sp, #-4]! /* Save the MSP on the interrupt stack */ bl up_doirq /* R0=IRQ, R1=register save (msp) */ @@ -275,23 +296,45 @@ sam3u_common: 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 */ +#ifdef CONFIG_NUTTX_KERNEL + ldmia r0, {r2-r11,r14} /* Recover R4-R11, r14 + 2 temp values */ +#else ldmia r0, {r2-r11} /* Recover R4-R11 + 2 temp values */ +#endif b 2f /* Re-join common logic */ /* We are returning with no context switch. We simply need to "unwind" * the same stack frame that we created */ 1: - ldmia r1!, {r2-r11} /* Recover R4-R11 + 2 temp values */ +#ifdef CONFIG_NUTTX_KERNEL + ldmia r0, {r2-r11,r14} /* Recover R4-R11, r14 + 2 temp values */ +#else + ldmia r0, {r2-r11} /* Recover R4-R11 + 2 temp values */ +#endif 2: - msr msp, r1 /* Recover the return MSP value */ +#ifdef CONFIG_NUTTX_KERNEL + /* The EXC_RETURN value will be 0xfffffff9 (privileged thread) or 0xfffffff1 + * (handler mode) if the state is on the MSP. It can only be on the PSP if + * EXC_RETURN is 0xfffffffd (unprivileged thread) + */ - /* Restore the interrupt state. Preload r14 with the special return - * value first (so that the return actually occurs with interrupts - * still disabled). + adds r0, r14, #3 /* If R14=0xfffffffd, then r0 == 0 */ + ite ne /* Next two instructions are condition */ + msrne msp, r1 /* R1=The main stack pointer */ + msreq psp, r1 /* R1=The process stack pointer */ +#else + msr msp, r1 /* Recover the return MSP value */ + + /* Preload r14 with the special return value first (so that the return + * actually occurs with interrupts still disabled). */ ldr r14, =EXC_RETURN /* Load the special value */ +#endif + + /* Restore the interrupt state */ + msr primask, r3 /* Restore interrupts */ /* Always return with R14 containing the special value that will: (1) |