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

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

commit 73e3fd8f3ce306393f81d67bb05963d71a29d7cd
Author: Afonso Oliveira <[email protected]>
AuthorDate: Thu Oct 8 22:05:47 2026 +0100

    riscv/erbium: Stop dispatching ET-Minion exceptions as interrupts.
    
    ET-Minion raises exception codes above 15: 25 (instruction bus error),
    26 (instruction ECC error), 27 and 28 (load and store split-page fault)
    and 30 (M-code emulation). Code 30 is raised by FDIV.S, FSQRT.S,
    FCVT.L.S, FCVT.LU.S, FCVT.S.L, FCVT.S.LU, FENCE.I, SFENCE.VMA and some
    ET packed instructions, which have no hardware implementation.
    
    riscv_dispatch_irq() uses the exception code as the IRQ number, and with
    the default RISCV_MAX_EXCEPTION of 15 these codes alias interrupt IRQ
    numbers. Code 30 ran the UART0 interrupt handler, which returned to the
    faulting instruction, so the task trapped again forever. A cast from
    float to int64_t, or a call to lroundf(), hung the system with no
    report.
    
    Set RISCV_MAX_EXCEPTION to 31, name the ET-Minion codes through
    RISCV_CUSTOM_EXCEPTION_REASONS and attach codes 16 to 31 to
    riscv_exception(), so that each is reported once as a fatal exception
    with its name, EPC and MTVAL. Interrupt IRQ numbers move up by 16, for
    example UART0 from 30 to 46.
    
    Also correct comments that said these instructions run in microcode.
    
    Assisted-by: Claude:claude-opus-5-5
    Signed-off-by: Afonso Oliveira <[email protected]>
---
 arch/risc-v/include/erbium/irq.h                  | 36 +++++++++++++++++++++++
 arch/risc-v/src/erbium/erbium_irq.c               | 33 ++++++++++++++++++++-
 arch/risc-v/src/erbium/erbium_irq_dispatch.c      | 18 ++++++++++--
 arch/risc-v/src/erbium/erbium_start.c             |  5 ++--
 boards/risc-v/erbium/minion/cmake/Toolchain.cmake |  4 +--
 boards/risc-v/erbium/minion/scripts/Make.defs     |  4 +--
 6 files changed, 91 insertions(+), 9 deletions(-)

diff --git a/arch/risc-v/include/erbium/irq.h b/arch/risc-v/include/erbium/irq.h
index 50c13cc3b46..6a18d0f59af 100644
--- a/arch/risc-v/include/erbium/irq.h
+++ b/arch/risc-v/include/erbium/irq.h
@@ -27,6 +27,42 @@
  * Pre-processor Definitions
  ****************************************************************************/
 
+/* ET-Minion reports a 5-bit exception code. Besides the standard codes it
+ * raises 25 (instruction bus error), 26 (instruction ECC error), 27 and 28
+ * (load and store split-page fault) and 30 (M-code emulation: the
+ * instruction has no hardware implementation and traps to machine mode).
+ * Number all 32 codes as exceptions so that none of them is dispatched as
+ * an interrupt. Interrupt IRQ numbers therefore start at 32.
+ */
+
+#define RISCV_MAX_EXCEPTION   (31)
+
+#define ERBIUM_IRQ_IBUSERR    (25)  /* Instruction bus error */
+#define ERBIUM_IRQ_IECCERR    (26)  /* Instruction ECC error */
+#define ERBIUM_IRQ_LSPLITPF   (27)  /* Load split-page fault */
+#define ERBIUM_IRQ_SSPLITPF   (28)  /* Store split-page fault */
+#define ERBIUM_IRQ_MCODE      (30)  /* M-code emulation */
+
+/* Reason strings for the codes after the common table. The common table
+ * names codes 16-19 itself when Machine ISA 1.13 support is enabled.
+ */
+
+#ifdef CONFIG_ARCH_RV_MACHINE_ISA_1_13
+#  define ERBIUM_FIRST_CUSTOM_EXCEPTION (20)
+#  define ERBIUM_EXCEPTION_REASONS_16_19
+#else
+#  define ERBIUM_FIRST_CUSTOM_EXCEPTION (16)
+#  define ERBIUM_EXCEPTION_REASONS_16_19 \
+     "Reserved", "Reserved", "Reserved", "Reserved",
+#endif
+
+#define RISCV_CUSTOM_EXCEPTION_REASONS                         \
+  ERBIUM_EXCEPTION_REASONS_16_19                               \
+  "Reserved", "Reserved", "Reserved", "Reserved", "Reserved",  \
+  "Instruction bus error", "Instruction ECC error",            \
+  "Load split-page fault", "Store split-page fault",           \
+  "Reserved", "M-code emulation", "Reserved",
+
 #define ERBIUM_IRQ_UART0      (RISCV_IRQ_MEXT + 3)
 #define ERBIUM_IRQ_EXT_MAX    (RISCV_IRQ_MEXT + 6)
 
diff --git a/arch/risc-v/src/erbium/erbium_irq.c 
b/arch/risc-v/src/erbium/erbium_irq.c
index da82ccba70a..097738a6a20 100644
--- a/arch/risc-v/src/erbium/erbium_irq.c
+++ b/arch/risc-v/src/erbium/erbium_irq.c
@@ -25,12 +25,32 @@
  ****************************************************************************/
 
 #include <nuttx/config.h>
+#include <assert.h>
 #include <stdint.h>
