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.*)
