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

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

commit a876f00e2afd2d0ee755895f466ebaf7cae1c178
Author: Filipe Cavalcanti <[email protected]>
AuthorDate: Thu Sep 12 11:11:43 2024 -0300

    risc-v/espressif: support marking interrupt as running from IRAM
---
 arch/risc-v/src/common/espressif/Kconfig           |  13 ++
 arch/risc-v/src/common/espressif/esp_irq.c         | 179 ++++++++++++++++++++-
 arch/risc-v/src/common/espressif/esp_irq.h         |  86 +++++++++-
 .../esp32c3/common/scripts/esp32c3_sections.ld     |   4 +
 .../esp32c6/common/scripts/esp32c6_sections.ld     |   5 +-
 .../esp32h2/common/scripts/esp32h2_sections.ld     |   4 +
 6 files changed, 284 insertions(+), 7 deletions(-)

diff --git a/arch/risc-v/src/common/espressif/Kconfig 
b/arch/risc-v/src/common/espressif/Kconfig
index c99ea1d7e4..de91632e4a 100644
--- a/arch/risc-v/src/common/espressif/Kconfig
+++ b/arch/risc-v/src/common/espressif/Kconfig
@@ -1200,6 +1200,19 @@ config ESPRESSIF_SPI_TEST_MODE
 
 endmenu # SPI configuration
 
+menu "Interrupt Configuration"
+
+config ESPRESSIF_IRAM_ISR_DEBUG
+       bool "Enable debugging of the IRAM-enabled interrupts"
+       default n
+       ---help---
+               This option enables keeping track of the IRAM-enabled 
interrupts by
+               registering its execution when non-IRAM interrupts are 
disabled. It
+               keeps track of the IRQ executed and register how many times 
since
+               boot it was executed. Generally used for testing.
+
+endmenu
+
 menu "SPI Flash Configuration"
 
 choice ESPRESSIF_FLASH_MODE
diff --git a/arch/risc-v/src/common/espressif/esp_irq.c 
b/arch/risc-v/src/common/espressif/esp_irq.c
index e9beb217cd..83e572e062 100644
--- a/arch/risc-v/src/common/espressif/esp_irq.c
+++ b/arch/risc-v/src/common/espressif/esp_irq.c
@@ -78,6 +78,11 @@
 
 #define NO_CPUINT                     ETS_INVALID_INUM
 
+/* Masks for interrupt type used on esp_setup_irq */
+
+#define ESP_CPUINT_IRAM_MASK       (1 << 1)
+#define ESP_CPUINT_TRIGGER_MASK    (1 << 0)
+
 /****************************************************************************
  * Private Types
  ****************************************************************************/
@@ -130,6 +135,14 @@ static uint32_t 
non_iram_int_mask[CONFIG_ESPRESSIF_NUM_CPUS];
 static uint32_t non_iram_int_disabled[CONFIG_ESPRESSIF_NUM_CPUS];
 static bool non_iram_int_disabled_flag[CONFIG_ESPRESSIF_NUM_CPUS];
 
+#ifdef CONFIG_ESPRESSIF_IRAM_ISR_DEBUG
+/* The g_iram_count keeps track of how many times such an IRQ ran when the
+ * non-IRAM interrupts were disabled.
+ */
+
+static uint64_t g_iram_count[NR_IRQS];
+#endif
+
 /****************************************************************************
  * Private Functions
  ****************************************************************************/
@@ -273,6 +286,33 @@ static void esp_cpuint_initialize(void)
   memset(g_cpuint_map, 0, sizeof(g_cpuint_map));
 }
 
+#ifdef CONFIG_ESPRESSIF_IRAM_ISR_DEBUG
+
+/****************************************************************************
+ * Name:  esp_iram_interrupt_record
+ *
+ * Description:
+ *   This function keeps track of the IRQs that ran when non-IRAM interrupts
+ *   are disabled and enables debugging of the IRAM-enabled interrupts.
+ *
+ * Input Parameters:
+ *   irq - The IRQ associated with a CPU interrupt
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+IRAM_ATTR void esp_irq_iram_interrupt_record(int irq)
+{
+  irqstate_t flags = enter_critical_section();
+
+  g_iram_count[irq]++;
+
+  leave_critical_section(flags);
+}
+#endif
+
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
@@ -464,7 +504,7 @@ void esp_route_intr(int source, int cpuint, irq_priority_t 
priority,
  *
  ****************************************************************************/
 
-int esp_setup_irq(int source, irq_priority_t priority, irq_trigger_t type)
+int esp_setup_irq(int source, irq_priority_t priority, int type)
 {
   irqstate_t irqstate;
   int irq;
@@ -492,7 +532,17 @@ int esp_setup_irq(int source, irq_priority_t priority, 
irq_trigger_t type)
       PANIC();
     }
 
