You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by gn...@apache.org on 2020/02/10 18:40:53 UTC

[incubator-nuttx] 01/03: arch/mips: When a CPU implements an External Interrupt Controller, use the IPL bits to control masking interrupts.

This is an automated email from the ASF dual-hosted git repository.

gnutt pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 0dc1dc605dcc74a01d400cf190cf8595b85bd847
Author: Ouss4 <ab...@gmail.com>
AuthorDate: Sat Feb 1 20:51:10 2020 +0000

    arch/mips: When a CPU implements an External Interrupt Controller,
    use the IPL bits to control masking interrupts.
---
 arch/mips/Kconfig                           |  6 +++++
 arch/mips/include/mips32/cp0.h              | 36 ++++++++++++++++++-----------
 arch/mips/include/mips32/syscall.h          |  2 +-
 arch/mips/include/pic32mx/chip.h            |  8 +++++++
 arch/mips/include/pic32mx/cp0.h             | 12 ++++------
 arch/mips/include/pic32mz/chip.h            |  8 +++++++
 arch/mips/include/pic32mz/cp0.h             | 14 +----------
 arch/mips/include/syscall.h                 |  6 ++---
 arch/mips/src/common/up_idle.c              | 14 -----------
 arch/mips/src/mips32/up_initialstate.c      |  7 +++---
 arch/mips/src/mips32/up_irq.c               | 27 +++++++++++-----------
 arch/mips/src/mips32/up_schedulesigaction.c | 10 ++++----
 arch/mips/src/pic32mx/pic32mx-irq.c         |  4 ++--
 arch/mips/src/pic32mz/pic32mz-irq.c         |  8 +++++--
 14 files changed, 84 insertions(+), 78 deletions(-)

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 616125b..6c20116 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -11,6 +11,7 @@ choice
 config ARCH_CHIP_PIC32MX
 	bool "PIC32MX"
 	select ARCH_MIPS32
+	select ARCH_HAVE_EIC
 	select ARCH_HAVE_IRQPRIO
 	select ARCH_VECNOTIRQ
 	select ARCH_HAVE_RAMFUNCS
@@ -21,6 +22,7 @@ config ARCH_CHIP_PIC32MX
 config ARCH_CHIP_PIC32MZ
 	bool "PIC32MZ"
 	select ARCH_MIPS32
+	select ARCH_HAVE_EIC
 	select ARCH_HAVE_IRQPRIO
 	select ARCH_VECNOTIRQ
 	select ARCH_HAVE_RAMFUNCS
@@ -44,6 +46,10 @@ config ARCH_MIPS_M14K
 	default n
 	select ARCH_HAVE_MICROMIPS
 
+config ARCH_HAVE_EIC
+  bool
+  default n
+
 config ARCH_HAVE_MICROMIPS
 	bool
 	default n
diff --git a/arch/mips/include/mips32/cp0.h b/arch/mips/include/mips32/cp0.h
index 893b1c0..4270e9b 100644
--- a/arch/mips/include/mips32/cp0.h
+++ b/arch/mips/include/mips32/cp0.h
@@ -41,6 +41,7 @@
  ****************************************************************************/
 
 #include <nuttx/config.h>
+#include <arch/chip/chip.h>
 
 /****************************************************************************
  * Pre-processor Definitions
@@ -213,20 +214,27 @@
 #define CP0_STATUS_UX               (1 << 5)  /* Bit 5: Enables 64-bit user address space (Not MIPS32) */
 #define CP0_STATUS_SX               (1 << 6)  /* Bit 6: Enables 64-bit supervisor address space (Not MIPS32) */
 #define CP0_STATUS_KX               (1 << 7)  /* Bit 7: Enables 64-bit kernel address space (Not MIPS32) */
