Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 27 additions & 20 deletions arch/risc-v/src/common/espressif/esp_irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,12 @@

#include <assert.h>
#include <debug.h>
#include <sched.h>
#include <errno.h>
#include <stdbool.h>
#include <stdint.h>

#include <nuttx/irq.h>
#include <nuttx/spinlock.h>
#include <nuttx/arch.h>

#include "riscv_internal.h"
Expand Down Expand Up @@ -145,6 +146,10 @@ static bool non_iram_int_disabled_flag[CONFIG_ESPRESSIF_NUM_CPUS];
static uint64_t g_iram_count[NR_IRQS];
#endif

/* Spinlock */

static spinlock_t g_irq_lock = SP_UNLOCKED;

/****************************************************************************
* Private Functions
****************************************************************************/
Expand Down Expand Up @@ -307,11 +312,11 @@ static void esp_cpuint_initialize(void)

IRAM_ATTR void esp_irq_iram_interrupt_record(int irq)
{
irqstate_t flags = enter_critical_section();
irqstate_t flags = spin_lock_irqsave(&g_irq_lock);

g_iram_count[irq]++;

leave_critical_section(flags);
spin_unlock_irqrestore(&g_irq_lock, flags);
}
#endif

Expand Down Expand Up @@ -402,12 +407,12 @@ void up_enable_irq(int irq)

DEBUGASSERT(cpuint >= 0 && cpuint < ESP_NCPUINTS);

irqstate_t irqstate = enter_critical_section();
irqstate_t flags = spin_lock_irqsave(&g_irq_lock);

CPUINT_ENABLE(g_cpuint_map[cpuint]);
esprv_intc_int_enable(BIT(cpuint));

leave_critical_section(irqstate);
spin_unlock_irqrestore(&g_irq_lock, flags);
}

/****************************************************************************
Expand All @@ -434,12 +439,12 @@ void up_disable_irq(int irq)

DEBUGASSERT(cpuint >= 0 && cpuint < ESP_NCPUINTS);

irqstate_t irqstate = enter_critical_section();
irqstate_t flags = spin_lock_irqsave(&g_irq_lock);

CPUINT_DISABLE(g_cpuint_map[cpuint]);
esprv_intc_int_disable(BIT(cpuint));

leave_critical_section(irqstate);
spin_unlock_irqrestore(&g_irq_lock, flags);
}

/****************************************************************************
Expand Down Expand Up @@ -508,15 +513,16 @@ void esp_route_intr(int source, int cpuint, irq_priority_t priority,

int esp_setup_irq(int source, irq_priority_t priority, int type)
{
irqstate_t irqstate;
irqstate_t flags;
int irq;
int cpuint;

irqinfo("source = %d\n", source);

DEBUGASSERT(source >= 0 && source < ESP_NSOURCES);

irqstate = enter_critical_section();
flags = spin_lock_irqsave(&g_irq_lock);
sched_lock();

/* Setting up an IRQ includes the following steps:
* 1. Allocate a CPU interrupt.
Expand Down Expand Up @@ -546,7 +552,8 @@ int esp_setup_irq(int source, irq_priority_t priority, int type)
esp_irq_unset_iram_isr(irq);
}

leave_critical_section(irqstate);
spin_unlock_irqrestore(&g_irq_lock, flags);
sched_unlock();

return cpuint;
}
Expand All @@ -572,7 +579,7 @@ int esp_setup_irq(int source, irq_priority_t priority, int type)

void esp_teardown_irq(int source, int cpuint)
{
irqstate_t irqstate = enter_critical_section();
irqstate_t flags = spin_lock_irqsave(&g_irq_lock);

/* Tearing down an IRQ includes the following steps:
* 1. Free the previously allocated CPU interrupt.
Expand All @@ -586,7 +593,7 @@ void esp_teardown_irq(int source, int cpuint)

esp_rom_route_intr_matrix(PRO_CPU_NUM, source, NO_CPUINT);

leave_critical_section(irqstate);
spin_unlock_irqrestore(&g_irq_lock, flags);
}

/****************************************************************************
Expand Down Expand Up @@ -693,11 +700,11 @@ irqstate_t up_irq_enable(void)
void esp_intr_noniram_disable(void)
{
uint32_t oldint;
irqstate_t irqstate;
irqstate_t flags;
uint32_t cpu;
uint32_t non_iram_ints;

irqstate = enter_critical_section();
flags = spin_lock_irqsave(&g_irq_lock);
cpu = esp_cpu_get_core_id();
non_iram_ints = non_iram_int_mask[cpu];

Expand All @@ -713,7 +720,7 @@ void esp_intr_noniram_disable(void)
/* Save disabled ints */

