Merge branch 'refactor/riscv_interrupt' into 'master'

refactor(riscv): Refactor crosscore interrupts and core interrupt code

Closes IDF-5720, DOC-5177, and IDF-7899

See merge request espressif/esp-idf!27845
This commit is contained in:
Omar Chebib
2024-01-19 10:51:04 +08:00
49 changed files with 1161 additions and 297 deletions

View File

@@ -463,9 +463,8 @@ static void interrupt_set_wrapper(int cpu_no, int intr_source, int intr_num, int
{ {
esp_rom_route_intr_matrix(cpu_no, intr_source, intr_num); esp_rom_route_intr_matrix(cpu_no, intr_source, intr_num);
#if __riscv #if __riscv
esprv_intc_int_set_priority(intr_num, intr_prio); esprv_int_set_priority(intr_num, intr_prio);
//esprv_intc_int_enable_level(1 << intr_num); esprv_int_set_type(intr_num, 0);
esprv_intc_int_set_type(intr_num, 0);
#endif #endif
} }

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -261,7 +261,7 @@ FORCE_INLINE_ATTR void esp_cpu_intr_set_type(int intr_num, esp_cpu_intr_type_t i
{ {
assert(intr_num >= 0 && intr_num < SOC_CPU_INTR_NUM); assert(intr_num >= 0 && intr_num < SOC_CPU_INTR_NUM);
enum intr_type type = (intr_type == ESP_CPU_INTR_TYPE_LEVEL) ? INTR_TYPE_LEVEL : INTR_TYPE_EDGE; enum intr_type type = (intr_type == ESP_CPU_INTR_TYPE_LEVEL) ? INTR_TYPE_LEVEL : INTR_TYPE_EDGE;
esprv_intc_int_set_type(intr_num, type); esprv_int_set_type(intr_num, type);
} }
/** /**
@@ -276,7 +276,7 @@ FORCE_INLINE_ATTR void esp_cpu_intr_set_type(int intr_num, esp_cpu_intr_type_t i
FORCE_INLINE_ATTR esp_cpu_intr_type_t esp_cpu_intr_get_type(int intr_num) FORCE_INLINE_ATTR esp_cpu_intr_type_t esp_cpu_intr_get_type(int intr_num)
{ {
assert(intr_num >= 0 && intr_num < SOC_CPU_INTR_NUM); assert(intr_num >= 0 && intr_num < SOC_CPU_INTR_NUM);
enum intr_type type = esprv_intc_int_get_type(intr_num); enum intr_type type = esprv_int_get_type(intr_num);
return (type == INTR_TYPE_LEVEL) ? ESP_CPU_INTR_TYPE_LEVEL : ESP_CPU_INTR_TYPE_EDGE; return (type == INTR_TYPE_LEVEL) ? ESP_CPU_INTR_TYPE_LEVEL : ESP_CPU_INTR_TYPE_EDGE;
} }
@@ -291,7 +291,7 @@ FORCE_INLINE_ATTR esp_cpu_intr_type_t esp_cpu_intr_get_type(int intr_num)
FORCE_INLINE_ATTR void esp_cpu_intr_set_priority(int intr_num, int intr_priority) FORCE_INLINE_ATTR void esp_cpu_intr_set_priority(int intr_num, int intr_priority)
{ {
assert(intr_num >= 0 && intr_num < SOC_CPU_INTR_NUM); assert(intr_num >= 0 && intr_num < SOC_CPU_INTR_NUM);
esprv_intc_int_set_priority(intr_num, intr_priority); esprv_int_set_priority(intr_num, intr_priority);
} }
/** /**
@@ -306,7 +306,7 @@ FORCE_INLINE_ATTR void esp_cpu_intr_set_priority(int intr_num, int intr_priority
FORCE_INLINE_ATTR int esp_cpu_intr_get_priority(int intr_num) FORCE_INLINE_ATTR int esp_cpu_intr_get_priority(int intr_num)
{ {
assert(intr_num >= 0 && intr_num < SOC_CPU_INTR_NUM); assert(intr_num >= 0 && intr_num < SOC_CPU_INTR_NUM);
return esprv_intc_int_get_priority(intr_num); return esprv_int_get_priority(intr_num);
} }
#endif // SOC_CPU_HAS_FLEXIBLE_INTC #endif // SOC_CPU_HAS_FLEXIBLE_INTC

View File

@@ -630,8 +630,8 @@ static esp_err_t esp_mprot_set_intr_matrix(const esp_mprot_mem_t mem_type)
} }
/* Set the type and priority to cache error interrupts. */ /* Set the type and priority to cache error interrupts. */
esprv_intc_int_set_type(ETS_MEMPROT_ERR_INUM, INTR_TYPE_LEVEL); esprv_int_set_type(ETS_MEMPROT_ERR_INUM, INTR_TYPE_LEVEL);
esprv_intc_int_set_priority(ETS_MEMPROT_ERR_INUM, SOC_INTERRUPT_LEVEL_MEDIUM); esprv_int_set_priority(ETS_MEMPROT_ERR_INUM, SOC_INTERRUPT_LEVEL_MEDIUM);
ESP_INTR_ENABLE(ETS_MEMPROT_ERR_INUM); ESP_INTR_ENABLE(ETS_MEMPROT_ERR_INUM);

View File

@@ -10,7 +10,7 @@
#include "esp_intr_alloc.h" #include "esp_intr_alloc.h"
#include "esp_debug_helpers.h" #include "esp_debug_helpers.h"
#include "soc/periph_defs.h" #include "soc/periph_defs.h"
#include "hal/crosscore_int_ll.h"
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/portmacro.h" #include "freertos/portmacro.h"
@@ -19,15 +19,6 @@
#include "esp_gdbstub.h" #include "esp_gdbstub.h"
#endif #endif
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
#include "soc/dport_reg.h"
#else
#include "soc/system_reg.h"
#endif
#if CONFIG_IDF_TARGET_ESP32P4
#include "soc/hp_system_reg.h"
#endif
#define REASON_YIELD BIT(0) #define REASON_YIELD BIT(0)
#define REASON_FREQ_SWITCH BIT(1) #define REASON_FREQ_SWITCH BIT(1)
#define REASON_PRINT_BACKTRACE BIT(2) #define REASON_PRINT_BACKTRACE BIT(2)
@@ -53,29 +44,7 @@ static void IRAM_ATTR esp_crosscore_isr(void *arg) {
volatile uint32_t *my_reason=arg; volatile uint32_t *my_reason=arg;
//Clear the interrupt first. //Clear the interrupt first.
#if CONFIG_IDF_TARGET_ESP32 crosscore_int_ll_clear_interrupt(esp_cpu_get_core_id());
if (esp_cpu_get_core_id()==0) {
DPORT_WRITE_PERI_REG(DPORT_CPU_INTR_FROM_CPU_0_REG, 0);
} else {
DPORT_WRITE_PERI_REG(DPORT_CPU_INTR_FROM_CPU_1_REG, 0);
}
#elif CONFIG_IDF_TARGET_ESP32S2
DPORT_WRITE_PERI_REG(DPORT_CPU_INTR_FROM_CPU_0_REG, 0);
#elif CONFIG_IDF_TARGET_ESP32S3
if (esp_cpu_get_core_id()==0) {
WRITE_PERI_REG(SYSTEM_CPU_INTR_FROM_CPU_0_REG, 0);
} else {
WRITE_PERI_REG(SYSTEM_CPU_INTR_FROM_CPU_1_REG, 0);
}
#elif CONFIG_IDF_TARGET_ESP32P4
if (esp_cpu_get_core_id() == 0) {
WRITE_PERI_REG(HP_SYSTEM_CPU_INT_FROM_CPU_0_REG, 0);
} else {
WRITE_PERI_REG(HP_SYSTEM_CPU_INT_FROM_CPU_1_REG, 0);
}
#elif CONFIG_IDF_TARGET_ARCH_RISCV
WRITE_PERI_REG(SYSTEM_CPU_INTR_FROM_CPU_0_REG, 0);
#endif
//Grab the reason and clear it. //Grab the reason and clear it.
portENTER_CRITICAL_ISR(&reason_spinlock); portENTER_CRITICAL_ISR(&reason_spinlock);
@@ -142,29 +111,7 @@ static void IRAM_ATTR esp_crosscore_int_send(int core_id, uint32_t reason_mask)
reason[core_id] |= reason_mask; reason[core_id] |= reason_mask;
portEXIT_CRITICAL_ISR(&reason_spinlock); portEXIT_CRITICAL_ISR(&reason_spinlock);
//Poke the other CPU. //Poke the other CPU.
#if CONFIG_IDF_TARGET_ESP32 crosscore_int_ll_trigger_interrupt(core_id);
if (core_id==0) {
DPORT_WRITE_PERI_REG(DPORT_CPU_INTR_FROM_CPU_0_REG, DPORT_CPU_INTR_FROM_CPU_0);
} else {
DPORT_WRITE_PERI_REG(DPORT_CPU_INTR_FROM_CPU_1_REG, DPORT_CPU_INTR_FROM_CPU_1);
}
#elif CONFIG_IDF_TARGET_ESP32S2
DPORT_WRITE_PERI_REG(DPORT_CPU_INTR_FROM_CPU_0_REG, DPORT_CPU_INTR_FROM_CPU_0);
#elif CONFIG_IDF_TARGET_ESP32S3
if (core_id==0) {
WRITE_PERI_REG(SYSTEM_CPU_INTR_FROM_CPU_0_REG, SYSTEM_CPU_INTR_FROM_CPU_0);
} else {
WRITE_PERI_REG(SYSTEM_CPU_INTR_FROM_CPU_1_REG, SYSTEM_CPU_INTR_FROM_CPU_1);
}
#elif CONFIG_IDF_TARGET_ESP32P4
if (core_id==0) {
WRITE_PERI_REG(HP_SYSTEM_CPU_INT_FROM_CPU_0_REG, HP_SYSTEM_CPU_INT_FROM_CPU_0);
} else {
WRITE_PERI_REG(HP_SYSTEM_CPU_INT_FROM_CPU_1_REG, HP_SYSTEM_CPU_INT_FROM_CPU_1);
}
#elif CONFIG_IDF_TARGET_ARCH_RISCV
WRITE_PERI_REG(SYSTEM_CPU_INTR_FROM_CPU_0_REG, SYSTEM_CPU_INTR_FROM_CPU_0);
#endif
} }
void IRAM_ATTR esp_crosscore_int_send_yield(int core_id) void IRAM_ATTR esp_crosscore_int_send_yield(int core_id)

View File

@@ -40,8 +40,8 @@ ESP_SYSTEM_INIT_FN(esp_hw_stack_guard_init, SECONDARY, ESP_SYSTEM_INIT_ALL_CORES
/* enable interrup routine */ /* enable interrup routine */
esp_rom_route_intr_matrix(core_id, ETS_ASSIST_DEBUG_INTR_SOURCE, ETS_ASSIST_DEBUG_INUM); esp_rom_route_intr_matrix(core_id, ETS_ASSIST_DEBUG_INTR_SOURCE, ETS_ASSIST_DEBUG_INUM);
esprv_intc_int_set_type(ETS_ASSIST_DEBUG_INUM, INTR_TYPE_LEVEL); esprv_int_set_type(ETS_ASSIST_DEBUG_INUM, INTR_TYPE_LEVEL);
esprv_intc_int_set_priority(ETS_ASSIST_DEBUG_INUM, SOC_INTERRUPT_LEVEL_MEDIUM); esprv_int_set_priority(ETS_ASSIST_DEBUG_INUM, SOC_INTERRUPT_LEVEL_MEDIUM);
ESP_INTR_ENABLE(ETS_ASSIST_DEBUG_INUM); ESP_INTR_ENABLE(ETS_ASSIST_DEBUG_INUM);
return ESP_OK; return ESP_OK;

View File

@@ -50,7 +50,7 @@ void esp_crosscore_int_send_freq_switch(int core_id);
void esp_crosscore_int_send_gdb_call(int core_id); void esp_crosscore_int_send_gdb_call(int core_id);
#if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32C2 && !CONFIG_IDF_TARGET_ESP32C6 && !CONFIG_IDF_TARGET_ESP32H2 #if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
/** /**
* Send an interrupt to a CPU indicating it should print its current backtrace * Send an interrupt to a CPU indicating it should print its current backtrace
* *
@@ -75,7 +75,7 @@ void esp_crosscore_int_send_print_backtrace(int core_id);
void esp_crosscore_int_send_twdt_abort(int core_id); void esp_crosscore_int_send_twdt_abort(int core_id);
#endif // CONFIG_ESP_TASK_WDT_EN #endif // CONFIG_ESP_TASK_WDT_EN
#endif // !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32C2 && !CONFIG_IDF_TARGET_ESP32C6 #endif // !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -68,13 +68,16 @@
#elif CONFIG_IDF_TARGET_ESP32P4 #elif CONFIG_IDF_TARGET_ESP32P4
#include "esp32p4/rtc.h" #include "esp32p4/rtc.h"
#include "soc/hp_sys_clkrst_reg.h" #include "soc/hp_sys_clkrst_reg.h"
#include "soc/interrupt_core0_reg.h"
#include "soc/interrupt_core1_reg.h"
#include "soc/keymng_reg.h" #include "soc/keymng_reg.h"
#endif #endif
#include "esp_private/rtc_clk.h" #include "esp_private/rtc_clk.h"
#include "esp_private/esp_ldo_psram.h" #include "esp_private/esp_ldo_psram.h"
#if SOC_INT_CLIC_SUPPORTED
#include "hal/interrupt_clic_ll.h"
#endif // SOC_INT_CLIC_SUPPORTED
#include "esp_private/esp_mmu_map_private.h" #include "esp_private/esp_mmu_map_private.h"
#if CONFIG_SPIRAM #if CONFIG_SPIRAM
#include "esp_psram.h" #include "esp_psram.h"
@@ -159,21 +162,17 @@ static void core_intr_matrix_clear(void)
uint32_t core_id = esp_cpu_get_core_id(); uint32_t core_id = esp_cpu_get_core_id();
for (int i = 0; i < ETS_MAX_INTR_SOURCE; i++) { for (int i = 0; i < ETS_MAX_INTR_SOURCE; i++) {
#if CONFIG_IDF_TARGET_ESP32P4 #if SOC_INT_CLIC_SUPPORTED
if (core_id == 0) { interrupt_clic_ll_route(core_id, i, ETS_INVALID_INUM);
REG_WRITE(INTERRUPT_CORE0_LP_RTC_INT_MAP_REG + 4 * i, ETS_INVALID_INUM);
} else {
REG_WRITE(INTERRUPT_CORE1_LP_RTC_INT_MAP_REG + 4 * i, ETS_INVALID_INUM);
}
#else #else
esp_rom_route_intr_matrix(core_id, i, ETS_INVALID_INUM); esp_rom_route_intr_matrix(core_id, i, ETS_INVALID_INUM);
#endif // CONFIG_IDF_TARGET_ESP32P4 #endif // SOC_INT_CLIC_SUPPORTED
} }
#if SOC_INT_CLIC_SUPPORTED #if SOC_INT_CLIC_SUPPORTED
for (int i = 0; i < 32; i++) { for (int i = 0; i < 32; i++) {
/* Set all the CPU interrupt lines to vectored by default, as it is on other RISC-V targets */ /* Set all the CPU interrupt lines to vectored by default, as it is on other RISC-V targets */
esprv_intc_int_set_vectored(i, true); esprv_int_set_vectored(i, true);
} }
#endif // SOC_INT_CLIC_SUPPORTED #endif // SOC_INT_CLIC_SUPPORTED

