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
}