-#define CP0_STATUS_IM_SHIFT         (8)       /* Bits 8-15: Interrupt Mask */
-#define CP0_STATUS_IM_MASK          (0xff << CP0_STATUS_IM_SHIFT)
-#  define CP0_STATUS_IM_SWINTS      (0x03 << CP0_STATUS_IM_SHIFT) /* IM0-1 = Software interrupts */
-#  define CP0_STATUS_IM0            (0x01 << CP0_STATUS_IM_SHIFT)
-#  define CP0_STATUS_IM1            (0x02 << CP0_STATUS_IM_SHIFT)
-#  define CP0_STATUS_IM_HWINTS      (0x7c << CP0_STATUS_IM_SHIFT) /* IM2-6 = Hardware interrupts */
-#  define CP0_STATUS_IM2            (0x04 << CP0_STATUS_IM_SHIFT)
-#  define CP0_STATUS_IM3            (0x08 << CP0_STATUS_IM_SHIFT)
-#  define CP0_STATUS_IM4            (0x10 << CP0_STATUS_IM_SHIFT)
-#  define CP0_STATUS_IM5            (0x20 << CP0_STATUS_IM_SHIFT)
-#  define CP0_STATUS_IM6            (0x40 << CP0_STATUS_IM_SHIFT)
-#  define CP0_STATUS_IM_TIMER       (0x80 << CP0_STATUS_IM_SHIFT) /* IM7 = Hardware/Timer/Perf interrupts */
-#  define CP0_STATUS_IM7            (0x80 << CP0_STATUS_IM_SHIFT)
-#  define CP0_STATUS_IM_ALL         (0xff << CP0_STATUS_IM_SHIFT)
+#ifdef CONFIG_ARCH_HAVE_EIC
+#  define CP0_STATUS_IPL_SHIFT      (10)       /* Bits 10-16+18: Interrupt Mask */
+#  define CP0_STATUS_IPL_MASK       (0x17f << CP0_STATUS_IPL_SHIFT)
+#    define CP0_STATUS_IPL_ENALL    (0x00  << CP0_STATUS_IPL_SHIFT)
+#    define CP0_STATUS_IPL_SW0      ((CHIP_MAX_PRIORITY - 1) << CP0_STATUS_IPL_SHIFT)
+#    define CP0_STATUS_IPL_DISALL   (CHIP_MAX_PRIORITY << CP0_STATUS_IPL_SHIFT)
+#      define CP0_STATUS_INT_ENALL  CP0_STATUS_IPL_ENALL
+#      define CP0_STATUS_INT_SW0    CP0_STATUS_IPL_SW0
+#      define CP0_STATUS_INT_MASK   CP0_STATUS_IPL_MASK
+#      define CP0_STATUS_INT_DISALL CP0_STATUS_IPL_DISALL
+#else
+#  define CP0_STATUS_IM_SHIFT       (8)       /* Bits 8-15: Interrupt Mask */
+#  define CP0_STATUS_IM_MASK        (0xff << CP0_STATUS_IM_SHIFT)
+#    define CP0_STATUS_IM_DISALL    (0x00 << CP0_STATUS_IM_SHIFT)
+#    define CP0_STATUS_IM_SW0       (0x03 << CP0_STATUS_IM_SHIFT) /* IM0-1 = Software interrupts */
+#    define CP0_STATUS_IM_ALL       (0xff << CP0_STATUS_IM_SHIFT)
+#      define CP0_STATUS_INT_ENALL  CP0_STATUS_IM_ALL
+#      define CP0_STATUS_INT_SW0    CP0_STATUS_IM_SW0
+#      define CP0_STATUS_INT_MASK   CP0_STATUS_IM_MASK
+#      define CP0_STATUS_INT_DISALL CP0_STATUS_IM_DISALL
+#endif
 #define CP0_STATUS_IMPL_SHIFT       (16)      /* Bits 16-17: Implementation dependent */
 #define CP0_STATUS_IMPL_MASK        (3 << CP0_STATUS_IMPL_SHIFT)
 #define CP0_STATUS_NMI              (1 << 19) /* Bit 19: Reset exception due to an NMI */
