mirror of
https://github.com/apache/nuttx.git
synced 2026-08-30 05:40:37 +00:00
risc-v/espressif: support marking interrupt as running from IRAM
This commit is contained in:
parent
7acb298f26
commit
a876f00e2a
6 changed files with 284 additions and 7 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.*)
|
||||
|
|
|
|||
|
|
@ -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.")
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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.*)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue