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 816b3fb39940f5dec41d378a229c15d0f638c84c Author: wangming9 <[email protected]> AuthorDate: Wed Jul 5 16:08:52 2023 +0800 arch/armv7-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,add arm_initialize_stack; Signed-off-by: wangming9 <[email protected]> --- arch/arm/src/armv7-m/arm_doirq.c | 18 ++------- arch/arm/src/armv7-m/arm_exception.S | 56 +++++++++------------------- arch/arm/src/armv7-m/arm_initialstate.c | 44 +++++++++++++++++++++- arch/arm/src/armv7-m/arm_schedulesigaction.c | 12 +++--- arch/arm/src/armv7-m/arm_svcall.c | 10 ++--- arch/arm/src/armv7-m/exc_return.h | 31 ++++++++------- arch/arm/src/common/arm_initialize.c | 6 +++ arch/arm/src/common/arm_internal.h | 4 ++ arch/arm/src/cxd56xx/chip.h | 19 ---------- arch/arm/src/cxd56xx/cxd56_cpustart.c | 6 +++ arch/arm/src/lc823450/chip.h | 18 --------- arch/arm/src/lc823450/lc823450_cpustart.c | 6 +++ 12 files changed, 113 insertions(+), 117 deletions(-) diff --git a/arch/arm/src/armv7-m/arm_doirq.c b/arch/arm/src/armv7-m/arm_doirq.c index 564b903142..e7b6411faa 100644 --- a/arch/arm/src/armv7-m/arm_doirq.c +++ b/arch/arm/src/armv7-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/armv7-m/arm_exception.S b/arch/arm/src/armv7-m/arm_exception.S index 6716a9d7f8..de5e8a3852 100644 --- a/arch/arm/src/armv7-m/arm_exception.S +++ b/arch/arm/src/armv7-m/arm_exception.S @@ -92,25 +92,6 @@ .thumb .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 > 7 - .macro setintstack, tmp1, tmp2 - ldr sp, =g_intstacktop - .endm -#endif - /**************************************************************************** * .text ****************************************************************************/ @@ -151,9 +132,14 @@ exception_common: 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 */ + b 2f 1: - mov r2, sp /* R2=Copy of the main/process stack pointer */ + mrs r1, msp /* R1=The main stack pointer (MSP) */ + sub r2, r1, #SW_XCPT_SIZE /* Reserved stack space */ + msr msp, r2 + +2: + mov r2, r1 /* 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 @@ -179,11 +165,11 @@ exception_common: tst r14, #EXC_RETURN_STD_CONTEXT ite eq - vstmdbeq sp!, {s16-s31} /* Save the non-volatile FP context */ - subne sp, #(4*SW_FPU_REGS) + vstmdbeq r1!, {s16-s31} /* Save the non-volatile FP context */ + subne r1, #(4*SW_FPU_REGS) #endif - stmdb sp!, {r2-r12,r14} /* Save the remaining registers plus the SP/PRIMASK values */ + stmdb r1!, {r2-r12,r14} /* Save the remaining registers plus the SP/PRIMASK values */ /* There are two arguments to arm_doirq: * @@ -191,19 +177,10 @@ exception_common: * R1 = The top of the stack points to the saved state */ - mov r1, sp - -#if CONFIG_ARCH_INTERRUPTSTACK > 7 - /* 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! - */ - - setintstack r2, r3 /* SP = IRQ stack top */ -#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). +#if CONFIG_ARCH_INTERRUPTSTACK < 7 + /* If CONFIG_ARCH_INTERRUPTSTACK is not defined, 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). */ /* If the interrupt stack is disabled, reserve xcpcontext to ensure @@ -217,9 +194,12 @@ exception_common: * also the sp should be restore after arm_doirq() */ + tst r14, #EXC_RETURN_THREAD_MODE /* Nonzero if context on thread mode */ + beq 3f /* Branch if context already on the handle mode */ sub r2, r1, #XCPTCONTEXT_SIZE /* Reserve signal context */ bic r2, r2, #7 /* Get the stack pointer with 8-byte alignment */ mov sp, r2 /* Instantiate the aligned stack */ +3: #endif bl arm_doirq /* R0=IRQ, R1=register save (msp) */ @@ -241,7 +221,7 @@ exception_common: /* The EXC_RETURN value tells us whether we are returning on the MSP or PSP */ - tst r14, #EXC_RETURN_PROCESS_STACK /* nonzero if context on process stack */ + tst r14, #EXC_RETURN_PROCESS_STACK /* Nonzero if context on process stack */ ite eq /* Next two instructions conditional */ msreq msp, r0 /* R0=The main stack pointer */ msrne psp, r0 /* R0=The process stack pointer */ diff --git a/arch/arm/src/armv7-m/arm_initialstate.c b/arch/arm/src/armv7-m/arm_initialstate.c index c86390abdc..fe42f23344 100644 --- a/arch/arm/src/armv7-m/arm_initialstate.c +++ b/arch/arm/src/armv7-m/arm_initialstate.c @@ -142,7 +142,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; @@ -168,3 +168,45 @@ void up_initial_state(struct tcb_s *tcb) #endif /* CONFIG_SUPPRESS_INTERRUPTS */ } + +#if CONFIG_ARCH_INTERRUPTSTACK > 7 +/**************************************************************************** + * 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 temp = 0; + + __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" (temp) + : "memory"); +} +#endif diff --git a/arch/arm/src/armv7-m/arm_schedulesigaction.c b/arch/arm/src/armv7-m/arm_schedulesigaction.c index 127e66fe65..16a05c6f3a 100644 --- a/arch/arm/src/armv7-m/arm_schedulesigaction.c +++ b/arch/arm/src/armv7-m/arm_schedulesigaction.c @@ -160,8 +160,8 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) #endif CURRENT_REGS[REG_XPSR] = ARMV7M_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 } @@ -209,7 +209,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) #endif tcb->xcp.regs[REG_XPSR] = ARMV7M_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 } @@ -320,7 +320,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) #endif tcb->xcp.regs[REG_XPSR] = ARMV7M_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 } @@ -367,7 +367,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) #endif CURRENT_REGS[REG_XPSR] = ARMV7M_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 } @@ -430,7 +430,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) #endif tcb->xcp.regs[REG_XPSR] = ARMV7M_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/armv7-m/arm_svcall.c b/arch/arm/src/armv7-m/arm_svcall.c index 336a64dfb7..c761a972a6 100644 --- a/arch/arm/src/armv7-m/arm_svcall.c +++ b/arch/arm/src/armv7-m/arm_svcall.c @@ -271,7 +271,7 @@ int arm_svcall(int irq, void *context, void *arg) */ regs[REG_PC] = (uint32_t)USERSPACE->task_startup & ~1; - regs[REG_EXC_RETURN] = EXC_RETURN_UNPRIVTHR; + regs[REG_EXC_RETURN] = EXC_RETURN_THREAD; /* Return unprivileged mode */ @@ -308,7 +308,7 @@ int arm_svcall(int irq, void *context, void *arg) */ regs[REG_PC] = (uint32_t)regs[REG_R1] & ~1; /* startup */ - regs[REG_EXC_RETURN] = EXC_RETURN_UNPRIVTHR; + regs[REG_EXC_RETURN] = EXC_RETURN_THREAD; /* Return unprivileged mode */ @@ -353,7 +353,7 @@ int arm_svcall(int irq, void *context, void *arg) */ regs[REG_PC] = (uint32_t)USERSPACE->signal_handler & ~1; - regs[REG_EXC_RETURN] = EXC_RETURN_UNPRIVTHR; + regs[REG_EXC_RETURN] = EXC_RETURN_THREAD; /* Return unprivileged mode */ @@ -390,7 +390,7 @@ int arm_svcall(int irq, void *context, void *arg) DEBUGASSERT(rtcb->xcp.sigreturn != 0); regs[REG_PC] = rtcb->xcp.sigreturn & ~1; - regs[REG_EXC_RETURN] = EXC_RETURN_PRIVTHR; + regs[REG_EXC_RETURN] = EXC_RETURN_THREAD; /* Return privileged mode */ @@ -428,7 +428,7 @@ int arm_svcall(int irq, void *context, void *arg) rtcb->xcp.nsyscalls = index + 1; regs[REG_PC] = (uint32_t)dispatch_syscall & ~1; - regs[REG_EXC_RETURN] = EXC_RETURN_PRIVTHR; + regs[REG_EXC_RETURN] = EXC_RETURN_THREAD; /* Return privileged mode */ diff --git a/arch/arm/src/armv7-m/exc_return.h b/arch/arm/src/armv7-m/exc_return.h index ddac01de57..079bddcd14 100644 --- a/arch/arm/src/armv7-m/exc_return.h +++ b/arch/arm/src/armv7-m/exc_return.h @@ -77,29 +77,28 @@ #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. - */ - #ifdef CONFIG_ARCH_FPU -# define EXC_RETURN_PRIVTHR (EXC_RETURN_BASE | EXC_RETURN_THREAD_MODE) +# define EXC_RETURN_FPU 0 #else -# define EXC_RETURN_PRIVTHR (EXC_RETURN_BASE | EXC_RETURN_STD_CONTEXT | \ - EXC_RETURN_THREAD_MODE) +# define EXC_RETURN_FPU EXC_RETURN_STD_CONTEXT #endif -/* EXC_RETURN_UNPRIVTHR: Return to unprivileged thread mode. Exception return - * gets state from the process stack. Execution uses PSP after return. - */ - -#ifdef CONFIG_ARCH_FPU -# define EXC_RETURN_UNPRIVTHR (EXC_RETURN_BASE | EXC_RETURN_THREAD_MODE | \ - EXC_RETURN_PROCESS_STACK) +#if CONFIG_ARCH_INTERRUPTSTACK > 7 +# define EXC_RETURN_STACK EXC_RETURN_PROCESS_STACK #else -# define EXC_RETURN_UNPRIVTHR (EXC_RETURN_BASE | EXC_RETURN_STD_CONTEXT | \ - EXC_RETURN_THREAD_MODE | EXC_RETURN_PROCESS_STACK) +# define EXC_RETURN_STACK 0 #endif +/* EXC_RETURN_THREAD: Return to thread mode. + * If EXC_RETURN_STACK is 0, Return to thread mode. + * Execution uses MSP after return. + * If EXC_RETURN_STACK is EXC_RETURN_PROCESS_STACK, Return to + * thread mode. Execution uses PSP after return. + */ + +#define EXC_RETURN_THREAD (EXC_RETURN_BASE | EXC_RETURN_FPU | \ + EXC_RETURN_THREAD_MODE | EXC_RETURN_STACK) + /**************************************************************************** * Inline Functions ****************************************************************************/ diff --git a/arch/arm/src/common/arm_initialize.c b/arch/arm/src/common/arm_initialize.c index 2b457ef0f4..65a09495e5 100644 --- a/arch/arm/src/common/arm_initialize.c +++ b/arch/arm/src/common/arm_initialize.c @@ -97,6 +97,12 @@ static inline void arm_color_intstack(void) void up_initialize(void) { +#if CONFIG_ARCH_INTERRUPTSTACK > 7 + /* Reinitializes the stack pointer */ + + arm_initialize_stack(); +#endif + /* Colorize the interrupt stack */ arm_color_intstack(); diff --git a/arch/arm/src/common/arm_internal.h b/arch/arm/src/common/arm_internal.h index 75918424c6..ca9517f2ce 100644 --- a/arch/arm/src/common/arm_internal.h +++ b/arch/arm/src/common/arm_internal.h @@ -346,6 +346,10 @@ uintptr_t arm_intstack_alloc(void); uintptr_t arm_intstack_top(void); #endif +#if CONFIG_ARCH_INTERRUPTSTACK > 7 +void weak_function arm_initialize_stack(void); +#endif + /* Exception handling logic unique to the Cortex-M family */ #if defined(CONFIG_ARCH_ARMV6M) || defined(CONFIG_ARCH_ARMV7M) || \ diff --git a/arch/arm/src/cxd56xx/chip.h b/arch/arm/src/cxd56xx/chip.h index c43ff78000..2e6f3e9e08 100644 --- a/arch/arm/src/cxd56xx/chip.h +++ b/arch/arm/src/cxd56xx/chip.h @@ -49,24 +49,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 > 7 - .macro setintstack, tmp1, tmp2 - ldr \tmp1, =CXD56_ADSP_PID - ldr \tmp1, [\tmp1, 0] - sub \tmp1, 2 /* tmp1 = getreg32(CXD56_ADSP_PID) - 2 */ - ldr \tmp2, =g_cpu_intstack_top - ldr sp, [\tmp2, \tmp1, lsl #2] /* sp = g_cpu_intstack_top[tmp1] */ - .endm -#endif /* CONFIG_SMP && CONFIG_ARCH_INTERRUPTSTACK > 7 */ - #endif /* __ASSEMBLY__ */ #endif /* __ARCH_ARM_SRC_CXD56XX_CHIP_H */ diff --git a/arch/arm/src/cxd56xx/cxd56_cpustart.c b/arch/arm/src/cxd56xx/cxd56_cpustart.c index c2071ea718..6f79626b41 100644 --- a/arch/arm/src/cxd56xx/cxd56_cpustart.c +++ b/arch/arm/src/cxd56xx/cxd56_cpustart.c @@ -97,6 +97,12 @@ static void appdsp_boot(void) cpu = up_cpu_index(); DPRINTF("cpu = %d\n", cpu); +#if CONFIG_ARCH_INTERRUPTSTACK > 7 + /* Initializes the stack pointer */ + + arm_initialize_stack(); +#endif + /* Setup NVIC */ up_irqinitialize(); diff --git a/arch/arm/src/lc823450/chip.h b/arch/arm/src/lc823450/chip.h index 952d6018c8..5a703f6c35 100644 --- a/arch/arm/src/lc823450/chip.h +++ b/arch/arm/src/lc823450/chip.h @@ -58,23 +58,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 > 7 - .macro setintstack, tmp1, tmp2 - ldr \tmp1, =CORE_COREID - ldr \tmp1, [\tmp1, 0] /* tmp1 = getreg32(CORE_COREID) */ - ldr \tmp2, =g_cpu_intstack_top - ldr sp, [\tmp2, \tmp1, lsl #2] /* sp = g_cpu_intstack_top[tmp1] */ - .endm -#endif /* CONFIG_SMP && CONFIG_ARCH_INTERRUPTSTACK > 7 */ - #endif /* __ASSEMBLY__ */ #endif /* __ARCH_ARM_SRC_LC823450_CHIP_H */ diff --git a/arch/arm/src/lc823450/lc823450_cpustart.c b/arch/arm/src/lc823450/lc823450_cpustart.c index 5fe44bd671..908eddec82 100644 --- a/arch/arm/src/lc823450/lc823450_cpustart.c +++ b/arch/arm/src/lc823450/lc823450_cpustart.c @@ -89,6 +89,12 @@ static void cpu1_boot(void) DPRINTF("cpu = %d\n", cpu); +#if CONFIG_ARCH_INTERRUPTSTACK > 7 + /* Initializes the stack pointer */ + + arm_initialize_stack(); +#endif + if (cpu == 1) { putreg32((uint32_t)_stext, NVIC_VECTAB); /* use CPU0 vectors */