diff --git a/arch/mips/include/mips32/syscall.h b/arch/mips/include/mips32/syscall.h
index a3a69ec..6044df8 100644
--- a/arch/mips/include/mips32/syscall.h
+++ b/arch/mips/include/mips32/syscall.h
@@ -33,7 +33,7 @@
  *
  ****************************************************************************/
 
-/* This file should never be included directed but, rather, only indirectly
+/* This file should never be included directly but, rather, only indirectly
  * through include/syscall.h or include/sys/sycall.h
  */
 
diff --git a/arch/mips/include/pic32mx/chip.h b/arch/mips/include/pic32mx/chip.h
index 1b3266d..d261d89 100644
--- a/arch/mips/include/pic32mx/chip.h
+++ b/arch/mips/include/pic32mx/chip.h
@@ -2400,6 +2400,14 @@
 #  error "Unrecognized PIC32 device
 #endif
 
+/* IPL priority levels *****************************************************/
+/* These priorities will be used by the core to properly disable/mask
+ * interrupts.
+ */
+
+#define CHIP_MIN_PRIORITY    1 /* Minimum priority. */
+#define CHIP_MAX_PRIORITY    7 /* Maximum priority. */
+
 /****************************************************************************
  * Public Types
  ****************************************************************************/
diff --git a/arch/mips/include/pic32mx/cp0.h b/arch/mips/include/pic32mx/cp0.h
index 1007262..c2ef364 100644
--- a/arch/mips/include/pic32mx/cp0.h
+++ b/arch/mips/include/pic32mx/cp0.h
@@ -140,17 +140,15 @@
 #undef CP0_STATUS_PX
 #undef CP0_STATUS_MX
 
-/*   2. The following field is of a different width.  Apparently, it
- *      excludes the software interrupt bits.
+/*   2. The following field is of a different width.
  *
- *      CP0_STATUS_IM   Bits 8-15: Interrupt Mask
- *      Vs.
- *      CP0_STATUS_IPL  Bits 10-15: Interrupt priority level
+ *      CP0_STATUS_IPL  Bits 10-12: Interrupt priority level
  *                      Bitss 8-9 reserved
  */
 
-#define CP0_STATUS_IPL_SHIFT        (10)   /*  Bits 10-15: Interrupt priority level */
-#define CP0_STATUS_IPL_MASK         (0x3f << CP0_STATUS_IPL_SHIFT)
+#undef CP0_STATUS_IPL_MASK
+
+#define CP0_STATUS_IPL_MASK         (0x07 << CP0_STATUS_IPL_SHIFT)
 
 /*   3. Supervisor mode not supported
  *       CP0_STATUS_KSU Bits 3-4: Operating mode (with supervisor mode)
diff --git a/arch/mips/include/pic32mz/chip.h b/arch/mips/include/pic32mz/chip.h
index e6ef4ba..7a8a5bb 100644
--- a/arch/mips/include/pic32mz/chip.h
+++ b/arch/mips/include/pic32mz/chip.h
@@ -198,6 +198,14 @@
 #  error "Unrecognized PIC32MZ device"
 #endif
 
+/* IPL priority levels *****************************************************/
+/* These priorities will be used by the core to properly disable/mask
+ * interrupts.
+ */
+
+#define CHIP_MIN_PRIORITY    1 /* Minimum priority. */
+#define CHIP_MAX_PRIORITY    7 /* Maximum priority. */
+
 /****************************************************************************
  * Public Types
  ****************************************************************************/
diff --git a/arch/mips/include/pic32mz/cp0.h b/arch/mips/include/pic32mz/cp0.h
index 90d0ade..160ac83 100644
--- a/arch/mips/include/pic32mz/cp0.h
+++ b/arch/mips/include/pic32mz/cp0.h
@@ -211,7 +211,7 @@
  *      CP0_STATUS_IMPL Bits 16-17: Implementation dependent
  *      CP0_STATUS_PX   Bit 23: Enables 64-bit operations (Not MIPS32)
  *      CP0_STATUS_FR   Bit 26: Controls the floating point register mode (Not MIPS32)