-  esp_route_intr(source, cpuint, priority, type);
+  esp_route_intr(source, cpuint, priority, (type & ESP_CPUINT_TRIGGER_MASK));
+
+  if ((type & ESP_CPUINT_IRAM_MASK) == ESP_IRQ_IRAM)
+    {
+      esp_irq_set_iram_isr(irq);
+      irqinfo("source %d marked IRAM (irq=%d)\n", source, irq);
+    }
+  else
+    {
+      esp_irq_unset_iram_isr(irq);
+    }
 
   leave_critical_section(irqstate);
 
@@ -557,6 +607,7 @@ IRAM_ATTR void *riscv_dispatch_irq(uintreg_t mcause, 
uintreg_t *regs)
   int irq;
   bool is_irq = (RISCV_IRQ_BIT & mcause) != 0;
   bool is_edge = false;
+  uint32_t cpu = esp_cpu_get_core_id();
 
   if (is_irq)
     {
@@ -568,7 +619,18 @@ IRAM_ATTR void *riscv_dispatch_irq(uintreg_t mcause, 
uintreg_t *regs)
 
       irq = g_cpuint_map[cpuint].irq;
 
-      is_edge = esprv_intc_int_get_type(cpuint) == INTR_TYPE_EDGE;
+#ifdef CONFIG_ESPRESSIF_IRAM_ISR_DEBUG
+      /* Check if non-IRAM interrupts are disabled */
+
+      if (esp_irq_noniram_status(cpu) == 0)
+        {
+          /* Sum-up the IRAM-enabled counter associated with the IRQ */
+
+          esp_irq_iram_interrupt_record(irq);
+        }
+#endif
+
+      is_edge = esprv_intc_int_get_type(cpuint) == INTR_TYPE_LEVEL;
       if (is_edge)
         {
           /* Clear edge interrupts. */
@@ -626,7 +688,7 @@ irqstate_t up_irq_enable(void)
  *
  ****************************************************************************/
 
-void IRAM_ATTR esp_intr_noniram_disable(void)
+void esp_intr_noniram_disable(void)
 {
   uint32_t oldint;
   irqstate_t irqstate;
@@ -666,7 +728,7 @@ void IRAM_ATTR esp_intr_noniram_disable(void)
  *
  ****************************************************************************/
 
-void IRAM_ATTR esp_intr_noniram_enable(void)
+void esp_intr_noniram_enable(void)
 {
   irqstate_t irqstate;
   uint32_t cpu;
@@ -686,6 +748,27 @@ void IRAM_ATTR esp_intr_noniram_enable(void)
   leave_critical_section(irqstate);
 }
 
+/****************************************************************************
+ * Name:  esp_irq_noniram_status
+ *
+ * Description:
+ *   Get the current status of non-IRAM interrupts on a specific CPU core
+ *
+ * Input Parameters:
+ *   cpu - The CPU to check the non-IRAM interrupts state
+ *
+ * Returned Value:
+ *   true if non-IRAM interrupts are enabled, false otherwise.
+ *
+ ****************************************************************************/
+
+bool esp_irq_noniram_status(int cpu)
+{
+  DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS);
+
+  return !non_iram_int_disabled_flag[cpu];
+}
+
 /****************************************************************************
  * Name:  esp_get_irq
  *
@@ -731,3 +814,89 @@ void esp_set_irq(int irq, int cpuint)
   CPUINT_ASSIGN(g_cpuint_map[cpuint], irq);
   g_irq_map[irq] = cpuint;
 }
+
+/****************************************************************************
+ * Name:  esp_irq_set_iram_isr
+ *
+ * Description:
+ *   Set the ISR associated to an IRQ as a IRAM-enabled ISR.
+ *
+ * Input Parameters:
+ *   irq - The associated IRQ to set
+ *
+ * Returned Value:
+ *   OK on success; A negated errno value on failure.
+ *
+ ****************************************************************************/
+
+int esp_irq_set_iram_isr(int irq)
+{
+  uint32_t cpu = esp_cpu_get_core_id();
+  int cpuint = g_irq_map[irq];
+
+  if (cpuint == IRQ_UNMAPPED)
+    {
+      return -EINVAL;
+    }
+
+  non_iram_int_mask[cpu] &= ~(1 << cpuint);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name:  esp_irq_unset_iram_isr
+ *
+ * Description:
+ *   Set the ISR associated to an IRQ as a non-IRAM ISR.
+ *
+ * Input Parameters:
+ *   irq - The associated IRQ to set
+ *
+ * Returned Value:
+ *   OK on success; A negated errno value on failure.
+ *
+ ****************************************************************************/
+
+int esp_irq_unset_iram_isr(int irq)
+{
+  uint32_t cpu = esp_cpu_get_core_id();
+  int cpuint = g_irq_map[irq];
+
+  if (cpuint == IRQ_UNMAPPED)
+    {
+      return -EINVAL;
+    }
+
+  non_iram_int_mask[cpu] |= (1 << cpuint);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name:  esp_get_iram_interrupt_records
+ *
+ * Description:
+ *   This function copies the vector that keeps track of the IRQs that ran
+ *   when non-IRAM interrupts were disabled.
+ *
+ * Input Parameters:
+ *
+ *   irq_count - A previously allocated pointer to store the counter of the
+ *               interrupts that ran when non-IRAM interrupts were disabled.
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_ESPRESSIF_IRAM_ISR_DEBUG
+void esp_get_iram_interrupt_records(uint64_t *irq_count)
+{
+  irqstate_t flags = enter_critical_section();
+
+  memcpy(irq_count, &g_iram_count, sizeof(uint64_t) * NR_IRQS);
+
+  leave_critical_section(flags);
+}
+#endif
diff --git a/arch/risc-v/src/common/espressif/esp_irq.h 
b/arch/risc-v/src/common/espressif/esp_irq.h
index 648665430e..8e41986870 100644
--- a/arch/risc-v/src/common/espressif/esp_irq.h
+++ b/arch/risc-v/src/common/espressif/esp_irq.h
@@ -45,6 +45,15 @@ extern "C"
 #define EXTERN extern
 #endif
 
+/* CPU interrupt flags.
+ * esp_setup_irq() will check bit 1 for IRAM requirement and
+ * bit 0 for trigger type.
+ *
+ * OR'ed values of irq_trigger_e and irq_iram_e define interrupt type.
+ *      | IRAM | TRIGGER |
+ * Bits |   1  |    0    |
+ */
+
 /* CPU interrupt trigger types */
 
 typedef enum irq_trigger_e
@@ -53,6 +62,14 @@ typedef enum irq_trigger_e
   ESP_IRQ_TRIGGER_EDGE     = 1, /* Edge-triggered interrupts */
 } irq_trigger_t;
 
+/* CPU interrupt IRAM enabled */
+
+typedef enum irq_iram_e
+{
+  ESP_IRQ_NON_IRAM    = (0 << 1), /* Non-IRAM interrupt */
+  ESP_IRQ_IRAM        = (1 << 1), /* IRAM interrupt */
+} irq_iram_t;
+
 /* CPU interrupt priority levels */
 
 typedef enum irq_priority_e
@@ -119,7 +136,7 @@ void esp_route_intr(int source, int cpuint, irq_priority_t 
priority,
  *
  ****************************************************************************/
 
-int esp_setup_irq(int source, irq_priority_t priority, irq_trigger_t type);
+int esp_setup_irq(int source, irq_priority_t priority, int type);
 
 /****************************************************************************
  * Name: esp_teardown_irq
@@ -213,6 +230,73 @@ int esp_get_irq(int cpuint);
 
 void esp_set_irq(int irq, int cpuint);
 
+/****************************************************************************
+ * Name:  esp_irq_set_iram_isr
+ *
+ * Description:
+ *   Set the ISR associated to an IRQ as a IRAM-enabled ISR.
+ *
+ * Input Parameters:
+ *   irq - The associated IRQ to set
+ *
+ * Returned Value:
+ *   OK on success; A negated errno value on failure.
+ *
+ ****************************************************************************/
+
+int esp_irq_set_iram_isr(int irq);
+
+/****************************************************************************
+ * Name:  esp32s3_irq_unset_iram_isr
+ *
+ * Description:
+ *   Set the ISR associated to an IRQ as a non-IRAM ISR.
+ *
+ * Input Parameters:
+ *   irq - The associated IRQ to set
+ *
+ * Returned Value:
+ *   OK on success; A negated errno value on failure.
+ *
+ ****************************************************************************/
+
+int esp_irq_unset_iram_isr(int irq);
+
+/****************************************************************************
+ * Name:  esp_irq_noniram_status
+ *
+ * Description:
+ *   Get the current status of non-IRAM interrupts on a specific CPU core
+ *
+ * Input Parameters:
+ *   cpu - The CPU to check the non-IRAM interrupts state
+ *
+ * Returned Value:
+ *   true if non-IRAM interrupts are enabled, false otherwise.
+ *
+ ****************************************************************************/
+
+bool esp_irq_noniram_status(int cpu);
+
+/****************************************************************************
+ * Name:  esp_get_iram_interrupt_records
+ *
+ * Description:
+ *   This function copies the vector that keeps track of the IRQs that ran
+ *   when non-IRAM interrupts were disabled.
+ *
+ * Input Parameters:
+ *
+ *   irq_count - A previously allocated pointer to store the counter of the
+ *               interrupts that ran when non-IRAM interrupts were disabled.
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void esp_get_iram_interrupt_records(uint64_t *irq_count);
+
 #undef EXTERN
 #if defined(__cplusplus)
 }
diff --git a/boards/risc-v/esp32c3/common/scripts/esp32c3_sections.ld 
b/boards/risc-v/esp32c3/common/scripts/esp32c3_sections.ld
index cc2661327c..e6f1e47e8b 100644
--- a/boards/risc-v/esp32c3/common/scripts/esp32c3_sections.ld
+++ b/boards/risc-v/esp32c3/common/scripts/esp32c3_sections.ld
@@ -73,6 +73,8 @@ SECTIONS
 
     *libsched.a:irq_dispatch.*(.text .text.* .literal .literal.*)
 
+    *libarch.a:*(.text.esprv_intc_int_get_type 
.literal.esprv_intc_int_get_type)
+    *libarch.a:*riscv_doirq.*(.text .text.* .literal .literal.*)
     *libarch.a:*brownout.*(.text .text.* .literal .literal.*)
     *libarch.a:*cpu.*(.text .text.* .literal .literal.*)
     *libarch.a:*gpio_hal.*(.text .text.* .literal .literal.*)
@@ -188,6 +190,8 @@ SECTIONS
 
     *libsched.a:irq_dispatch.*(.rodata .rodata.*)
 
+    *libarch.a:*(.rodata.esprv_intc_int_get_type)
+    *libarch.a:*riscv_doirq.*(.rodata .rodata.*)
     *libarch.a:*brownout.*(.rodata .rodata.*)
     *libarch.a:*cpu.*(.rodata .rodata.*)
     *libarch.a:*gpio_hal.*(.rodata .rodata.*)
diff --git a/boards/risc-v/esp32c6/common/scripts/esp32c6_sections.ld 
b/boards/risc-v/esp32c6/common/scripts/esp32c6_sections.ld
index 8af813d980..5700182f2f 100644
--- a/boards/risc-v/esp32c6/common/scripts/esp32c6_sections.ld
+++ b/boards/risc-v/esp32c6/common/scripts/esp32c6_sections.ld
@@ -73,6 +73,8 @@ SECTIONS
 
     *libsched.a:irq_dispatch.*(.text .text.* .literal .literal.*)
 
+    *libarch.a:*(.text.esprv_intc_int_get_type 
.literal.esprv_intc_int_get_type)
+    *libarch.a:*riscv_doirq.*(.text .text.* .literal .literal.*)
     *libarch.a:*brownout.*(.text .text.* .literal .literal.*)
     *libarch.a:*cpu.*(.text .text.* .literal .literal.*)
     *libarch.a:*gpio_hal.*(.text .text.* .literal .literal.*)
@@ -212,6 +214,8 @@ SECTIONS
 
     *libsched.a:irq_dispatch.*(.rodata .rodata.*)
 
+    *libarch.a:*(.rodata.esprv_intc_int_get_type)
+    *libarch.a:*riscv_doirq.*(.rodata .rodata.*)
     *libarch.a:*brownout.*(.rodata .rodata.*)
     *libarch.a:*cpu.*(.rodata .rodata.*)
     *libarch.a:*gpio_hal.*(.rodata .rodata.*)
@@ -488,4 +492,3 @@ SECTIONS
           "RTC reserved segment data does not fit.")
 
 }
-
diff --git a/boards/risc-v/esp32h2/common/scripts/esp32h2_sections.ld 
b/boards/risc-v/esp32h2/common/scripts/esp32h2_sections.ld
index 9461b0dd98..8d8a7bc4cb 100644
--- a/boards/risc-v/esp32h2/common/scripts/esp32h2_sections.ld
+++ b/boards/risc-v/esp32h2/common/scripts/esp32h2_sections.ld
@@ -73,6 +73,8 @@ SECTIONS
 
     *libsched.a:irq_dispatch.*(.text .text.* .literal .literal.*)
 
+    *libarch.a:*(.text.esprv_intc_int_get_type 
.literal.esprv_intc_int_get_type)
+    *libarch.a:*riscv_doirq.*(.text .text.* .literal .literal.*)
     *libarch.a:*brownout.*(.text .text.* .literal .literal.*)
     *libarch.a:*cpu.*(.text .text.* .literal .literal.*)
     *libarch.a:*gpio_hal.*(.text .text.* .literal .literal.*)
@@ -209,6 +211,8 @@ SECTIONS
 
     *libsched.a:irq_dispatch.*(.rodata .rodata.*)
 
+    *libarch.a:*(.rodata.esprv_intc_int_get_type)
+    *libarch.a:*riscv_doirq.*(.rodata .rodata.*)
     *libarch.a:*brownout.*(.rodata .rodata.*)
     *libarch.a:*cpu.*(.rodata .rodata.*)
     *libarch.a:*gpio_hal.*(.rodata .rodata.*)

Reply via email to