View File

@@ -166,8 +166,8 @@ void esp_cache_err_int_init(void)
esp_rom_route_intr_matrix(core_id, ETS_CACHE_CORE0_ACS_INTR_SOURCE, ETS_CACHEERR_INUM); esp_rom_route_intr_matrix(core_id, ETS_CACHE_CORE0_ACS_INTR_SOURCE, ETS_CACHEERR_INUM);
/* Set the type and priority to cache error interrupts. */ /* Set the type and priority to cache error interrupts. */
esprv_intc_int_set_type(ETS_CACHEERR_INUM, INTR_TYPE_LEVEL); esprv_int_set_type(ETS_CACHEERR_INUM, INTR_TYPE_LEVEL);
esprv_intc_int_set_priority(ETS_CACHEERR_INUM, SOC_INTERRUPT_LEVEL_MEDIUM); esprv_int_set_priority(ETS_CACHEERR_INUM, SOC_INTERRUPT_LEVEL_MEDIUM);
ESP_DRAM_LOGV(TAG, "access error intr clr & ena mask is: 0x%x", CACHE_LL_L1_ACCESS_EVENT_MASK); ESP_DRAM_LOGV(TAG, "access error intr clr & ena mask is: 0x%x", CACHE_LL_L1_ACCESS_EVENT_MASK);
/* On the hardware side, start by clearing all the bits reponsible for cache access error */ /* On the hardware side, start by clearing all the bits reponsible for cache access error */

View File

@@ -165,8 +165,8 @@ void esp_cache_err_int_init(void)
esp_rom_route_intr_matrix(core_id, ETS_CACHE_CORE0_ACS_INTR_SOURCE, ETS_CACHEERR_INUM); esp_rom_route_intr_matrix(core_id, ETS_CACHE_CORE0_ACS_INTR_SOURCE, ETS_CACHEERR_INUM);
/* Set the type and priority to cache error interrupts. */ /* Set the type and priority to cache error interrupts. */
esprv_intc_int_set_type(ETS_CACHEERR_INUM, INTR_TYPE_LEVEL); esprv_int_set_type(ETS_CACHEERR_INUM, INTR_TYPE_LEVEL);
esprv_intc_int_set_priority(ETS_CACHEERR_INUM, SOC_INTERRUPT_LEVEL_MEDIUM); esprv_int_set_priority(ETS_CACHEERR_INUM, SOC_INTERRUPT_LEVEL_MEDIUM);
ESP_DRAM_LOGV(TAG, "access error intr clr & ena mask is: 0x%x", CACHE_LL_L1_ACCESS_EVENT_MASK); ESP_DRAM_LOGV(TAG, "access error intr clr & ena mask is: 0x%x", CACHE_LL_L1_ACCESS_EVENT_MASK);
/* On the hardware side, start by clearing all the bits reponsible for cache access error */ /* On the hardware side, start by clearing all the bits reponsible for cache access error */

View File

@@ -57,8 +57,8 @@ void esp_cache_err_int_init(void)
esp_rom_route_intr_matrix(core_id, ETS_CACHE_INTR_SOURCE, ETS_CACHEERR_INUM); esp_rom_route_intr_matrix(core_id, ETS_CACHE_INTR_SOURCE, ETS_CACHEERR_INUM);
/* Set the type and priority to cache error interrupts. */ /* Set the type and priority to cache error interrupts. */
esprv_intc_int_set_type(ETS_CACHEERR_INUM, INTR_TYPE_LEVEL); esprv_int_set_type(ETS_CACHEERR_INUM, INTR_TYPE_LEVEL);
esprv_intc_int_set_priority(ETS_CACHEERR_INUM, SOC_INTERRUPT_LEVEL_MEDIUM); esprv_int_set_priority(ETS_CACHEERR_INUM, SOC_INTERRUPT_LEVEL_MEDIUM);
ESP_DRAM_LOGV(TAG, "access error intr clr & ena mask is: 0x%x", CACHE_LL_L1_ACCESS_EVENT_MASK); ESP_DRAM_LOGV(TAG, "access error intr clr & ena mask is: 0x%x", CACHE_LL_L1_ACCESS_EVENT_MASK);
/* On the hardware side, start by clearing all the bits reponsible for cache access error */ /* On the hardware side, start by clearing all the bits reponsible for cache access error */

View File

@@ -56,8 +56,8 @@ void esp_cache_err_int_init(void)
esp_rom_route_intr_matrix(core_id, ETS_CACHE_INTR_SOURCE, ETS_CACHEERR_INUM); esp_rom_route_intr_matrix(core_id, ETS_CACHE_INTR_SOURCE, ETS_CACHEERR_INUM);
/* Set the type and priority to cache error interrupts. */ /* Set the type and priority to cache error interrupts. */
esprv_intc_int_set_type(ETS_CACHEERR_INUM, INTR_TYPE_LEVEL); esprv_int_set_type(ETS_CACHEERR_INUM, INTR_TYPE_LEVEL);
esprv_intc_int_set_priority(ETS_CACHEERR_INUM, SOC_INTERRUPT_LEVEL_MEDIUM); esprv_int_set_priority(ETS_CACHEERR_INUM, SOC_INTERRUPT_LEVEL_MEDIUM);
ESP_DRAM_LOGV(TAG, "access error intr clr & ena mask is: 0x%x", CACHE_LL_L1_ACCESS_EVENT_MASK); ESP_DRAM_LOGV(TAG, "access error intr clr & ena mask is: 0x%x", CACHE_LL_L1_ACCESS_EVENT_MASK);
/* On the hardware side, start by clearing all the bits reponsible for cache access error */ /* On the hardware side, start by clearing all the bits reponsible for cache access error */

View File

@@ -52,8 +52,8 @@ void esp_cache_err_int_init(void)
esp_rom_route_intr_matrix(core_id, ETS_CACHE_INTR_SOURCE, ETS_CACHEERR_INUM); esp_rom_route_intr_matrix(core_id, ETS_CACHE_INTR_SOURCE, ETS_CACHEERR_INUM);
/* Set the type and priority to cache error interrupts. */ /* Set the type and priority to cache error interrupts. */
esprv_intc_int_set_type(ETS_CACHEERR_INUM, INTR_TYPE_LEVEL); esprv_int_set_type(ETS_CACHEERR_INUM, INTR_TYPE_LEVEL);
esprv_intc_int_set_priority(ETS_CACHEERR_INUM, SOC_INTERRUPT_LEVEL_MEDIUM); esprv_int_set_priority(ETS_CACHEERR_INUM, SOC_INTERRUPT_LEVEL_MEDIUM);
ESP_DRAM_LOGV(TAG, "access error intr clr & ena mask is: 0x%x", CACHE_LL_L1_ACCESS_EVENT_MASK); ESP_DRAM_LOGV(TAG, "access error intr clr & ena mask is: 0x%x", CACHE_LL_L1_ACCESS_EVENT_MASK);
/* On the hardware side, start by clearing all the bits reponsible for cache access error */ /* On the hardware side, start by clearing all the bits reponsible for cache access error */

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -105,9 +105,9 @@ static void wifi_delete_queue_wrapper(void *queue)
static void set_intr_wrapper(int32_t cpu_no, uint32_t intr_source, uint32_t intr_num, int32_t intr_prio) static void set_intr_wrapper(int32_t cpu_no, uint32_t intr_source, uint32_t intr_num, int32_t intr_prio)
{ {
intr_matrix_route(intr_source, intr_num); esp_rom_route_intr_matrix(cpu_no, intr_source, intr_num);
esprv_intc_int_set_priority(intr_num, intr_prio); esprv_int_set_priority(intr_num, intr_prio);
esprv_intc_int_set_type(intr_num, INTR_TYPE_LEVEL); esprv_int_set_type(intr_num, INTR_TYPE_LEVEL);
} }
static void clear_intr_wrapper(uint32_t intr_source, uint32_t intr_num) static void clear_intr_wrapper(uint32_t intr_source, uint32_t intr_num)
@@ -122,12 +122,12 @@ static void set_isr_wrapper(int32_t n, void *f, void *arg)
static void enable_intr_wrapper(uint32_t intr_mask) static void enable_intr_wrapper(uint32_t intr_mask)
{ {
esprv_intc_int_enable(intr_mask); esprv_int_enable(intr_mask);
} }
static void disable_intr_wrapper(uint32_t intr_mask) static void disable_intr_wrapper(uint32_t intr_mask)
{ {
esprv_intc_int_disable(intr_mask); esprv_int_disable(intr_mask);
} }
static bool IRAM_ATTR is_from_isr_wrapper(void) static bool IRAM_ATTR is_from_isr_wrapper(void)

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -108,9 +108,9 @@ static void wifi_delete_queue_wrapper(void *queue)
static void set_intr_wrapper(int32_t cpu_no, uint32_t intr_source, uint32_t intr_num, int32_t intr_prio) static void set_intr_wrapper(int32_t cpu_no, uint32_t intr_source, uint32_t intr_num, int32_t intr_prio)
{ {
intr_matrix_route(intr_source, intr_num); esp_rom_route_intr_matrix(cpu_no, intr_source, intr_num);
esprv_intc_int_set_priority(intr_num, intr_prio); esprv_int_set_priority(intr_num, intr_prio);
esprv_intc_int_set_type(intr_num, INTR_TYPE_LEVEL); esprv_int_set_type(intr_num, INTR_TYPE_LEVEL);
} }
static void clear_intr_wrapper(uint32_t intr_source, uint32_t intr_num) static void clear_intr_wrapper(uint32_t intr_source, uint32_t intr_num)
@@ -125,12 +125,12 @@ static void set_isr_wrapper(int32_t n, void *f, void *arg)
static void enable_intr_wrapper(uint32_t intr_mask) static void enable_intr_wrapper(uint32_t intr_mask)
{ {
esprv_intc_int_enable(intr_mask); esprv_int_enable(intr_mask);
} }
static void disable_intr_wrapper(uint32_t intr_mask) static void disable_intr_wrapper(uint32_t intr_mask)
{ {
esprv_intc_int_disable(intr_mask); esprv_int_disable(intr_mask);
} }
static bool IRAM_ATTR is_from_isr_wrapper(void) static bool IRAM_ATTR is_from_isr_wrapper(void)

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -111,9 +111,9 @@ static void wifi_delete_queue_wrapper(void *queue)
static void set_intr_wrapper(int32_t cpu_no, uint32_t intr_source, uint32_t intr_num, int32_t intr_prio) static void set_intr_wrapper(int32_t cpu_no, uint32_t intr_source, uint32_t intr_num, int32_t intr_prio)
{ {
intr_matrix_route(intr_source, intr_num); esp_rom_route_intr_matrix(cpu_no, intr_source, intr_num);
esprv_intc_int_set_priority(intr_num, intr_prio); esprv_int_set_priority(intr_num, intr_prio);
esprv_intc_int_set_type(intr_num, INTR_TYPE_LEVEL); esprv_int_set_type(intr_num, INTR_TYPE_LEVEL);
} }
static void clear_intr_wrapper(uint32_t intr_source, uint32_t intr_num) static void clear_intr_wrapper(uint32_t intr_source, uint32_t intr_num)
@@ -128,12 +128,12 @@ static void set_isr_wrapper(int32_t n, void *f, void *arg)
static void enable_intr_wrapper(uint32_t intr_mask) static void enable_intr_wrapper(uint32_t intr_mask)
{ {
esprv_intc_int_enable(intr_mask); esprv_int_enable(intr_mask);
} }
static void disable_intr_wrapper(uint32_t intr_mask) static void disable_intr_wrapper(uint32_t intr_mask)
{ {
esprv_intc_int_disable(intr_mask); esprv_int_disable(intr_mask);
} }
static bool IRAM_ATTR is_from_isr_wrapper(void) static bool IRAM_ATTR is_from_isr_wrapper(void)

View File

@@ -9,7 +9,7 @@
#include "soc/soc_caps.h" #include "soc/soc_caps.h"
#include "soc/periph_defs.h" #include "soc/periph_defs.h"
#include "soc/system_reg.h" #include "soc/system_reg.h"
#include "soc/interrupt_reg.h" #include "hal/crosscore_int_ll.h"
#include "hal/systimer_hal.h" #include "hal/systimer_hal.h"
#include "hal/systimer_ll.h" #include "hal/systimer_ll.h"
#include "riscv/rvruntime-frames.h" #include "riscv/rvruntime-frames.h"
@@ -184,6 +184,9 @@ void IRAM_ATTR vPortReleaseLock( portMUX_TYPE *lock )
void vPortYield(void) void vPortYield(void)
{ {
// TODO: IDF-8113
const int core_id = 0;
if (uxInterruptNesting) { if (uxInterruptNesting) {
vPortYieldFromISR(); vPortYieldFromISR();
} else { } else {
@@ -199,7 +202,7 @@ void vPortYield(void)
for an instant yield, and if that happens then the WFI would be for an instant yield, and if that happens then the WFI would be
waiting for the next interrupt to occur...) waiting for the next interrupt to occur...)
*/ */
while (uxSchedulerRunning && REG_READ(SYSTEM_CPU_INTR_FROM_CPU_0_REG) != 0) {} while (uxSchedulerRunning && crosscore_int_ll_get_state(core_id) != 0) {}
} }
} }
@@ -283,7 +286,7 @@ BaseType_t xPortStartScheduler(void)
/* Setup the hardware to generate the tick. */ /* Setup the hardware to generate the tick. */
vPortSetupTimer(); vPortSetupTimer();
esprv_intc_int_set_threshold(1); /* set global INTC masking level */ esprv_int_set_threshold(1); /* set global INTC masking level */
rv_utils_intr_global_enable(); rv_utils_intr_global_enable();
vPortYield(); vPortYield();

View File

@@ -46,6 +46,7 @@
#include "riscv/rv_utils.h" #include "riscv/rv_utils.h"
#include "riscv/interrupt.h" #include "riscv/interrupt.h"
#include "esp_private/crosscore_int.h" #include "esp_private/crosscore_int.h"
#include "hal/crosscore_int_ll.h"
#include "esp_attr.h" #include "esp_attr.h"
#include "esp_system.h" #include "esp_system.h"
#include "esp_intr_alloc.h" #include "esp_intr_alloc.h"
@@ -144,7 +145,7 @@ BaseType_t xPortStartScheduler(void)
/* Setup the hardware to generate the tick. */ /* Setup the hardware to generate the tick. */
vPortSetupTimer(); vPortSetupTimer();
esprv_intc_int_set_threshold(RVHAL_INTR_ENABLE_THRESH); /* set global interrupt masking level */ esprv_int_set_threshold(RVHAL_INTR_ENABLE_THRESH); /* set global interrupt masking level */
rv_utils_intr_global_enable(); rv_utils_intr_global_enable();
vPortYield(); vPortYield();
@@ -626,13 +627,6 @@ void vPortExitCritical(void)
void vPortYield(void) void vPortYield(void)
{ {
BaseType_t coreID = xPortGetCoreID(); BaseType_t coreID = xPortGetCoreID();
int system_cpu_int_reg;
#if !CONFIG_IDF_TARGET_ESP32P4
system_cpu_int_reg = SYSTEM_CPU_INTR_FROM_CPU_0_REG;
#else
system_cpu_int_reg = HP_SYSTEM_CPU_INT_FROM_CPU_0_REG;
#endif /* !CONFIG_IDF_TARGET_ESP32P4 */
if (port_uxInterruptNesting[coreID]) { if (port_uxInterruptNesting[coreID]) {
vPortYieldFromISR(); vPortYieldFromISR();
@@ -648,7 +642,7 @@ void vPortYield(void)
for an instant yield, and if that happens then the WFI would be for an instant yield, and if that happens then the WFI would be
waiting for the next interrupt to occur...) waiting for the next interrupt to occur...)
*/ */
while (port_xSchedulerRunning[coreID] && port_uxCriticalNesting[coreID] == 0 && REG_READ(system_cpu_int_reg + 4 * coreID) != 0) {} while (port_xSchedulerRunning[coreID] && port_uxCriticalNesting[coreID] == 0 && crosscore_int_ll_get_state(coreID) != 0) {}
} }
} }