non_iram_int_disabled[cpu] = oldint & non_iram_ints;
leave_critical_section(irqstate);
spin_unlock_irqrestore(&g_irq_lock, flags);
}

/****************************************************************************
Expand All @@ -732,11 +739,11 @@ void esp_intr_noniram_disable(void)

void esp_intr_noniram_enable(void)
{
irqstate_t irqstate;
irqstate_t flags;
uint32_t cpu;
int non_iram_ints;

irqstate = enter_critical_section();
flags = spin_lock_irqsave(&g_irq_lock);
cpu = esp_cpu_get_core_id();
non_iram_ints = non_iram_int_disabled[cpu];

Expand All @@ -747,7 +754,7 @@ void esp_intr_noniram_enable(void)

non_iram_int_disabled_flag[cpu] = false;
esp_cpu_intr_enable(non_iram_ints);
leave_critical_section(irqstate);
spin_unlock_irqrestore(&g_irq_lock, flags);
}

/****************************************************************************
Expand Down Expand Up @@ -895,10 +902,10 @@ int esp_irq_unset_iram_isr(int irq)
#ifdef CONFIG_ESPRESSIF_IRAM_ISR_DEBUG
void esp_get_iram_interrupt_records(uint64_t *irq_count)
{
irqstate_t flags = enter_critical_section();
irqstate_t flags = spin_lock_irqsave(&g_irq_lock);

memcpy(irq_count, &g_iram_count, sizeof(uint64_t) * NR_IRQS);

leave_critical_section(flags);
spin_unlock_irqrestore(&g_irq_lock, flags);
}
#endif
116 changes: 70 additions & 46 deletions arch/risc-v/src/esp32c3-legacy/esp32c3_irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <sched.h>

#include <nuttx/irq.h>
#include <nuttx/spinlock.h>
#include <nuttx/arch.h>

#include "riscv_internal.h"
Expand Down Expand Up @@ -117,6 +118,10 @@ static uint32_t g_cpu_freeints = ESP32C3_CPUINT_PERIPHSET &
(~ESP32C3_WIFI_RESERVE_INT &
~ESP32C3_BLE_RESERVE_INT);

/* Spinlock */

static spinlock_t g_irq_lock = SP_UNLOCKED;

/****************************************************************************
* Private Functions
****************************************************************************/
Expand Down Expand Up @@ -191,6 +196,45 @@ static int esp32c3_getcpuint(void)
return cpuint;
}

/****************************************************************************
* Name: esp32c3_free_cpuint_nolock
*
* Description:
* The version of public function esp32c3_free_cpuint without spinlock.
*
****************************************************************************/

static void esp32c3_free_cpuint_nolock(uint8_t periphid)
{
uint8_t cpuint;

DEBUGASSERT(periphid < ESP32C3_NPERIPHERALS);

/* Get the CPU interrupt ID mapped to this peripheral. */

cpuint = getreg32(DR_REG_INTERRUPT_BASE + periphid * 4) & 0x1f;

irqinfo("INFO: irq[%" PRIu8 "]=%" PRIu8 "\n", periphid, cpuint);

if (cpuint != 0)
{
/* Undo the allocation process:
* 1. Unmap the peripheral from the CPU interrupt ID.
* 2. Reset the interrupt type.
* 3. Reset the interrupt priority.
* 4. Clear the CPU interrupt.
*/

DEBUGASSERT(g_cpu_intmap[cpuint] != CPUINT_UNASSIGNED);

g_cpu_intmap[cpuint] = CPUINT_UNASSIGNED;
putreg32(0, DR_REG_INTERRUPT_BASE + periphid * 4);
resetbits(1 << cpuint, INTERRUPT_CPU_INT_TYPE_REG);
putreg32(0, INTERRUPT_CPU_INT_PRI_0_REG + cpuint * 4);
resetbits(1 << cpuint, INTERRUPT_CPU_INT_ENABLE_REG);
}
}

/****************************************************************************
* Public Functions
****************************************************************************/
Expand Down Expand Up @@ -260,15 +304,15 @@ void up_irqinitialize(void)
void up_enable_irq(int irq)
{
int cpuint = g_irqmap[irq];
irqstate_t irqstate;
irqstate_t flags;

irqinfo("irq=%d | cpuint=%d \n", irq, cpuint);

DEBUGASSERT(cpuint >= 1 && cpuint <= ESP32C3_CPUINT_MAX);

irqstate = enter_critical_section();
flags = spin_lock_irqsave(&g_irq_lock);
setbits(1 << cpuint, INTERRUPT_CPU_INT_ENABLE_REG);
leave_critical_section(irqstate);
spin_unlock_irqrestore(&g_irq_lock, flags);
}

