This is an automated email from the ASF dual-hosted git repository. xiaoxiang pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 2684642a7a846ed367bdd4e57e9cfb060cfe0411 Author: wangming9 <[email protected]> AuthorDate: Wed Jul 5 21:37:14 2023 +0800 arch/armv6-m: Supports interrupt nesting 1、The process stack supports interrupt nesting, Execute in MSP; 2、The interrupt stack supports interrupt nesting; The thread mode use PSP, and the handle mode use MSP; 3、Adjust arm_doirq、exception_common implementation to meet interrupt nesting 4、Adjust the conditions for returning MSP and PSP; 5、remove setintstack; Signed-off-by: wangming9 <[email protected]> --- arch/arm/src/armv6-m/arm_doirq.c | 18 +++-------- arch/arm/src/armv6-m/arm_exception.S | 40 ++++++++----------------- arch/arm/src/armv6-m/arm_initialstate.c | 45 +++++++++++++++++++++++++++- arch/arm/src/armv6-m/arm_schedulesigaction.c | 12 ++++---- arch/arm/src/armv6-m/arm_svcall.c | 10 +++---- arch/arm/src/armv6-m/exc_return.h | 16 +++++----- arch/arm/src/rp2040/chip.h | 21 ------------- arch/arm/src/rp2040/rp2040_cpustart.c | 6 ++++ 8 files changed, 85 insertions(+), 83 deletions(-) diff --git a/arch/arm/src/armv6-m/arm_doirq.c b/arch/arm/src/armv6-m/arm_doirq.c index 7abd54145f..80b076636f 100644 --- a/arch/arm/src/armv6-m/arm_doirq.c +++ b/arch/arm/src/armv6-m/arm_doirq.c @@ -34,6 +34,7 @@ #include <sched/sched.h> #include "arm_internal.h" +#include "exc_return.h" /**************************************************************************** * Public Functions @@ -46,20 +47,9 @@ uint32_t *arm_doirq(int irq, uint32_t *regs) PANIC(); #else - /* Nested interrupts are not supported in this implementation. If you - * want to implement nested interrupts, you would have to (1) change the - * way that CURRENT_REGS is handled and (2) the design associated with - * CONFIG_ARCH_INTERRUPTSTACK. - */ - - /* Current regs non-zero indicates that we are processing an interrupt; - * CURRENT_REGS is also used to manage interrupt level context switches. - */ - - if (CURRENT_REGS == NULL) + if (regs[REG_EXC_RETURN] & EXC_RETURN_THREAD_MODE) { CURRENT_REGS = regs; - regs = NULL; } /* Acknowledge the interrupt */ @@ -68,7 +58,7 @@ uint32_t *arm_doirq(int irq, uint32_t *regs) /* Deliver the IRQ */ - irq_dispatch(irq, (uint32_t *)CURRENT_REGS); + irq_dispatch(irq, regs); /* If a context switch occurred while processing the interrupt then * CURRENT_REGS may have change value. If we return any value different @@ -76,7 +66,7 @@ uint32_t *arm_doirq(int irq, uint32_t *regs) * switch occurred during interrupt processing. */ - if (regs == NULL) + if (regs[REG_EXC_RETURN] & EXC_RETURN_THREAD_MODE) { /* Restore the cpu lock */ diff --git a/arch/arm/src/armv6-m/arm_exception.S b/arch/arm/src/armv6-m/arm_exception.S index a2c6ce854b..6408d4d1f1 100644 --- a/arch/arm/src/armv6-m/arm_exception.S +++ b/arch/arm/src/armv6-m/arm_exception.S @@ -58,26 +58,6 @@ .globl exception_common .file "arm_exception.S" -/**************************************************************************** - * Macro Definitions - ****************************************************************************/ - -/**************************************************************************** - * Name: setintstack - * - * Description: - * Set the current stack pointer to the "top" the interrupt stack. Single CPU - * case. Must be provided by MCU-specific logic in the SMP case. - * - ****************************************************************************/ - -#if !defined(CONFIG_SMP) && CONFIG_ARCH_INTERRUPTSTACK > 3 - .macro setintstack, tmp1, tmp2 - ldr \tmp1, =g_intstacktop - mov sp, \tmp1 - .endm -#endif - /**************************************************************************** * .text ****************************************************************************/ @@ -118,10 +98,13 @@ exception_common: lsls r0, #(31 - EXC_RETURN_PROCESS_BITNO) /* Move to bit 31 */ bmi 1f /* Test bit 31 */ mrs r1, msp /* R1=The main stack pointer */ + subs r1, #SW_XCPT_SIZE /* R1=Beginning of context array on the stack */ + msr msp, r1 /* Reserved stack space */ b 2f 1: mrs r1, psp /* R1=The process stack pointer */ + subs r1, #SW_XCPT_SIZE /* R1=Beginning of context array on the stack */ /* R1 is the current stack pointer. HW_XCPT_REGS were pushed onto the stack * when the interrupt was taken so (R1)+HW_XCPT_SIZE is the value of the @@ -133,7 +116,6 @@ exception_common: 2: /* Save SP, PRIMASK, and R4-R7 in the context array */ - subs r1, #SW_XCPT_SIZE /* R1=Beginning of context array on the stack */ movs r2, #XCPTCONTEXT_SIZE /* R2=Size of the context array */ add r2, r1 /* R2=MSP/PSP before the interrupt was taken */ /* (ignoring the xPSR[9] alignment bit) */ @@ -160,9 +142,7 @@ exception_common: * Otherwise, we will use the stack that was current when the interrupt was taken. */ -#if CONFIG_ARCH_INTERRUPTSTACK > 3 - setintstack r7, r6 /* SP = IRQ stack top */ -#else +#if CONFIG_ARCH_INTERRUPTSTACK < 3 /* If the interrupt stack is disabled, reserve xcpcontext to ensure * that signal processing can have a separate xcpcontext to handle * signal context (reference: arm_schedulesigaction.c): @@ -174,9 +154,13 @@ exception_common: * also the sp should be restore after arm_doirq() */ + mov r2, r14 + lsls r2, #(31 - EXC_RETURN_THREAD_BITNO) /* Move to bit 31 */ + bpl 3f /* Test bit 31 */ mov r2, r1 /* Reserve signal context */ subs r2, r2, #XCPTCONTEXT_SIZE msr msp, r2 /* We are using the main stack pointer */ +3: #endif bl arm_doirq /* R0=IRQ, R1=register save area on stack */ @@ -211,14 +195,14 @@ exception_common: mov r0, r14 /* Copy high register to low register */ lsls r0, #(31 - EXC_RETURN_PROCESS_BITNO) /* Move to bit 31 */ - bmi 3f /* Test bit 31 */ + bmi 4f /* Test bit 31 */ msr msp, r1 /* R1=The main stack pointer */ - b 4f + b 5f -3: +4: msr psp, r1 /* R1=The process stack pointer */ -4: +5: /* Restore the interrupt state */ diff --git a/arch/arm/src/armv6-m/arm_initialstate.c b/arch/arm/src/armv6-m/arm_initialstate.c index fa730969c7..b52c8f3f9b 100644 --- a/arch/arm/src/armv6-m/arm_initialstate.c +++ b/arch/arm/src/armv6-m/arm_initialstate.c @@ -135,7 +135,7 @@ void up_initial_state(struct tcb_s *tcb) * mode before transferring control to the user task. */ - xcp->regs[REG_EXC_RETURN] = EXC_RETURN_PRIVTHR; + xcp->regs[REG_EXC_RETURN] = EXC_RETURN_THREAD; xcp->regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV; @@ -145,3 +145,46 @@ void up_initial_state(struct tcb_s *tcb) xcp->regs[REG_PRIMASK] = 1; #endif /* CONFIG_SUPPRESS_INTERRUPTS */ } + +#if CONFIG_ARCH_INTERRUPTSTACK > 3 +/**************************************************************************** + * Name: arm_initialize_stack + * + * Description: + * If interrupt stack is defined, the PSP and MSP need to be reinitialized. + * + ****************************************************************************/ + +noinline_function void arm_initialize_stack(void) +{ +#ifdef CONFIG_SMP + uint32_t stack = (uint32_t)arm_intstack_top(); +#else + uint32_t stack = (uint32_t)g_intstacktop; +#endif + uint32_t tempa = 0; + uint32_t tempb = 2; + + __asm__ __volatile__ + ( + + /* Initialize PSP */ + + "mov %1, sp\n" + "msr psp, %1\n" + + /* Select PSP */ + + "mrs %1, CONTROL\n" + "orr %1, %2\n" + "msr CONTROL, %1\n" + "isb sy\n" + + /* Initialize MSP */ + + "msr msp, %0\n" + : + : "r" (stack), "r" (tempa), "r" (tempb) + : "memory"); +} +#endif diff --git a/arch/arm/src/armv6-m/arm_schedulesigaction.c b/arch/arm/src/armv6-m/arm_schedulesigaction.c index f03b9e535b..000c2e866c 100644 --- a/arch/arm/src/armv6-m/arm_schedulesigaction.c +++ b/arch/arm/src/armv6-m/arm_schedulesigaction.c @@ -155,8 +155,8 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) CURRENT_REGS[REG_PRIMASK] = 1; CURRENT_REGS[REG_XPSR] = ARMV6M_XPSR_T; #ifdef CONFIG_BUILD_PROTECTED - CURRENT_REGS[REG_LR] = EXC_RETURN_PRIVTHR; - CURRENT_REGS[REG_EXC_RETURN] = EXC_RETURN_PRIVTHR; + CURRENT_REGS[REG_LR] = EXC_RETURN_THREAD; + CURRENT_REGS[REG_EXC_RETURN] = EXC_RETURN_THREAD; CURRENT_REGS[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV; #endif } @@ -200,7 +200,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) tcb->xcp.regs[REG_PRIMASK] = 1; tcb->xcp.regs[REG_XPSR] = ARMV6M_XPSR_T; #ifdef CONFIG_BUILD_PROTECTED - tcb->xcp.regs[REG_LR] = EXC_RETURN_PRIVTHR; + tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD; tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV; #endif } @@ -307,7 +307,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) tcb->xcp.regs[REG_PRIMASK] = 1; tcb->xcp.regs[REG_XPSR] = ARMV6M_XPSR_T; #ifdef CONFIG_BUILD_PROTECTED - tcb->xcp.regs[REG_LR] = EXC_RETURN_PRIVTHR; + tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD; tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV; #endif } @@ -350,7 +350,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) CURRENT_REGS[REG_PRIMASK] = 1; CURRENT_REGS[REG_XPSR] = ARMV6M_XPSR_T; #ifdef CONFIG_BUILD_PROTECTED - CURRENT_REGS[REG_LR] = EXC_RETURN_PRIVTHR; + CURRENT_REGS[REG_LR] = EXC_RETURN_THREAD; CURRENT_REGS[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV; #endif } @@ -409,7 +409,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) tcb->xcp.regs[REG_PRIMASK] = 1; tcb->xcp.regs[REG_XPSR] = ARMV6M_XPSR_T; #ifdef CONFIG_BUILD_PROTECTED - tcb->xcp.regs[REG_LR] = EXC_RETURN_PRIVTHR; + tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD; tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV; #endif } diff --git a/arch/arm/src/armv6-m/arm_svcall.c b/arch/arm/src/armv6-m/arm_svcall.c index 231c796301..2775079dca 100644 --- a/arch/arm/src/armv6-m/arm_svcall.c +++ b/arch/arm/src/armv6-m/arm_svcall.c @@ -262,7 +262,7 @@ int arm_svcall(int irq, void *context, void *arg) */ regs[REG_PC] = (uint32_t)USERSPACE->task_startup; - regs[REG_EXC_RETURN] = EXC_RETURN_UNPRIVTHR; + regs[REG_EXC_RETURN] = EXC_RETURN_THREAD; /* Return unprivileged mode */ @@ -299,7 +299,7 @@ int arm_svcall(int irq, void *context, void *arg) */ regs[REG_PC] = (uint32_t)regs[REG_R1]; /* startup */ - regs[REG_EXC_RETURN] = EXC_RETURN_UNPRIVTHR; + regs[REG_EXC_RETURN] = EXC_RETURN_THREAD; /* Return unprivileged mode */ @@ -344,7 +344,7 @@ int arm_svcall(int irq, void *context, void *arg) */ regs[REG_PC] = (uint32_t)USERSPACE->signal_handler; - regs[REG_EXC_RETURN] = EXC_RETURN_UNPRIVTHR; + regs[REG_EXC_RETURN] = EXC_RETURN_THREAD; /* Return unprivileged mode */ @@ -381,7 +381,7 @@ int arm_svcall(int irq, void *context, void *arg) DEBUGASSERT(rtcb->xcp.sigreturn != 0); regs[REG_PC] = rtcb->xcp.sigreturn; - regs[REG_EXC_RETURN] = EXC_RETURN_PRIVTHR; + regs[REG_EXC_RETURN] = EXC_RETURN_THREAD; /* Return privileged mode */ @@ -419,7 +419,7 @@ int arm_svcall(int irq, void *context, void *arg) rtcb->xcp.nsyscalls = index + 1; regs[REG_PC] = (uint32_t)dispatch_syscall; - regs[REG_EXC_RETURN] = EXC_RETURN_PRIVTHR; + regs[REG_EXC_RETURN] = EXC_RETURN_THREAD; /* Return privileged mode */ diff --git a/arch/arm/src/armv6-m/exc_return.h b/arch/arm/src/armv6-m/exc_return.h index 007cb22f21..9572afdf17 100644 --- a/arch/arm/src/armv6-m/exc_return.h +++ b/arch/arm/src/armv6-m/exc_return.h @@ -71,17 +71,17 @@ #define EXC_RETURN_HANDLER 0xfffffff1 -/* EXC_RETURN_PRIVTHR: Return to privileged thread mode. Exception return - * gets state from the main stack. Execution uses MSP after return. - */ +#if CONFIG_ARCH_INTERRUPTSTACK > 3 -#define EXC_RETURN_PRIVTHR 0xfffffff9 +/* Execution uses PSP after return */ -/* EXC_RETURN_UNPRIVTHR: Return to unprivileged thread mode. Exception return - * gets state from the process stack. Execution uses PSP after return. - */ +# define EXC_RETURN_THREAD 0xfffffffd +#else + +/* Execution uses MSP after return */ -#define EXC_RETURN_UNPRIVTHR 0xfffffffd +# define EXC_RETURN_THREAD 0xfffffff9 +#endif /**************************************************************************** * Inline Functions diff --git a/arch/arm/src/rp2040/chip.h b/arch/arm/src/rp2040/chip.h index 480f623ddb..0274144dbc 100644 --- a/arch/arm/src/rp2040/chip.h +++ b/arch/arm/src/rp2040/chip.h @@ -57,26 +57,5 @@ #ifdef __ASSEMBLY__ -/**************************************************************************** - * Name: setintstack - * - * Description: - * Set the current stack pointer to the "top" the correct interrupt stack - * for the current CPU. - * - ****************************************************************************/ - -#if defined(CONFIG_SMP) && CONFIG_ARCH_INTERRUPTSTACK > 3 - .macro setintstack, tmp1, tmp2 - ldr \tmp1, =RP2040_SIO_CPUID - ldr \tmp1, [\tmp1, #0] - lsls \tmp1, \tmp1, #2 - ldr \tmp2, =g_cpu_intstack_top - add \tmp2, \tmp2, \tmp1 - ldr \tmp2, [\tmp2, #0] - mov sp, \tmp2 /* sp = g_cpu_intstack_top[cpuid] */ - .endm -#endif /* CONFIG_SMP && CONFIG_ARCH_INTERRUPTSTACK > 7 */ - #endif /* __ASSEMBLY__ */ #endif /* __ARCH_ARM_SRC_RP2040_CHIP_H */ diff --git a/arch/arm/src/rp2040/rp2040_cpustart.c b/arch/arm/src/rp2040/rp2040_cpustart.c index 977dad7e6d..230246497e 100644 --- a/arch/arm/src/rp2040/rp2040_cpustart.c +++ b/arch/arm/src/rp2040/rp2040_cpustart.c @@ -137,6 +137,12 @@ static int fifo_comm(uint32_t msg) static void core1_boot(void) { +#if CONFIG_ARCH_INTERRUPTSTACK > 3 + /* Initializes the stack pointer */ + + arm_initialize_stack(); +#endif + fifo_drain(); /* Setup NVIC */