View File

@@ -23,8 +23,8 @@
#define TEST_CLR_INT_MASK(mask) xt_set_intclear(mask) #define TEST_CLR_INT_MASK(mask) xt_set_intclear(mask)
#elif CONFIG_IDF_TARGET_ARCH_RISCV #elif CONFIG_IDF_TARGET_ARCH_RISCV
#include "riscv/interrupt.h" #include "riscv/interrupt.h"
#define TEST_SET_INT_MASK(mask) esprv_intc_int_enable(mask) #define TEST_SET_INT_MASK(mask) esprv_int_enable(mask)
#define TEST_CLR_INT_MASK(mask) esprv_intc_int_disable(mask) #define TEST_CLR_INT_MASK(mask) esprv_int_disable(mask)
#endif #endif
#ifndef __riscv // TODO: IDF-4416 #ifndef __riscv // TODO: IDF-4416

View File

@@ -0,0 +1,45 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "esp_attr.h"
#include "soc/dport_reg.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Clear the crosscore interrupt that just occurred on the current core
*/
FORCE_INLINE_ATTR void crosscore_int_ll_clear_interrupt(int core_id)
{
if (core_id == 0) {
DPORT_WRITE_PERI_REG(DPORT_CPU_INTR_FROM_CPU_0_REG, 0);
} else {
DPORT_WRITE_PERI_REG(DPORT_CPU_INTR_FROM_CPU_1_REG, 0);
}
}
/**
* @brief Trigger a crosscore interrupt on the given core
*
* @param core_id Core to trigger an interrupt on. Ignored on single core targets.
*/
FORCE_INLINE_ATTR void crosscore_int_ll_trigger_interrupt(int core_id)
{
if (core_id == 0) {
DPORT_WRITE_PERI_REG(DPORT_CPU_INTR_FROM_CPU_0_REG, DPORT_CPU_INTR_FROM_CPU_0);
} else {
DPORT_WRITE_PERI_REG(DPORT_CPU_INTR_FROM_CPU_1_REG, DPORT_CPU_INTR_FROM_CPU_1);
}
}
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,52 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include "esp_attr.h"
#include "soc/system_reg.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Clear the crosscore interrupt that just occurred on the current core
*/
FORCE_INLINE_ATTR void crosscore_int_ll_clear_interrupt(int core_id)
{
WRITE_PERI_REG(SYSTEM_CPU_INTR_FROM_CPU_0_REG, 0);
}
/**
* @brief Trigger a crosscore interrupt on the given core
*
* @param core_id Core to trigger an interrupt on. Ignored on single core targets.
*/
FORCE_INLINE_ATTR void crosscore_int_ll_trigger_interrupt(int core_id)
{
WRITE_PERI_REG(SYSTEM_CPU_INTR_FROM_CPU_0_REG, SYSTEM_CPU_INTR_FROM_CPU_0);
}
/**
* @brief Get the state of the crosscore interrupt register for the given core
*
* @param core_id Core to get the crosscore interrupt state of. Ignored on single core targets.
*
* @return Non zero value if a software interrupt is pending on the given core,
* 0 if no software interrupt is pending.
*/
FORCE_INLINE_ATTR uint32_t crosscore_int_ll_get_state(int core_id)
{
return REG_READ(SYSTEM_CPU_INTR_FROM_CPU_0_REG);
}
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,52 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include "esp_attr.h"
#include "soc/system_reg.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Clear the crosscore interrupt that just occurred on the current core
*/
FORCE_INLINE_ATTR void crosscore_int_ll_clear_interrupt(int core_id)
{
WRITE_PERI_REG(SYSTEM_CPU_INTR_FROM_CPU_0_REG, 0);
}
/**
* @brief Trigger a crosscore interrupt on the given core
*
* @param core_id Core to trigger an interrupt on. Ignored on single core targets.
*/
FORCE_INLINE_ATTR void crosscore_int_ll_trigger_interrupt(int core_id)
{
WRITE_PERI_REG(SYSTEM_CPU_INTR_FROM_CPU_0_REG, SYSTEM_CPU_INTR_FROM_CPU_0);
}
/**
* @brief Get the state of the crosscore interrupt register for the given core
*
* @param core_id Core to get the crosscore interrupt state of. Ignored on single core targets.
*
* @return Non zero value if a software interrupt is pending on the given core,
* 0 if no software interrupt is pending.
*/
FORCE_INLINE_ATTR uint32_t crosscore_int_ll_get_state(int core_id)
{
return REG_READ(SYSTEM_CPU_INTR_FROM_CPU_0_REG);
}
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,52 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include "esp_attr.h"
#include "soc/intpri_reg.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Clear the crosscore interrupt that just occurred on the current core
*/
FORCE_INLINE_ATTR void crosscore_int_ll_clear_interrupt(int core_id)
{
WRITE_PERI_REG(INTPRI_CPU_INTR_FROM_CPU_0_REG, 0);
}
/**
* @brief Trigger a crosscore interrupt on the given core
*
* @param core_id Core to trigger an interrupt on. Ignored on single core targets.
*/
FORCE_INLINE_ATTR void crosscore_int_ll_trigger_interrupt(int core_id)
{
WRITE_PERI_REG(INTPRI_CPU_INTR_FROM_CPU_0_REG, INTPRI_CPU_INTR_FROM_CPU_0);
}
/**
* @brief Get the state of the crosscore interrupt register for the given core
*
* @param core_id Core to get the crosscore interrupt state of. Ignored on single core targets.
*
* @return Non zero value if a software interrupt is pending on the given core,
* 0 if no software interrupt is pending.
*/
FORCE_INLINE_ATTR uint32_t crosscore_int_ll_get_state(int core_id)
{
return REG_READ(INTPRI_CPU_INTR_FROM_CPU_0_REG);
}
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,52 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include "esp_attr.h"
#include "soc/intpri_reg.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Clear the crosscore interrupt that just occurred on the current core
*/
FORCE_INLINE_ATTR void crosscore_int_ll_clear_interrupt(int core_id)
{
WRITE_PERI_REG(INTPRI_CPU_INTR_FROM_CPU_0_REG, 0);
}
/**
* @brief Trigger a crosscore interrupt on the given core
*
* @param core_id Core to trigger an interrupt on. Ignored on single core targets.
*/
FORCE_INLINE_ATTR void crosscore_int_ll_trigger_interrupt(int core_id)
{
WRITE_PERI_REG(INTPRI_CPU_INTR_FROM_CPU_0_REG, INTPRI_CPU_INTR_FROM_CPU_0);
}
/**
* @brief Get the state of the crosscore interrupt register for the given core
*
* @param core_id Core to get the crosscore interrupt state of. Ignored on single core targets.
*
* @return Non zero value if a software interrupt is pending on the given core,
* 0 if no software interrupt is pending.
*/
FORCE_INLINE_ATTR uint32_t crosscore_int_ll_get_state(int core_id)
{
return REG_READ(INTPRI_CPU_INTR_FROM_CPU_0_REG);
}
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,68 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include "esp_attr.h"
#include "soc/hp_system_reg.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Clear the crosscore interrupt that just occurred on the current core
*/
FORCE_INLINE_ATTR void crosscore_int_ll_clear_interrupt(int core_id)
{
if (core_id == 0) {
WRITE_PERI_REG(HP_SYSTEM_CPU_INT_FROM_CPU_0_REG, 0);
} else {
WRITE_PERI_REG(HP_SYSTEM_CPU_INT_FROM_CPU_1_REG, 0);
}
}
/**
* @brief Trigger a crosscore interrupt on the given core
*
* @param core_id Core to trigger an interrupt on. Ignored on single core targets.
*/
FORCE_INLINE_ATTR void crosscore_int_ll_trigger_interrupt(int core_id)
{
if (core_id == 0) {
WRITE_PERI_REG(HP_SYSTEM_CPU_INT_FROM_CPU_0_REG, HP_SYSTEM_CPU_INT_FROM_CPU_0);
} else {
WRITE_PERI_REG(HP_SYSTEM_CPU_INT_FROM_CPU_1_REG, HP_SYSTEM_CPU_INT_FROM_CPU_1);
}
}
/**
* @brief Get the state of the crosscore interrupt register for the given core
*
* @param core_id Core to get the crosscore interrupt state of. Ignored on single core targets.
*
* @return Non zero value if a software interrupt is pending on the given core,
* 0 if no software interrupt is pending.
*/
FORCE_INLINE_ATTR uint32_t crosscore_int_ll_get_state(int core_id)
{
uint32_t reg = 0;
if (core_id == 0) {
reg = REG_READ(HP_SYSTEM_CPU_INT_FROM_CPU_0_REG);
} else {
reg = REG_READ(HP_SYSTEM_CPU_INT_FROM_CPU_1_REG);
}
return reg;
}
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,37 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/dport_reg.h"
#include "esp_attr.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Clear the crosscore interrupt that just occurred on the current core
*/
static inline void crosscore_int_ll_clear_interrupt(int core_id)
{
DPORT_WRITE_PERI_REG(DPORT_CPU_INTR_FROM_CPU_0_REG, 0);
}
/**
* @brief Trigger a crosscore interrupt on the given core
*
* @param core_id Core to trigger an interrupt on. Ignored on single core targets.
*/
static inline void crosscore_int_ll_trigger_interrupt(int core_id)
{
DPORT_WRITE_PERI_REG(DPORT_CPU_INTR_FROM_CPU_0_REG, DPORT_CPU_INTR_FROM_CPU_0);
}
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,44 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/system_reg.h"
#include "esp_attr.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Clear the crosscore interrupt that just occurred on the current core
*/
FORCE_INLINE_ATTR void crosscore_int_ll_clear_interrupt(int core_id)
{
if (core_id == 0) {
WRITE_PERI_REG(SYSTEM_CPU_INTR_FROM_CPU_0_REG, 0);
} else {
WRITE_PERI_REG(SYSTEM_CPU_INTR_FROM_CPU_1_REG, 0);
}
}
/**
* @brief Trigger a crosscore interrupt on the given core
*
* @param core_id Core to trigger an interrupt on.
*/
FORCE_INLINE_ATTR void crosscore_int_ll_trigger_interrupt(int core_id)
{
if (core_id == 0) {
WRITE_PERI_REG(SYSTEM_CPU_INTR_FROM_CPU_0_REG, SYSTEM_CPU_INTR_FROM_CPU_0);
} else {
WRITE_PERI_REG(SYSTEM_CPU_INTR_FROM_CPU_1_REG, SYSTEM_CPU_INTR_FROM_CPU_1);
}
}
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,104 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdbool.h>
#include "hal/assert.h"
#include "esp_attr.h"
#include "soc/soc.h"
#include "soc/soc_caps.h"
#include "soc/reg_base.h"
#if SOC_INT_CLIC_SUPPORTED
#include "soc/clic_reg.h"
#ifdef __cplusplus
extern "C" {
#endif
#define RV_TOTAL_INT_COUNT 48
/**
* @brief Route any interrupt source to any CPU interrupt, including internal ones
*
* @param core_id CPU core to map the interrupt in (ignored on single-core targets)
* @param intr_src Interrupt source to map
* @param rv_int_num Destination CPU interrupt source, which can be an internal or an external interrupt.
*/
FORCE_INLINE_ATTR void interrupt_clic_ll_route(uint32_t core_id, int intr_src, int intr_num)
{
HAL_ASSERT(intr_num < RV_TOTAL_INT_COUNT);
#if SOC_CPU_CORES_NUM > 1
if (core_id == 0) {
REG_WRITE(DR_REG_INTERRUPT_CORE0_BASE + 4 * intr_src, intr_num);
} else {
REG_WRITE(DR_REG_INTERRUPT_CORE1_BASE + 4 * intr_src, intr_num);
}
#else
REG_WRITE(DR_REG_INTERRUPT_CORE0_BASE + 4 * intr_src, intr_num);
#endif // SOC_CPU_CORES_NUM > 1
}
/**
* @brief Get the type for the given interrupt
*
* @param rv_int_num Interrupt number to get the type of. It can be an internal or an external interrupt.
*
* @return 0 for level-triggered type, 1 for edge-triggered interrupt type
*/
FORCE_INLINE_ATTR int interrupt_clic_ll_get_type(int rv_int_num)
{
return REG_GET_FIELD(CLIC_INT_CTRL_REG(rv_int_num), CLIC_INT_ATTR_TRIG) & 1;
}
/**
* @brief Get the priority for the given interrupt
*
* @param rv_int_num Interrupt number to get the priority of. It can be an internal or an external interrupt.
*
* @return interrupt priority, between 0 and 7
*/
FORCE_INLINE_ATTR int interrupt_clic_ll_get_priority(int rv_int_num)
{
const uint32_t priority = REG_GET_FIELD(CLIC_INT_CTRL_REG(rv_int_num), CLIC_INT_CTL);
return (priority >> (8 - NLBITS));
}
/**
* @brief Check if an interrupt is vectored
*
* @param rv_int_num Interrupt number to check. It can be an internal or an external interrupt.
*
* @return true if the interrupt is vectored, false else
*/
FORCE_INLINE_ATTR bool interrupt_clic_ll_is_vectored(int rv_int_num)
{
const uint32_t shv = REG_GET_FIELD(CLIC_INT_CTRL_REG(rv_int_num), CLIC_INT_ATTR_SHV);
return shv != 0;
}
/**
* @brief Set an interrupt to vectored or non-vectored
*
* @param rv_int_num Interrupt number to modify. It can be an internal or an external interrupt.
* @param vectored True to set the interrupt to vectored, false to set it to non vectored.
*
*/
FORCE_INLINE_ATTR void interrupt_clic_ll_set_vectored(int rv_int_num, bool vectored)
{
REG_SET_FIELD(CLIC_INT_CTRL_REG(rv_int_num), CLIC_INT_ATTR_SHV, vectored ? 1 : 0);
}
#ifdef __cplusplus
}
#endif
#endif // SOC_INT_PLIC_SUPPORTED