/****************************************************************************
Expand All @@ -295,13 +339,13 @@ void up_disable_irq(int irq)
}
else
{
irqstate_t irqstate;
irqstate_t flags;

g_cpu_intmap[cpuint] = CPUINT_DISABLE(g_cpu_intmap[cpuint]);

irqstate = enter_critical_section();
flags = spin_lock_irqsave(&g_irq_lock);
resetbits(1 << cpuint, INTERRUPT_CPU_INT_ENABLE_REG);
leave_critical_section(irqstate);
spin_unlock_irqrestore(&g_irq_lock, flags);
}
}

Expand All @@ -321,38 +365,13 @@ void up_disable_irq(int irq)

void esp32c3_free_cpuint(uint8_t periphid)
{
irqstate_t irqstate;
uint8_t cpuint;

DEBUGASSERT(periphid < ESP32C3_NPERIPHERALS);

irqstate = enter_critical_section();

/* Get the CPU interrupt ID mapped to this peripheral. */

cpuint = getreg32(DR_REG_INTERRUPT_BASE + periphid * 4) & 0x1f;

irqinfo("INFO: irq[%" PRIu8 "]=%" PRIu8 "\n", periphid, cpuint);

if (cpuint != 0)
{
/* Undo the allocation process:
* 1. Unmap the peripheral from the CPU interrupt ID.
* 2. Reset the interrupt type.
* 3. Reset the interrupt priority.
* 4. Clear the CPU interrupt.
*/

DEBUGASSERT(g_cpu_intmap[cpuint] != CPUINT_UNASSIGNED);

g_cpu_intmap[cpuint] = CPUINT_UNASSIGNED;
putreg32(0, DR_REG_INTERRUPT_BASE + periphid * 4);
resetbits(1 << cpuint, INTERRUPT_CPU_INT_TYPE_REG);
putreg32(0, INTERRUPT_CPU_INT_PRI_0_REG + cpuint * 4);
resetbits(1 << cpuint, INTERRUPT_CPU_INT_ENABLE_REG);
}
irqstate_t flags;

leave_critical_section(irqstate);
flags = spin_lock_irqsave(&g_irq_lock);
sched_lock();
esp32c3_free_cpuint_nolock(periphid);
spin_unlock_irqrestore(&g_irq_lock, flags);
sched_unlock();
}

/****************************************************************************
Expand Down Expand Up @@ -462,13 +481,14 @@ void esp32c3_bind_irq(uint8_t cpuint, uint8_t periphid, uint8_t prio,

int esp32c3_setup_irq(int periphid, int priority, int type)
{
irqstate_t irqstate;
irqstate_t flags;
int irq;
int cpuint;

irqinfo("periphid = %d\n", periphid);

irqstate = enter_critical_section();
flags = spin_lock_irqsave(&g_irq_lock);
sched_lock();

/* Setting up an IRQ includes the following steps:
* 1. Allocate a CPU interrupt.
Expand All @@ -481,7 +501,8 @@ int esp32c3_setup_irq(int periphid, int priority, int type)
{
irqerr("Unable to allocate CPU interrupt for priority=%d and type=%d",
priority, type);
leave_critical_section(irqstate);
spin_unlock_irqrestore(&g_irq_lock, flags);
sched_unlock();

return cpuint;
}
Expand All @@ -497,7 +518,8 @@ int esp32c3_setup_irq(int periphid, int priority, int type)

esp32c3_bind_irq(cpuint, periphid, priority, type);

leave_critical_section(irqstate);
spin_unlock_irqrestore(&g_irq_lock, flags);
sched_unlock();

return cpuint;
}
Expand All @@ -523,19 +545,20 @@ int esp32c3_setup_irq(int periphid, int priority, int type)

void esp32c3_teardown_irq(int periphid, int cpuint)
{
irqstate_t irqstate;
irqstate_t flags;
uintptr_t regaddr;
int irq;

irqstate = enter_critical_section();
flags = spin_lock_irqsave(&g_irq_lock);
sched_lock();

/* Tearing down an IRQ includes the following steps:
* 1. Free the previously allocated CPU interrupt.
* 2. Detach the interrupt from the peripheral.
* 3. Unmap the IRQ from the IRQ-to-cpuint map.
*/

esp32c3_free_cpuint(cpuint);
esp32c3_free_cpuint_nolock(cpuint);

irq = ESP32C3_PERIPH2IRQ(periphid);

Expand All @@ -548,7 +571,8 @@ void esp32c3_teardown_irq(int periphid, int cpuint)

putreg32(NO_CPUINT, regaddr);

leave_critical_section(irqstate);
spin_unlock_irqrestore(&g_irq_lock, flags);
sched_unlock();
}

/****************************************************************************
Expand Down
Loading