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 */

Reply via email to