View File

@@ -0,0 +1,75 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "esp_attr.h"
#include "soc/soc.h"
#include "soc/soc_caps.h"
#include "soc/reg_base.h"
/* Do not use INTC on targets that have harware CLIC */
#if SOC_CPU_HAS_FLEXIBLE_INTC && !SOC_INT_CLIC_SUPPORTED
#include "soc/interrupt_reg.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Route any interrupt source to any CPU interrupt, including internal ones
*
* @param intr_src Interrupt source to map
* @param rv_int_num Destination CPU interrupt source, which can be an internal or an external interrupt.
*/
FORCE_INLINE_ATTR void interrupt_intc_ll_route(int intr_src, int intr_num)
{
REG_WRITE(DR_REG_INTERRUPT_BASE + 4 * intr_src, intr_num);
}
/**
* @brief Get interrupt enable mask
*
* @return interrupt enable mask, bit i is 1 if interrupt i is enabled, 0 if interrupt i is disabled
*/
FORCE_INLINE_ATTR uint32_t interrupt_intc_ll_get_unmask(void)
{
return REG_READ(INTERRUPT_CORE0_CPU_INT_ENABLE_REG);
}
/**
* @brief Get the type for the given interrupt
*
* @param rv_int_num Interrupt number to get the type of. It can be an internal or an external interrupt.
*
* @return 0 for level-triggered type, 1 for edge-triggered interrupt type
*/
FORCE_INLINE_ATTR int interrupt_intc_ll_get_type(int rv_int_num)
{
uint32_t intr_type_reg = REG_READ(INTERRUPT_CORE0_CPU_INT_TYPE_REG);
return (intr_type_reg & (1 << rv_int_num));
}
/**
* @brief Get the priority for the given interrupt
*
* @param rv_int_num Interrupt number to get the priority of. It can be an internal or an external interrupt.
*
* @return interrupt priority, between 0 and 7
*/
FORCE_INLINE_ATTR int interrupt_intc_ll_get_priority(int rv_int_num)
{
return REG_READ(INTERRUPT_PRIO_REG(rv_int_num));
}
#ifdef __cplusplus
}
#endif
#endif // SOC_CPU_HAS_FLEXIBLE_INTC

View File

@@ -0,0 +1,76 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "esp_attr.h"
#include "soc/soc.h"
#include "soc/soc_caps.h"
#include "soc/reg_base.h"
#if SOC_INT_PLIC_SUPPORTED
#include "soc/interrupt_reg.h"
#include "soc/plic_reg.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Route any interrupt source to any CPU interrupt, including internal ones
*
* @param intr_src Interrupt source to map
* @param rv_int_num Destination CPU interrupt source, which can be an internal or an external interrupt.
*/
FORCE_INLINE_ATTR void interrupt_plic_ll_route(int intr_src, int intr_num)
{
REG_WRITE(DR_REG_INTERRUPT_MATRIX_BASE + 4 * intr_src, intr_num);
}
/**
* @brief Get interrupt enable mask
*
* @return interrupt enable mask, bit i is 1 if interrupt i is enabled, 0 if interrupt i is disabled
*/
FORCE_INLINE_ATTR uint32_t interrupt_plic_ll_get_unmask(void)
{
return REG_READ(PLIC_MXINT_ENABLE_REG);
}
/**
* @brief Get the type for the given interrupt
*
* @param rv_int_num Interrupt number to get the type of. It can be an internal or an external interrupt.
*
* @return 0 for level-triggered type, 1 for edge-triggered interrupt type
*/
FORCE_INLINE_ATTR int interrupt_plic_ll_get_type(int rv_int_num)
{
uint32_t intr_type_reg = REG_READ(PLIC_MXINT_TYPE_REG);
return (intr_type_reg & (1 << rv_int_num));
}
/**
* @brief Get the priority for the given interrupt
*
* @param rv_int_num Interrupt number to get the priority of. It can be an internal or an external interrupt.
*
* @return interrupt priority, between 0 and 7
*/
FORCE_INLINE_ATTR int interrupt_plic_ll_get_priority(int rv_int_num)
{
return REG_READ(INTERRUPT_PRIO_REG(rv_int_num));
}
#ifdef __cplusplus
}
#endif
#endif // SOC_INT_PLIC_SUPPORTED

View File

@@ -16,9 +16,11 @@ else()
"vectors.S") "vectors.S")
if(CONFIG_SOC_INT_CLIC_SUPPORTED) if(CONFIG_SOC_INT_CLIC_SUPPORTED)
list(APPEND srcs "vectors_clic.S") list(APPEND srcs "interrupt_clic.c" "vectors_clic.S")
elseif(CONFIG_SOC_INT_PLIC_SUPPORTED)
list(APPEND srcs "interrupt_plic.c" "vectors_intc.S")
else() else()
list(APPEND srcs "vectors_intc.S") list(APPEND srcs "interrupt_intc.c" "vectors_intc.S")
endif() endif()
endif() endif()
@@ -26,3 +28,5 @@ idf_component_register(SRCS "${srcs}"
LDFRAGMENTS linker.lf LDFRAGMENTS linker.lf
INCLUDE_DIRS "include" INCLUDE_DIRS "include"
PRIV_REQUIRES ${priv_requires}) PRIV_REQUIRES ${priv_requires})
target_linker_script(${COMPONENT_LIB} INTERFACE "ld/rom.api.ld")

View File