- *      CP0_STATUS_MX   Bit 24: Enables MDMX� (Not MIPS32)
+ *      CP0_STATUS_MX   Bit 24: Enables MDMX (Not MIPS32)
  *      CP0_STATUS_CU1  Bit 29: Controls access to coprocessor 1
  *      CP0_STATUS_CU2  Bit 30: Controls access to coprocessor 2
  *      CP0_STATUS_CU3  Bit 31: Controls access to coprocessor 3
@@ -229,18 +229,6 @@
 #undef CP0_STATUS_CU2
 #undef CP0_STATUS_CU3
 
-/*   2. The following field is of a different width.  Apparently, it
- *      excludes the software interrupt bits.
- *
- *      CP0_STATUS_IM   Bits 8-15: Interrupt Mask
- *      Vs.
- *      CP0_STATUS_IPL  Bits 10-16+18: Interrupt priority level
- *                      Bits 8-9 reserved
- */
-
-#define CP0_STATUS_IPL_SHIFT        (10)   /*  Bits 10-16+18: Interrupt priority level */
-#define CP0_STATUS_IPL_MASK         (0x17f << CP0_STATUS_IPL_SHIFT)
-
 /*   3. Supervisor mode not supported
  *       CP0_STATUS_KSU Bits 3-4: Operating mode (with supervisor mode)
  */
diff --git a/arch/mips/include/syscall.h b/arch/mips/include/syscall.h
index b23d3b5..58b458b 100644
--- a/arch/mips/include/syscall.h
+++ b/arch/mips/include/syscall.h
@@ -33,7 +33,7 @@
  *
  ****************************************************************************/
 
-/* This file should never be included directed but, rather, only indirectly
+/* This file should never be included directly but, rather, only indirectly
  * through include/syscall.h or include/sys/sycall.h
  */
 
@@ -44,10 +44,10 @@
  * Included Files
  ****************************************************************************/
 
-/* Include ARM architecture-specific syscall macros */
+/* Include MIPS architecture-specific syscall macros */
 
 #ifdef CONFIG_ARCH_MIPS32
-# include <arch/mips32/syscall.h>
+#  include <arch/mips32/syscall.h>
 #endif
 
 /****************************************************************************
diff --git a/arch/mips/src/common/up_idle.c b/arch/mips/src/common/up_idle.c
index ba872ce..977661d 100644
--- a/arch/mips/src/common/up_idle.c
+++ b/arch/mips/src/common/up_idle.c
@@ -69,23 +69,9 @@ void up_idle(void)
 
   nxsched_process_timer();
 #else
-  irqstate_t flags;
-
   /* This would be an appropriate place to put some MCU-specific logic to
    * sleep in a reduced power mode until an interrupt occurs to save power
    */
 
-  /* This is a kludge that I still don't understand.  It appears that we are
-   * somehow left idling with interrupts non-functional. The following should
-   * be no-op, it just disables then re-enables interrupts.  But it fixes the
-   * problem and will stay here until I understand the problem/fix better.
-   *
-   * And no, the contents of the CP0 status register are not incorrect.  But
-   * for some reason the status register needs to be re-written again on this
-   * thread for it to take effect.  This might be a PIC32-only issue?
-   */
-
-  flags = up_irq_save();
-  up_irq_restore(flags);
 #endif
 }
diff --git a/arch/mips/src/mips32/up_initialstate.c b/arch/mips/src/mips32/up_initialstate.c
index 42fc610..516a68a 100644
--- a/arch/mips/src/mips32/up_initialstate.c
+++ b/arch/mips/src/mips32/up_initialstate.c
@@ -125,11 +125,12 @@ void up_initial_state(struct tcb_s *tcb)
 
   regval  = cp0_getstatus();
 #ifdef CONFIG_SUPPRESS_INTERRUPTS