+#include <sys/param.h>
 #include <nuttx/irq.h>
 
 #include "chip.h"
 #include "riscv_internal.h"
 
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* riscv_exception() names an exception with g_reasons_str[code], which has
+ * RISCV_MAX_EXCEPTION + 1 entries. The chip's part of that table must name
+ * every code after the common part; this copy only checks its length.
+ */
+
+static const char * const g_custom_reasons[] unused_data =
+{
+  RISCV_CUSTOM_EXCEPTION_REASONS
+};
+
+static_assert(nitems(g_custom_reasons) ==
+              RISCV_MAX_EXCEPTION + 1 - ERBIUM_FIRST_CUSTOM_EXCEPTION,
+              "RISCV_CUSTOM_EXCEPTION_REASONS must end at code 31");
+
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
@@ -40,7 +60,8 @@
  *
  * Description:
  *   Initialize hart 0 interrupt state and PLIC priorities, attach the
- *   common exception handlers, and enable interrupts unless suppressed.
+ *   exception handlers, including those for the ET-specific exception
+ *   codes, and enable interrupts unless suppressed.
  *
  * Input Parameters:
  *   None.
@@ -70,6 +91,16 @@ void up_irqinitialize(void)
   putreg32(0, ERBIUM_PLIC_THRESHOLD);
   riscv_exception_attach();
 
+  /* riscv_exception_attach() covers codes 0-15 only. Report the other
+   * codes, among them the ET-specific ones and M-code instructions that
+   * are not emulated, as fatal exceptions.
+   */
+
+  for (id = RISCV_IRQ_RESERVED16; id <= RISCV_MAX_EXCEPTION; id++)
+    {
+      irq_attach(id, riscv_exception, NULL);
+    }
+
 #ifndef CONFIG_SUPPRESS_INTERRUPTS
   up_irq_enable();
 #endif
diff --git a/arch/risc-v/src/erbium/erbium_irq_dispatch.c 
b/arch/risc-v/src/erbium/erbium_irq_dispatch.c
index ecc6369cddf..c37fdb161cd 100644
--- a/arch/risc-v/src/erbium/erbium_irq_dispatch.c
+++ b/arch/risc-v/src/erbium/erbium_irq_dispatch.c
@@ -31,6 +31,18 @@
 #include "hardware/erbium_plic.h"
 #include "riscv_internal.h"
 
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* An exception is dispatched with its 5-bit cause code as the IRQ number,
+ * so every code must lie below the first interrupt IRQ number.
+ */
+
+#if RISCV_IRQ_ASYNC < 32
+#  error "ET-Minion exception codes would alias interrupt IRQ numbers"
+#endif
+
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
@@ -39,8 +51,10 @@
  * Name: riscv_dispatch_irq
  *
  * Description:
- *   Dispatch hart-local traps or claim, dispatch and complete a PLIC
- *   interrupt. Complete nonzero claims even if their source is unsupported.
+ *   Dispatch an exception as IRQ <cause> (0-31) and a hart-local
+ *   interrupt as IRQ RISCV_IRQ_ASYNC + <cause>, or claim, dispatch and
+ *   complete a PLIC interrupt. Complete nonzero claims even if their
+ *   source is unsupported.
  *
  * Input Parameters:
  *   vector - Trap cause register value.
diff --git a/arch/risc-v/src/erbium/erbium_start.c 
b/arch/risc-v/src/erbium/erbium_start.c
index c5aac2e734c..dfc92f02cd0 100644
--- a/arch/risc-v/src/erbium/erbium_start.c
+++ b/arch/risc-v/src/erbium/erbium_start.c
@@ -63,8 +63,9 @@ void erbium_start(void)
     }
 
 #ifdef CONFIG_ARCH_FPU
-  /* Erbium traps FENCE.I to microcode. The ELF loader has already installed
-   * the image, so initialize the FPU without the common FENCE.I sequence.
+  /* FENCE.I raises exception 30 (M-code emulation) on ET-Minion. The ELF
+   * loader has already installed the image, so initialize the FPU without
+   * the common FENCE.I sequence.
    */
 
   SET_CSR(CSR_STATUS, MSTATUS_FS_INIT);
diff --git a/boards/risc-v/erbium/minion/cmake/Toolchain.cmake 
b/boards/risc-v/erbium/minion/cmake/Toolchain.cmake
index 1b1b845af12..1fc89398af0 100644
--- a/boards/risc-v/erbium/minion/cmake/Toolchain.cmake
+++ b/boards/risc-v/erbium/minion/cmake/Toolchain.cmake
@@ -20,8 +20,8 @@
 #
 # 
##############################################################################
 
-# Erbium executes floating-point divide and square root in microcode, which 
this
-# image does not provide. Use software helpers for those operations.
+# ET-Minion has no hardware for floating-point divide and square root; they
+# raise exception 30 (M-code emulation). Use software helpers instead.
 
 if(CONFIG_ARCH_FPU)
   add_compile_options(-mno-fdiv)
diff --git a/boards/risc-v/erbium/minion/scripts/Make.defs 
b/boards/risc-v/erbium/minion/scripts/Make.defs
index c4d0b779062..766eb9f6ccb 100644
--- a/boards/risc-v/erbium/minion/scripts/Make.defs
+++ b/boards/risc-v/erbium/minion/scripts/Make.defs
@@ -24,8 +24,8 @@ include $(TOPDIR)/.config
 include $(TOPDIR)/tools/Config.mk
 include $(TOPDIR)/arch/risc-v/src/common/Toolchain.defs
 
-# Erbium executes floating-point divide and square root in microcode, which
-# this image does not provide. Use software helpers for those operations.
+# ET-Minion has no hardware for floating-point divide and square root; they
+# raise exception 30 (M-code emulation). Use software helpers instead.
 
 ifeq ($(CONFIG_ARCH_FPU),y)
   ARCHCPUFLAGS += -mno-fdiv

Reply via email to