@@ -0,0 +1,35 @@
/*
* SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include <assert.h>
#include "esp_attr.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* If the target is using the CLIC as the interrupt controller, we have 32 external interrupt lines and 16 internal
* lines. Let's consider the internal ones reserved and not mappable to any handler.
*/
#define RV_EXTERNAL_INT_COUNT 32
#define RV_EXTERNAL_INT_OFFSET 16
FORCE_INLINE_ATTR void assert_valid_rv_int_num(int rv_int_num)
{
assert(rv_int_num < RV_EXTERNAL_INT_COUNT && "Invalid CPU interrupt number");
}
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,112 @@
/*
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include "riscv/interrupt.h"
#ifdef __cplusplus
extern "C" {
#endif
/*************************** Former API / Backport compatibility ***************************/
/**
* @brief Enable interrupts from interrupt controller.
*
* @param uint32_t unmask, unmask bits for interrupts, each bit for an interrupt
*
* return none
*/
void esprv_intc_int_enable(uint32_t unmask) __attribute__((deprecated("please use esprv_int_enable instead")));
/**
* @brief Disable interrupts from interrupt controller.
*
* @param uint32_t mask, mask bits for interrupts, each bit for an interrupt
*
* return none
*/
void esprv_intc_int_disable(uint32_t mask) __attribute__((deprecated("please use esprv_int_disable instead")));
/**
* @brief Set interrupt type
*
* Set the type of a particular interrupt (level or edge).
* - Level interrupts are cleared automatically once their interrupt source has
* been cleared
* - Edge interrupts must be cleared by software when they are handled.
*
* @param intr_num Interrupt number
* @param type Interrupt type
*/
void esprv_intc_int_set_type(int intr_num, enum intr_type type) __attribute__((deprecated("please use esprv_int_set_type instead")));
/**
* @brief Get the current type of an interrupt
*
* Get the current type of a particular interrupt (level or edge). An interrupt's
* type can be set by calling esprv_intc_int_set_type().
*
* @param intr_num Interrupt number
* @return Interrupt type
*/
static inline __attribute__((deprecated("please use esprv_int_get_type instead"))) enum intr_type esprv_intc_int_get_type(int intr_num)
{
return esprv_int_get_type(intr_num);
}
/**
* Set interrupt priority in the interrupt controller
* @param rv_int_num CPU interrupt number
* @param priority Interrupt priority level, 1 to 7
*/
void esprv_intc_int_set_priority(int rv_int_num, int priority) __attribute__((deprecated("please use esprv_int_set_priority instead")));
/**
* @brief Get the current priority of an interrupt
*
* Get the current priority of an interrupt.
*
* @param rv_int_num CPU interrupt number
* @return Interrupt priority level, 1 to 7
*/
static inline __attribute__((deprecated("please use esprv_int_get_priority instead"))) int esprv_intc_int_get_priority(int rv_int_num)
{
return esprv_int_get_priority(rv_int_num);
}
/**
* Set interrupt priority threshold.
* Interrupts with priority levels lower than the threshold are masked.
*
* @param priority_threshold Interrupt priority threshold, 0 to 7
*/
void esprv_intc_int_set_threshold(int priority_threshold) __attribute__((deprecated("please use esprv_int_set_threshold instead")));
/**
* @brief Get interrupt unmask
* @param none
* @return uint32_t interrupt unmask
*/
static inline __attribute__((deprecated("please use esprv_get_interrupt_unmask instead"))) uint32_t esprv_intc_get_interrupt_unmask(void)
{
return esprv_get_interrupt_unmask();
}
/**
* @brief Route the peripheral interrupt signal to the CPU
* @param periph_intr_source Peripheral interrupt number, one of ETS_XXX_SOURCE
* @param rv_int_num CPU interrupt number
*/
void intr_matrix_route(int periph_intr_source, int rv_int_num) __attribute__((deprecated("please use esp_rom_route_intr_matrix instead")));
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,33 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include <assert.h>
#include "esp_attr.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* In the case of INTC, all the interrupt lines are dedicated to external peripherals, so the offset is 0
*/
#define RV_EXTERNAL_INT_COUNT 32
#define RV_EXTERNAL_INT_OFFSET 0
FORCE_INLINE_ATTR void assert_valid_rv_int_num(int rv_int_num)
{
assert(rv_int_num != 0 && "Invalid CPU interrupt number");
}
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,33 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include <assert.h>
#include "esp_attr.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* In the case of PLIC, all the interrupt lines are dedicated to external peripherals, so the offset is 0
*/
#define RV_EXTERNAL_INT_COUNT 32
#define RV_EXTERNAL_INT_OFFSET 0
FORCE_INLINE_ATTR void assert_valid_rv_int_num(int rv_int_num)
{
assert(rv_int_num != 0 && "Invalid CPU interrupt number");
}
#ifdef __cplusplus
}
#endif

View File

@@ -1,21 +1,32 @@
/* /*
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
#pragma once #pragma once
#include <stdbool.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
enum intr_type { enum intr_type {
INTR_TYPE_LEVEL = 0, INTR_TYPE_LEVEL = 0,
INTR_TYPE_EDGE INTR_TYPE_EDGE
}; };
#include <stdbool.h>
#include "soc/soc_caps.h"
#if SOC_INT_CLIC_SUPPORTED
#include "esp_private/interrupt_clic.h"
#elif SOC_INT_PLIC_SUPPORTED
#include "esp_private/interrupt_plic.h"
#else
#include "esp_private/interrupt_intc.h"
#endif
/*************************** Software interrupt dispatcher ***************************/ /*************************** Software interrupt dispatcher ***************************/
/** Callback type of the interrupt handler */ /** Callback type of the interrupt handler */
@@ -40,16 +51,6 @@ intr_handler_t intr_handler_get(int rv_int_num);
*/ */
void *intr_handler_get_arg(int rv_int_num); void *intr_handler_get_arg(int rv_int_num);
/*************************** Interrupt matrix ***************************/
/**
* this function will be removed in later, please use `intr_matrix_set` instead
* Route the peripheral interrupt signal to the CPU
* @param periph_intr_source Peripheral interrupt number, one of ETS_XXX_SOURCE
* @param rv_int_num CPU interrupt number
*/
void intr_matrix_route(int periph_intr_source, int rv_int_num);
/*************************** ESP-RV Interrupt Controller ***************************/ /*************************** ESP-RV Interrupt Controller ***************************/
/** /**
@@ -59,7 +60,7 @@ void intr_matrix_route(int periph_intr_source, int rv_int_num);
* *
* return none * return none
*/ */
void esprv_intc_int_enable(uint32_t unmask); void esprv_int_enable(uint32_t unmask);
/** /**
* @brief Disable interrupts from interrupt controller. * @brief Disable interrupts from interrupt controller.
@@ -68,7 +69,7 @@ void esprv_intc_int_enable(uint32_t unmask);
* *
* return none * return none
*/ */
void esprv_intc_int_disable(uint32_t mask); void esprv_int_disable(uint32_t mask);
/** /**
* @brief Set interrupt type * @brief Set interrupt type
@@ -81,25 +82,25 @@ void esprv_intc_int_disable(uint32_t mask);
* @param intr_num Interrupt number * @param intr_num Interrupt number
* @param type Interrupt type * @param type Interrupt type
*/ */
void esprv_intc_int_set_type(int intr_num, enum intr_type type); void esprv_int_set_type(int intr_num, enum intr_type type);
/** /**
* @brief Get the current type of an interrupt * @brief Get the current type of an interrupt
* *
* Get the current type of a particular interrupt (level or edge). An interrupt's * Get the current type of a particular interrupt (level or edge). An interrupt's
* type can be set by calling esprv_intc_int_set_type(). * type can be set by calling esprv_int_set_type().
* *
* @param intr_num Interrupt number * @param intr_num Interrupt number
* @return Interrupt type * @return Interrupt type
*/ */
enum intr_type esprv_intc_int_get_type(int intr_num); enum intr_type esprv_int_get_type(int intr_num);
/** /**
* Set interrupt priority in the interrupt controller * Set interrupt priority in the interrupt controller
* @param rv_int_num CPU interrupt number * @param rv_int_num CPU interrupt number
* @param priority Interrupt priority level, 1 to 7 * @param priority Interrupt priority level, 1 to 7
*/ */
void esprv_intc_int_set_priority(int rv_int_num, int priority); void esprv_int_set_priority(int rv_int_num, int priority);
/** /**
* @brief Get the current priority of an interrupt * @brief Get the current priority of an interrupt
@@ -109,7 +110,7 @@ void esprv_intc_int_set_priority(int rv_int_num, int priority);
* @param rv_int_num CPU interrupt number * @param rv_int_num CPU interrupt number
* @return Interrupt priority level, 1 to 7 * @return Interrupt priority level, 1 to 7
*/ */
int esprv_intc_int_get_priority(int rv_int_num); int esprv_int_get_priority(int rv_int_num);
/** /**
* Set interrupt priority threshold. * Set interrupt priority threshold.
@@ -117,14 +118,14 @@ int esprv_intc_int_get_priority(int rv_int_num);
* *
* @param priority_threshold Interrupt priority threshold, 0 to 7 * @param priority_threshold Interrupt priority threshold, 0 to 7
*/ */
void esprv_intc_int_set_threshold(int priority_threshold); void esprv_int_set_threshold(int priority_threshold);
/** /**
* @brief Get interrupt unmask * @brief Get interrupt unmask
* @param none * @param none
* @return uint32_t interrupt unmask * @return uint32_t interrupt unmask
*/ */
uint32_t esprv_intc_get_interrupt_unmask(void); uint32_t esprv_get_interrupt_unmask(void);
/** /**
* @brief Check if the given interrupt is hardware vectored * @brief Check if the given interrupt is hardware vectored
@@ -133,7 +134,7 @@ uint32_t esprv_intc_get_interrupt_unmask(void);
* *
* @return true if the interrupt is vectored, false if it is not. * @return true if the interrupt is vectored, false if it is not.
*/ */
bool esprv_intc_int_is_vectored(int rv_int_num); bool esprv_int_is_vectored(int rv_int_num);
/** /**
* @brief Set interrupt vectored * @brief Set interrupt vectored
@@ -143,7 +144,13 @@ bool esprv_intc_int_is_vectored(int rv_int_num);
* @param rv_int_num Interrupt number * @param rv_int_num Interrupt number
* @param vectored True to set it to vectored, false to set it to non-vectored * @param vectored True to set it to vectored, false to set it to non-vectored
*/ */
void esprv_intc_int_set_vectored(int rv_int_num, bool vectored); void esprv_int_set_vectored(int rv_int_num, bool vectored);
/**
* Include the deprecated functions last since they will alias the functions declared above
*/
#include "esp_private/interrupt_deprecated.h"
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -159,7 +159,7 @@ FORCE_INLINE_ATTR void rv_utils_intr_enable(uint32_t intr_mask)
{ {
// Disable all interrupts to make updating of the interrupt mask atomic. // Disable all interrupts to make updating of the interrupt mask atomic.
unsigned old_mstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE); unsigned old_mstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE);
esprv_intc_int_enable(intr_mask); esprv_int_enable(intr_mask);
RV_SET_CSR(mstatus, old_mstatus & MSTATUS_MIE); RV_SET_CSR(mstatus, old_mstatus & MSTATUS_MIE);
} }
@@ -167,7 +167,7 @@ FORCE_INLINE_ATTR void rv_utils_intr_disable(uint32_t intr_mask)
{ {
// Disable all interrupts to make updating of the interrupt mask atomic. // Disable all interrupts to make updating of the interrupt mask atomic.
unsigned old_mstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE); unsigned old_mstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE);
esprv_intc_int_disable(intr_mask); esprv_int_disable(intr_mask);
RV_SET_CSR(mstatus, old_mstatus & MSTATUS_MIE); RV_SET_CSR(mstatus, old_mstatus & MSTATUS_MIE);
} }