-  regval &= ~(CP0_STATUS_IM_ALL | CP0_STATUS_BEV | CP0_STATUS_UM);
-  regval |=  (CP0_STATUS_IE | CP0_STATUS_EXL | CP0_STATUS_IM_SWINTS);
+  regval &= ~(CP0_STATUS_INT_MASK | CP0_STATUS_BEV | CP0_STATUS_UM);
+  regval |=  (CP0_STATUS_IE | CP0_STATUS_EXL | CP0_STATUS_INT_SW0);
 #else
   regval &= ~(CP0_STATUS_BEV | CP0_STATUS_UM);
-  regval |=  (CP0_STATUS_IE | CP0_STATUS_EXL | CP0_STATUS_IM_ALL);
+  regval &= ~CP0_STATUS_INT_MASK;
+  regval |=  (CP0_STATUS_IE | CP0_STATUS_EXL);
 #endif
   xcp->regs[REG_STATUS] = regval;
 }
diff --git a/arch/mips/src/mips32/up_irq.c b/arch/mips/src/mips32/up_irq.c
index 2f3f3bb..010909b 100644
--- a/arch/mips/src/mips32/up_irq.c
+++ b/arch/mips/src/mips32/up_irq.c
@@ -68,10 +68,10 @@ irqstate_t up_irq_save(void)
 
   status  = cp0_getstatus();       /* Get CP0 status */
   ret     = status;                /* Save the status */
-  status &= ~CP0_STATUS_IM_MASK;   /* Clear all interrupt mask bits */
-  status |= CP0_STATUS_IM_SWINTS;  /* Keep S/W interrupts enabled */
-  cp0_putstatus(status);           /* Disable interrupts */
-  return ret;                      /* Return status before interrupts disabled */
+  status &= ~CP0_STATUS_INT_MASK;  /* Clear all interrupt mask bits */
+  status |= CP0_STATUS_INT_SW0;    /* Enable only the SW0 interrupt */
+  cp0_putstatus(status);           /* Disable the rest of interrupts */
+  return ret;                      /* Return saved status */
 }
 
 /****************************************************************************
@@ -93,12 +93,11 @@ void up_irq_restore(irqstate_t irqstate)
 {
   register irqstate_t status;
 
-  status    = cp0_getstatus();      /* Get CP0 status */
-  status   &= ~CP0_STATUS_IM_MASK;  /* Clear all interrupt mask bits */
-  irqstate &= CP0_STATUS_IM_MASK;   /* Retain interrupt mask bits only */
-  status   |= irqstate;             /* Set new interrupt mask bits */
-  status   |= CP0_STATUS_IM_SWINTS; /* Make sure that S/W interrupts enabled */
-  cp0_putstatus(status);            /* Restore interrupt state */
+  status    = cp0_getstatus();       /* Get CP0 status */
+  status   &= ~CP0_STATUS_INT_MASK;  /* Clear all interrupt mask bits */
+  irqstate &= CP0_STATUS_INT_MASK;   /* Retain interrupt mask bits only */
+  status   |= irqstate;              /* Set new interrupt mask bits */
+  cp0_putstatus(status);             /* Restore interrupt state */
 }
 
 /****************************************************************************
@@ -125,13 +124,13 @@ void up_irq_enable(void)
    * 1. Clear the BEV bit (This bit should already be clear)
    * 2. Clear the UM bit so that the task executes in kernel mode
    *   (This bit should already be clear)
-   * 3. Make sure the IE is set
-   * 4. Make sure the S/W interrupts are enabled
-   * 5. Set the interrupt mask bits
+   * 3. Clear all the Interrupt mask bits.
+   * 4. Make sure the IE is set
    */
 
   status  = cp0_getstatus();
   status &= ~(CP0_STATUS_BEV | CP0_STATUS_UM);
-  status |=  (CP0_STATUS_IE | CP0_STATUS_IM_SWINTS | CP0_STATUS_IM_ALL);
+  status &= ~CP0_STATUS_INT_MASK;
+  status |=  CP0_STATUS_IE;
   cp0_putstatus(status);
 }