View File

@@ -1,48 +1,15 @@
/* /*
* SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
#include <assert.h>
#include "soc/soc.h" #include "soc/soc.h"
#include "riscv/interrupt.h" #include "riscv/interrupt.h"
#include "soc/interrupt_reg.h"
#include "riscv/csr.h"
#include "esp_attr.h"
#include "riscv/rv_utils.h" #include "riscv/rv_utils.h"
#if SOC_INT_CLIC_SUPPORTED
/**
* If the target is using the CLIC as the interrupt controller, we have 32 external interrupt lines and 16 internal
* lines. Let's consider the internal ones reserved and not mappable to any handler.
*/
#define RV_EXTERNAL_INT_COUNT 32
#define RV_EXTERNAL_INT_OFFSET (CLIC_EXT_INTR_NUM_OFFSET)
#else // !SOC_INT_CLIC_SUPPORTED
/**
* In the case of INTC, all the interrupt lines are dedicated to external peripherals, so the offset is 0.
* In the case of PLIC, the reserved interrupts are not contiguous, moreover, they are already marked as
* unusable by the interrupt allocator, so the offset can also be 0 here.
*/
#define RV_EXTERNAL_INT_COUNT 32
#define RV_EXTERNAL_INT_OFFSET 0
/* Since DR_REG_INTERRUPT_CORE0_BASE is not defined on some single-core targets, use the former
* DR_REG_INTERRUPT_BASE macro instead. */
#ifndef DR_REG_INTERRUPT_CORE0_BASE
#define DR_REG_INTERRUPT_CORE0_BASE DR_REG_INTERRUPT_BASE
#endif // DR_REG_INTERRUPT_CORE0_BASE
#endif // SOC_INT_CLIC_SUPPORTED
typedef struct { typedef struct {
intr_handler_t handler; intr_handler_t handler;
void *arg; void *arg;
@@ -51,15 +18,6 @@ typedef struct {
static intr_handler_item_t s_intr_handlers[SOC_CPU_CORES_NUM][RV_EXTERNAL_INT_COUNT]; static intr_handler_item_t s_intr_handlers[SOC_CPU_CORES_NUM][RV_EXTERNAL_INT_COUNT];
static inline void assert_valid_rv_int_num(int rv_int_num)
{
#if !SOC_INT_CLIC_SUPPORTED
assert(rv_int_num != 0 && "Invalid CPU interrupt number");
#endif
assert(rv_int_num < RV_EXTERNAL_INT_COUNT && "Invalid CPU interrupt number");
}
static intr_handler_item_t* intr_get_item(int int_no) static intr_handler_item_t* intr_get_item(int int_no)
{ {
assert_valid_rv_int_num(int_no); assert_valid_rv_int_num(int_no);
@@ -106,77 +64,6 @@ void _global_interrupt_handler(intptr_t sp, int mcause)
} }
} }
/*************************** RISC-V interrupt enable/disable ***************************/
void intr_matrix_route(int intr_src, int intr_num)
{
assert_valid_rv_int_num(intr_num);
if (rv_utils_get_core_id() == 0) {
REG_WRITE(DR_REG_INTERRUPT_CORE0_BASE + 4 * intr_src, intr_num + RV_EXTERNAL_INT_OFFSET);
}
#if SOC_CPU_CORES_NUM > 1
else {
REG_WRITE(DR_REG_INTERRUPT_CORE1_BASE + 4 * intr_src, intr_num + RV_EXTERNAL_INT_OFFSET);
}
#endif // SOC_CPU_CORES_NUM > 1
}
// CLIC for each interrupt line provides a IE register
// this api is not used
#if !SOC_INT_CLIC_SUPPORTED
uint32_t esprv_intc_get_interrupt_unmask(void)
{
return REG_READ(INTERRUPT_CORE0_CPU_INT_ENABLE_REG);
}
#endif
/*************************** ESP-RV Interrupt Controller ***************************/
#if SOC_INT_CLIC_SUPPORTED
enum intr_type esprv_intc_int_get_type(int rv_int_num)
{
uint32_t intr_type_reg = REG_GET_FIELD(CLIC_INT_CTRL_REG(rv_int_num + RV_EXTERNAL_INT_OFFSET), CLIC_INT_ATTR_TRIG);
return (intr_type_reg & 1) ? INTR_TYPE_EDGE : INTR_TYPE_LEVEL;
}
int esprv_intc_int_get_priority(int rv_int_num)
{
uint32_t intr_priority_reg = REG_GET_FIELD(CLIC_INT_CTRL_REG(rv_int_num + RV_EXTERNAL_INT_OFFSET), CLIC_INT_CTL);
return (intr_priority_reg >> (8 - NLBITS));
}
bool esprv_intc_int_is_vectored(int rv_int_num)
{
const uint32_t shv = REG_GET_FIELD(CLIC_INT_CTRL_REG(rv_int_num + RV_EXTERNAL_INT_OFFSET), CLIC_INT_ATTR_SHV);
return shv != 0;
}
void esprv_intc_int_set_vectored(int rv_int_num, bool vectored)
{
REG_SET_FIELD(CLIC_INT_CTRL_REG(rv_int_num + RV_EXTERNAL_INT_OFFSET), CLIC_INT_ATTR_SHV, vectored ? 1 : 0);
}
#else // !SOC_INT_CLIC_SUPPORTED
enum intr_type esprv_intc_int_get_type(int rv_int_num)
{
uint32_t intr_type_reg = REG_READ(INTERRUPT_CORE0_CPU_INT_TYPE_REG);
return (intr_type_reg & (1 << rv_int_num)) ? INTR_TYPE_EDGE : INTR_TYPE_LEVEL;
}
int esprv_intc_int_get_priority(int rv_int_num)
{
uint32_t intr_priority_reg = REG_READ(INTC_INT_PRIO_REG(rv_int_num));
return intr_priority_reg;
}
#endif // SOC_INT_CLIC_SUPPORTED
/*************************** Exception names. Used in .gdbinit file. ***************************/ /*************************** Exception names. Used in .gdbinit file. ***************************/
const char *riscv_excp_names[16] __attribute__((used)) = { const char *riscv_excp_names[16] __attribute__((used)) = {

View File

@@ -0,0 +1,42 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include "riscv/rv_utils.h"
#include "hal/interrupt_clic_ll.h"
#include "esp_private/interrupt_clic.h"
void intr_matrix_route(int intr_src, int intr_num)
{
assert_valid_rv_int_num(intr_num);
const int core_id = rv_utils_get_core_id();
interrupt_clic_ll_route(core_id, intr_src, intr_num + RV_EXTERNAL_INT_OFFSET);
}
enum intr_type esprv_int_get_type(int rv_int_num)
{
return interrupt_clic_ll_get_type(rv_int_num + RV_EXTERNAL_INT_OFFSET) ? INTR_TYPE_EDGE : INTR_TYPE_LEVEL;
}
int esprv_int_get_priority(int rv_int_num)
{
return interrupt_clic_ll_get_priority(rv_int_num + RV_EXTERNAL_INT_OFFSET);
}
bool esprv_int_is_vectored(int rv_int_num)
{
return interrupt_clic_ll_is_vectored(rv_int_num + RV_EXTERNAL_INT_OFFSET);
}
void esprv_int_set_vectored(int rv_int_num, bool vectored)
{
interrupt_clic_ll_set_vectored(rv_int_num + RV_EXTERNAL_INT_OFFSET, vectored);
}

View File

@@ -0,0 +1,40 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include "riscv/interrupt.h"
#include "esp_private/interrupt_intc.h"
#include "hal/interrupt_intc_ll.h"
void intr_matrix_route(int intr_src, int intr_num)
{
assert_valid_rv_int_num(intr_num);
interrupt_intc_ll_route(intr_src, intr_num);
}
uint32_t esprv_get_interrupt_unmask(void)
{
return interrupt_intc_ll_get_unmask();
}
enum intr_type esprv_int_get_type(int rv_int_num)
{
return interrupt_intc_ll_get_type(rv_int_num) ? INTR_TYPE_EDGE : INTR_TYPE_LEVEL;
}
int esprv_int_get_priority(int rv_int_num)
{
return interrupt_intc_ll_get_priority(rv_int_num);
}
bool esprv_int_is_vectored(int rv_int_num)
{
return true;
}

View File

@@ -0,0 +1,40 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdbool.h>
#include "riscv/interrupt.h"
#include "esp_private/interrupt_plic.h"
#include "hal/interrupt_plic_ll.h"
void intr_matrix_route(int intr_src, int intr_num)
{
assert_valid_rv_int_num(intr_num);
interrupt_plic_ll_route(intr_src, intr_num);
}
uint32_t esprv_get_interrupt_unmask(void)
{
return interrupt_plic_ll_get_unmask();
}
enum intr_type esprv_int_get_type(int rv_int_num)
{
return interrupt_plic_ll_get_type(rv_int_num) ? INTR_TYPE_EDGE : INTR_TYPE_LEVEL;
}
int esprv_int_get_priority(int rv_int_num)
{
return interrupt_plic_ll_get_priority(rv_int_num);
}
bool esprv_int_is_vectored(int rv_int_num)
{
return true;
}

View File

@@ -0,0 +1,12 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/* The interrupt API functions are implemented in ROM under the deprecated names, define the aliases */
PROVIDE ( esprv_int_set_priority = esprv_intc_int_set_priority );
PROVIDE ( esprv_int_set_threshold = esprv_intc_int_set_threshold );
PROVIDE ( esprv_int_enable = esprv_intc_int_enable );
PROVIDE ( esprv_int_disable = esprv_intc_int_disable );
PROVIDE ( esprv_int_set_type = esprv_intc_int_set_type );

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2017-2023 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -316,9 +316,9 @@ _interrupt_handler:
li t2, VECTORS_MCAUSE_REASON_MASK li t2, VECTORS_MCAUSE_REASON_MASK
and t1, s1, t2 /* t1 = mcause & mask */ and t1, s1, t2 /* t1 = mcause & mask */
slli t1, t1, 2 /* t1 = mcause * 4 */ slli t1, t1, 2 /* t1 = mcause * 4 */
li t2, INTC_INT_PRIO_REG(0) li t2, INTERRUPT_PRIO_REG(0)
add t1, t2, t1 /* t1 = INTC_INT_PRIO_REG + 4 * mcause */ add t1, t2, t1 /* t1 = INTERRUPT_PRIO_REG + 4 * mcause */
lw t2, 0(t1) /* t2 = INTC_INT_PRIO_REG[mcause] */ lw t2, 0(t1) /* t2 = INTERRUPT_PRIO_REG[mcause] */
addi t2, t2, 1 /* t2 = t2 +1 */ addi t2, t2, 1 /* t2 = t2 +1 */
sw t2, 0(t0) /* INTERRUPT_CURRENT_CORE_INT_THRESH_REG = t2 */ sw t2, 0(t0) /* INTERRUPT_CURRENT_CORE_INT_THRESH_REG = t2 */
fence fence

View File

@@ -3,6 +3,9 @@
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
#pragma once
#include "interrupt_core0_reg.h" #include "interrupt_core0_reg.h"
#define INTERRUPT_CURRENT_CORE_INT_THRESH_REG INTERRUPT_CORE0_CPU_INT_THRESH_REG #define INTERRUPT_CURRENT_CORE_INT_THRESH_REG INTERRUPT_CORE0_CPU_INT_THRESH_REG
#define INTERRUPT_PRIO_REG(n) (INTERRUPT_CORE0_CPU_INT_PRI_0_REG + (n)*4)

View File

@@ -3,6 +3,9 @@
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
#pragma once
#include "interrupt_core0_reg.h" #include "interrupt_core0_reg.h"
#define INTERRUPT_CURRENT_CORE_INT_THRESH_REG INTERRUPT_CORE0_CPU_INT_THRESH_REG #define INTERRUPT_CURRENT_CORE_INT_THRESH_REG INTERRUPT_CORE0_CPU_INT_THRESH_REG
#define INTERRUPT_PRIO_REG(n) (INTERRUPT_CORE0_CPU_INT_PRI_0_REG + (n)*4)

View File

@@ -1,22 +1,25 @@
/* /*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
#include "soc/reg_base.h"
#include "soc/interrupt_matrix_reg.h"
#include "soc/clic_reg.h" #include "soc/clic_reg.h"
#include "soc/soc_caps.h" #include "soc/soc_caps.h"
#ifdef __cplusplus
extern "C" {
#endif
/** /**
* ESP32C5 uses the CLIC controller as the interrupt controller (SOC_INT_CLIC_SUPPORTED = y) * ESP32C5 uses the CLIC controller as the interrupt controller (SOC_INT_CLIC_SUPPORTED = y)
*
* The memory map for interrupt registers is on a per-core basis, CLIC_INT_THRESH_REG points to
* the current core interrupt register, whereas CLIC_INT_THRESH_REG + DUALCORE_CLIC_CTRL_OFF points
* to the other core registers, regardless of the core we are currently running on.
*/ */
#define INTERRUPT_CURRENT_CORE_INT_THRESH_REG (CLIC_INT_THRESH_REG) #define INTERRUPT_CURRENT_CORE_INT_THRESH_REG (CLIC_INT_THRESH_REG)
#define INTERRUPT_OTHER_CORE_INT_THRESH_REG (CLIC_INT_THRESH_REG + DUALCORE_CLIC_CTRL_OFF) #define INTERRUPT_OTHER_CORE_INT_THRESH_REG (CLIC_INT_THRESH_REG + DUALCORE_CLIC_CTRL_OFF)
#define INTERRUPT_CORE0_CPU_INT_THRESH_REG INTERRUPT_CURRENT_CORE_INT_THRESH_REG #define INTERRUPT_CORE0_CPU_INT_THRESH_REG INTERRUPT_CURRENT_CORE_INT_THRESH_REG
#ifdef __cplusplus
}
#endif

View File

@@ -1,20 +1,25 @@
/* /*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
#pragma once
#include "soc/interrupt_matrix_reg.h" #include "soc/interrupt_matrix_reg.h"
#include "soc/intpri_reg.h" #include "soc/intpri_reg.h"
#include "soc/plic_reg.h" #include "soc/plic_reg.h"
#include "soc/soc_caps.h" #include "soc/soc_caps.h"
// ESP32C6 should use the PLIC controller as the interrupt controller instead of INTC (SOC_INT_PLIC_SUPPORTED = y) #define INTERRUPT_PRIO_REG(n) (PLIC_MXINT0_PRI_REG + (n)*4)
#define INTERRUPT_CURRENT_CORE_INT_THRESH_REG INTERRUPT_CORE0_CPU_INT_THRESH_REG #define INTERRUPT_CURRENT_CORE_INT_THRESH_REG PLIC_MXINT_THRESH_REG
#define INTERRUPT_CORE0_CPU_INT_ENABLE_REG PLIC_MXINT_ENABLE_REG
#define INTERRUPT_CORE0_CPU_INT_THRESH_REG PLIC_MXINT_THRESH_REG
#define INTERRUPT_CORE0_CPU_INT_CLEAR_REG PLIC_MXINT_CLEAR_REG
#define INTERRUPT_CORE0_CPU_INT_TYPE_REG PLIC_MXINT_TYPE_REG
#define INTC_INT_PRIO_REG(n) (PLIC_MXINT0_PRI_REG + (n)*4)
#define DR_REG_INTERRUPT_BASE DR_REG_INTERRUPT_MATRIX_BASE /**
* ESP32C6 should use the PLIC controller as the interrupt controller instead of INTC (SOC_INT_PLIC_SUPPORTED = y)
* Keep the following macros for backward compatibility reasons
*/
#define INTERRUPT_CORE0_CPU_INT_ENABLE_REG PLIC_MXINT_ENABLE_REG
#define INTERRUPT_CORE0_CPU_INT_THRESH_REG PLIC_MXINT_THRESH_REG
#define INTERRUPT_CORE0_CPU_INT_CLEAR_REG PLIC_MXINT_CLEAR_REG
#define INTERRUPT_CORE0_CPU_INT_TYPE_REG PLIC_MXINT_TYPE_REG
#define INTC_INT_PRIO_REG(n) (PLIC_MXINT0_PRI_REG + (n)*4)
#define DR_REG_INTERRUPT_BASE DR_REG_INTERRUPT_MATRIX_BASE

View File

@@ -1,18 +1,24 @@
/* /*
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
#pragma once
#include "interrupt_matrix_reg.h" #include "interrupt_matrix_reg.h"
#include "plic_reg.h" #include "plic_reg.h"
#include "soc/soc_caps.h" #include "soc/soc_caps.h"
// ESP32H2 should use the PLIC controller as the interrupt controller instead of INTC (SOC_INT_PLIC_SUPPORTED = y) #define INTERRUPT_PRIO_REG(n) (PLIC_MXINT0_PRI_REG + (n)*4)
#define INTERRUPT_CURRENT_CORE_INT_THRESH_REG INTERRUPT_CORE0_CPU_INT_THRESH_REG #define INTERRUPT_CURRENT_CORE_INT_THRESH_REG PLIC_MXINT_THRESH_REG
#define INTERRUPT_CORE0_CPU_INT_ENABLE_REG PLIC_MXINT_ENABLE_REG
#define INTERRUPT_CORE0_CPU_INT_THRESH_REG PLIC_MXINT_THRESH_REG /**
#define INTERRUPT_CORE0_CPU_INT_CLEAR_REG PLIC_MXINT_CLEAR_REG * ESP32H2 should use the PLIC controller as the interrupt controller instead of INTC (SOC_INT_PLIC_SUPPORTED = y)
#define INTERRUPT_CORE0_CPU_INT_TYPE_REG PLIC_MXINT_TYPE_REG * Keep the following macros for backward compatibility reasons
#define INTC_INT_PRIO_REG(n) (PLIC_MXINT0_PRI_REG + (n)*4) */
#define DR_REG_INTERRUPT_BASE DR_REG_INTERRUPT_MATRIX_BASE #define INTERRUPT_CORE0_CPU_INT_ENABLE_REG PLIC_MXINT_ENABLE_REG
#define INTERRUPT_CORE0_CPU_INT_THRESH_REG PLIC_MXINT_THRESH_REG
#define INTERRUPT_CORE0_CPU_INT_CLEAR_REG PLIC_MXINT_CLEAR_REG
#define INTERRUPT_CORE0_CPU_INT_TYPE_REG PLIC_MXINT_TYPE_REG
#define INTC_INT_PRIO_REG(n) (PLIC_MXINT0_PRI_REG + (n)*4)
#define DR_REG_INTERRUPT_BASE DR_REG_INTERRUPT_MATRIX_BASE

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -22,9 +22,8 @@ extern "C" {
#define INTERRUPT_CURRENT_CORE_INT_THRESH_REG (CLIC_INT_THRESH_REG) #define INTERRUPT_CURRENT_CORE_INT_THRESH_REG (CLIC_INT_THRESH_REG)
#define INTERRUPT_OTHER_CORE_INT_THRESH_REG (CLIC_INT_THRESH_REG + DUALCORE_CLIC_CTRL_OFF) #define INTERRUPT_OTHER_CORE_INT_THRESH_REG (CLIC_INT_THRESH_REG + DUALCORE_CLIC_CTRL_OFF)
#define INTERRUPT_CORE0_CPU_INT_THRESH_REG (rv_utils_get_core_id() == 0 ? INTERRUPT_CURRENT_CORE_INT_THRESH_REG : INTERRUPT_OTHER_CORE_INT_THRESH_REG)
#define INTERRUPT_CORE0_CPU_INT_THRESH_REG (rv_utils_get_core_id() == 0 ? INTERRUPT_CURRENT_CORE_INT_THRESH_REG : INTERRUPT_OTHER_CORE_INT_THRESH_REG) #define INTERRUPT_CORE1_CPU_INT_THRESH_REG (rv_utils_get_core_id() == 1 ? INTERRUPT_CURRENT_CORE_INT_THRESH_REG : INTERRUPT_OTHER_CORE_INT_THRESH_REG)
#define INTERRUPT_CORE1_CPU_INT_THRESH_REG (rv_utils_get_core_id() == 1 ? INTERRUPT_CURRENT_CORE_INT_THRESH_REG : INTERRUPT_OTHER_CORE_INT_THRESH_REG)
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -6,6 +6,7 @@
#pragma once #pragma once
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
#include "soc/soc_caps.h" #include "soc/soc_caps.h"
#include "xtensa/config/core-isa.h" #include "xtensa/config/core-isa.h"
#include "xtensa/config/core.h" #include "xtensa/config/core.h"