diff --git a/arch/mips/src/mips32/up_schedulesigaction.c b/arch/mips/src/mips32/up_schedulesigaction.c
index ad31e5e..265caff 100644
--- a/arch/mips/src/mips32/up_schedulesigaction.c
+++ b/arch/mips/src/mips32/up_schedulesigaction.c
@@ -62,7 +62,7 @@
  *   This function is called by the OS when one or more
  *   signal handling actions have been queued for execution.
  *   The architecture specific code must configure things so
- *   that the 'igdeliver' callback is executed on the thread
+ *   that the 'sigdeliver' callback is executed on the thread
  *   specified by 'tcb' as soon as possible.
  *
  *   This function may be called from interrupt handling logic.
@@ -152,8 +152,8 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
 
               CURRENT_REGS[REG_EPC]      = (uint32_t)up_sigdeliver;
               status                     = CURRENT_REGS[REG_STATUS];
-              status                    &= ~CP0_STATUS_IM_MASK;
-              status                    |= CP0_STATUS_IM_SWINTS;
+              status                    &= ~CP0_STATUS_INT_MASK;
+              status                    |= CP0_STATUS_INT_SW0;
               CURRENT_REGS[REG_STATUS]   = status;
 
               /* And make sure that the saved context in the TCB
@@ -191,8 +191,8 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
 
           tcb->xcp.regs[REG_EPC]     = (uint32_t)up_sigdeliver;
           status                     = tcb->xcp.regs[REG_STATUS];
-          status                    &= ~CP0_STATUS_IM_MASK;
-          status                    |= CP0_STATUS_IM_SWINTS;
+          status                    &= ~CP0_STATUS_INT_MASK;
+          status                    |= CP0_STATUS_INT_SW0;
           tcb->xcp.regs[REG_STATUS]  = status;
 
           sinfo("PC/STATUS Saved: %08x/%08x New: %08x/%08x\n",
diff --git a/arch/mips/src/pic32mx/pic32mx-irq.c b/arch/mips/src/pic32mx/pic32mx-irq.c
index 064ed4e..434369b 100644
--- a/arch/mips/src/pic32mx/pic32mx-irq.c
+++ b/arch/mips/src/pic32mx/pic32mx-irq.c
@@ -172,11 +172,11 @@ void up_irqinitialize(void)
 #ifndef CONFIG_SUPPRESS_INTERRUPTS
   /* Then enable all interrupt levels */
 
-  up_irq_restore(CP0_STATUS_IM_ALL);
+  up_irq_restore(CP0_STATUS_INT_ENALL);
 #else
   /* Enable only software interrupts */
 
-  up_irq_restore(CP0_STATUS_IM_SWINTS);
+  up_irq_restore(CP0_STATUS_INT_SW0);
 #endif
 }
 
diff --git a/arch/mips/src/pic32mz/pic32mz-irq.c b/arch/mips/src/pic32mz/pic32mz-irq.c
index 6d9e055..124029a 100644
--- a/arch/mips/src/pic32mz/pic32mz-irq.c
+++ b/arch/mips/src/pic32mz/pic32mz-irq.c
@@ -200,6 +200,10 @@ void up_irqinitialize(void)
       pic32mz_prioritize_irq(irq, (INT_IPC_MID_PRIORITY << 2));
     }
 
+  /* Set the Software Interrupt0 to a special priority */
+
+  pic32mz_prioritize_irq(1, 7 << 2);
+
   /* Set the BEV bit in the STATUS register */
 
   regval  = cp0_getstatus();
@@ -261,11 +265,11 @@ void up_irqinitialize(void)
 #ifndef CONFIG_SUPPRESS_INTERRUPTS
   /* Then enable all interrupt levels */
 
-  up_irq_restore(CP0_STATUS_IM_ALL);
+  up_irq_restore(CP0_STATUS_INT_ENALL);
 #else
   /* Enable only software interrupts */
 
-  up_irq_restore(CP0_STATUS_IM_SWINTS);
+  up_irq_restore(CP0_STATUS_INT_SW0);
 #endif
 }