kopia lustrzana https://github.com/espressif/esp-idf
fix(esp32p4): Fixed interrupt handling to use the CLIC controller
rodzic
eb8883cc20
commit
8ca191e4c1
|
@ -156,21 +156,32 @@ void esp_cpu_wait_for_intr(void)
|
|||
|
||||
#if SOC_CPU_HAS_FLEXIBLE_INTC
|
||||
|
||||
|
||||
#if SOC_INT_CLIC_SUPPORTED
|
||||
|
||||
static bool is_intr_num_resv(int ext_intr_num) {
|
||||
/* On targets that uses CLIC as the interrupt controller, the first 16 lines (0..15) are reserved for software
|
||||
* interrupts, all the other lines starting from 16 and above can be used by external peripheral.
|
||||
* in the case of this function, the parameter only refers to the external peripheral index, so if
|
||||
* `ext_intr_num` is 0, it refers to interrupt index 16.
|
||||
*
|
||||
* Only interrupt line 6 is reserved at the moment since it is used for disabling interrupts */
|
||||
return ext_intr_num == 6;
|
||||
}
|
||||
|
||||
#else // !SOC_INT_CLIC_SUPPORTED
|
||||
|
||||
static bool is_intr_num_resv(int intr_num)
|
||||
{
|
||||
// Workaround to reserve interrupt number 1 for Wi-Fi, 5,8 for Bluetooth, 6 for "permanently disabled interrupt"
|
||||
// [TODO: IDF-2465]
|
||||
uint32_t reserved = BIT(1) | BIT(5) | BIT(6) | BIT(8);
|
||||
|
||||
// int_num 0,3,4,7 are inavaliable for PULP cpu
|
||||
// int_num 0,3,4,7 are unavailable for PULP cpu
|
||||
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2// TODO: IDF-5728 replace with a better macro name
|
||||
reserved |= BIT(0) | BIT(3) | BIT(4) | BIT(7);
|
||||
#endif
|
||||
|
||||
#if SOC_INT_CLIC_SUPPORTED
|
||||
//TODO: IDF-7795
|
||||
return false;
|
||||
#endif
|
||||
if (reserved & BIT(intr_num)) {
|
||||
return true;
|
||||
}
|
||||
|
@ -185,6 +196,8 @@ static bool is_intr_num_resv(int intr_num)
|
|||
return destination != (intptr_t)&_interrupt_handler;
|
||||
}
|
||||
|
||||
#endif // SOC_INT_CLIC_SUPPORTED
|
||||
|
||||
void esp_cpu_intr_get_desc(int core_id, int intr_num, esp_cpu_intr_desc_t *intr_desc_ret)
|
||||
{
|
||||
intr_desc_ret->priority = 1; //Todo: We should make this -1
|
||||
|
|
|
@ -233,7 +233,7 @@ FORCE_INLINE_ATTR void esp_cpu_intr_set_ivt_addr(const void *ivt_addr)
|
|||
#endif
|
||||
}
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32P4
|
||||
#if SOC_INT_CLIC_SUPPORTED
|
||||
//TODO: IDF-7863
|
||||
//"MTVT is only implemented in RISC-V arch"
|
||||
/**
|
||||
|
@ -245,7 +245,7 @@ FORCE_INLINE_ATTR void esp_cpu_intr_set_mtvt_addr(const void *mtvt_addr)
|
|||
{
|
||||
rv_utils_set_mtvt((uint32_t)mtvt_addr);
|
||||
}
|
||||
#endif //#if CONFIG_IDF_TARGET_ESP32P4
|
||||
#endif //#if SOC_INT_CLIC_SUPPORTED
|
||||
|
||||
#if SOC_CPU_HAS_FLEXIBLE_INTC
|
||||
/**
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -30,6 +30,9 @@
|
|||
#include "esp_ipc.h"
|
||||
#endif
|
||||
|
||||
/* For targets that uses a CLIC as their interrupt controller, CPU_INT_LINES_COUNT represents the external interrupts count */
|
||||
#define CPU_INT_LINES_COUNT 32
|
||||
|
||||
static const char* TAG = "intr_alloc";
|
||||
|
||||
#define ETS_INTERNAL_TIMER0_INTR_NO 6
|
||||
|
@ -161,7 +164,7 @@ static vector_desc_t *get_desc_for_int(int intno, int cpu)
|
|||
}
|
||||
}
|
||||
|
||||
//Returns a vector_desc entry for an source, the cpu parameter is used to tell GPIO_INT and GPIO_NMI from different CPUs
|
||||
//Returns a vector_desc entry for a source, the cpu parameter is used to tell GPIO_INT and GPIO_NMI from different CPUs
|
||||
static vector_desc_t * find_desc_for_source(int source, int cpu)
|
||||
{
|
||||
vector_desc_t *vd = vector_desc_head;
|
||||
|
@ -326,11 +329,11 @@ static int get_available_int(int flags, int cpu, int force, int source)
|
|||
vector_desc_t *vd = find_desc_for_source(source, cpu);
|
||||
if (vd) {
|
||||
// if existing vd found, don't need to search any more.
|
||||
ALCHLOG("get_avalible_int: existing vd found. intno: %d", vd->intno);
|
||||
ALCHLOG("get_available_int: existing vd found. intno: %d", vd->intno);
|
||||
if ( force != -1 && force != vd->intno ) {
|
||||
ALCHLOG("get_avalible_int: intr forced but not matach existing. existing intno: %d, force: %d", vd->intno, force);
|
||||
ALCHLOG("get_available_int: intr forced but does not match existing. existing intno: %d, force: %d", vd->intno, force);
|
||||
} else if (!is_vect_desc_usable(vd, flags, cpu, force)) {
|
||||
ALCHLOG("get_avalible_int: existing vd invalid.");
|
||||
ALCHLOG("get_available_int: existing vd invalid.");
|
||||
} else {
|
||||
best = vd->intno;
|
||||
}
|
||||
|
@ -348,14 +351,14 @@ static int get_available_int(int flags, int cpu, int force, int source)
|
|||
if (is_vect_desc_usable(vd, flags, cpu, force)) {
|
||||
best = vd->intno;
|
||||
} else {
|
||||
ALCHLOG("get_avalible_int: forced vd invalid.");
|
||||
ALCHLOG("get_avalaible_int: forced vd invalid.");
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
ALCHLOG("get_free_int: start looking. Current cpu: %d", cpu);
|
||||
//No allocated handlers as well as forced intr, iterate over the 32 possible interrupts
|
||||
for (x = 0; x < 32; x++) {
|
||||
/* No allocated handlers as well as forced intr, iterate over the 32 possible interrupts */
|
||||
for (x = 0; x < CPU_INT_LINES_COUNT; x++) {
|
||||
//Grab the vector_desc for this vector.
|
||||
vd = find_desc_for_int(x, cpu);
|
||||
if (vd == NULL) {
|
||||
|
@ -811,12 +814,13 @@ esp_err_t IRAM_ATTR esp_intr_enable(intr_handle_t handle)
|
|||
|
||||
esp_err_t IRAM_ATTR esp_intr_disable(intr_handle_t handle)
|
||||
{
|
||||
if (!handle) {
|
||||
if (handle == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
portENTER_CRITICAL_SAFE(&spinlock);
|
||||
int source;
|
||||
bool disabled = 1;
|
||||
bool disabled = true;
|
||||
if (handle->shared_vector_desc) {
|
||||
handle->shared_vector_desc->disabled = 1;
|
||||
source=handle->shared_vector_desc->source;
|
||||
|
@ -824,8 +828,8 @@ esp_err_t IRAM_ATTR esp_intr_disable(intr_handle_t handle)
|
|||
shared_vector_desc_t *svd = handle->vector_desc->shared_vec_info;
|
||||
assert(svd != NULL);
|
||||
while(svd) {
|
||||
if (svd->source == source && svd->disabled == 0) {
|
||||
disabled = 0;
|
||||
if (svd->source == source && !svd->disabled) {
|
||||
disabled = false;
|
||||
break;
|
||||
}
|
||||
svd = svd->next;
|
||||
|
@ -924,7 +928,7 @@ esp_err_t esp_intr_dump(FILE *stream)
|
|||
for (int cpu = 0; cpu < cpu_num; ++cpu) {
|
||||
fprintf(stream, "CPU %d interrupt status:\n", cpu);
|
||||
fprintf(stream, " Int Level Type Status\n");
|
||||
for (int i_num = 0; i_num < 32; ++i_num) {
|
||||
for (int i_num = 0; i_num < CPU_INT_LINES_COUNT; ++i_num) {
|
||||
fprintf(stream, " %2d ", i_num);
|
||||
esp_cpu_intr_desc_t intr_desc;
|
||||
esp_cpu_intr_get_desc(cpu, i_num, &intr_desc);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2010-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -76,12 +76,14 @@ soc_reset_reason_t esp_rom_get_reset_reason(int cpu_no);
|
|||
* Usually there're 4 steps to use an interrupt:
|
||||
* 1. Route peripheral interrupt source to CPU. e.g. esp_rom_route_intr_matrix(0, ETS_WIFI_MAC_INTR_SOURCE, ETS_WMAC_INUM)
|
||||
* 2. Set interrupt handler for CPU
|
||||
* 3. Enable CPU interupt
|
||||
* 3. Enable CPU interrupt
|
||||
* 4. Enable peripheral interrupt
|
||||
*
|
||||
* @param cpu_core The CPU number, which the peripheral interupt will inform to
|
||||
* @param cpu_core The CPU number, which the peripheral interrupt will inform to
|
||||
* @param periph_intr_id The peripheral interrupt source number
|
||||
* @param cpu_intr_num The CPU interrupt number
|
||||
* @param cpu_intr_num The CPU (external) interrupt number. On targets that use CLIC as their interrupt controller,
|
||||
* this number represents the external interrupt number. For example, passing `cpu_intr_num = i`
|
||||
* to this function would in fact bind peripheral source to CPU interrupt `CLIC_EXT_INTR_NUM_OFFSET + i`.
|
||||
*/
|
||||
void esp_rom_route_intr_matrix(int cpu_core, uint32_t periph_intr_id, uint32_t cpu_intr_num);
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ SECTIONS
|
|||
_iram_start = ABSOLUTE(.);
|
||||
/* Vectors go to start of IRAM */
|
||||
ASSERT(ABSOLUTE(.) % 0x100 == 0, "vector address must be 256 byte aligned");
|
||||
KEEP(*(.exception_vectors_table.text));
|
||||
KEEP(*(.exception_vectors.text));
|
||||
. = ALIGN(4);
|
||||
|
||||
|
|
|
@ -145,6 +145,7 @@ SECTIONS
|
|||
_iram_start = ABSOLUTE(.);
|
||||
/* Vectors go to start of IRAM */
|
||||
ASSERT(ABSOLUTE(.) % 0x100 == 0, "vector address must be 256 byte aligned");
|
||||
KEEP(*(.exception_vectors_table.text));
|
||||
KEEP(*(.exception_vectors.text));
|
||||
. = ALIGN(4);
|
||||
|
||||
|
|
|
@ -147,6 +147,7 @@ SECTIONS
|
|||
_iram_start = ABSOLUTE(.);
|
||||
/* Vectors go to start of IRAM */
|
||||
ASSERT(ABSOLUTE(.) % 0x100 == 0, "vector address must be 256 byte aligned");
|
||||
KEEP(*(.exception_vectors_table.text));
|
||||
KEEP(*(.exception_vectors.text));
|
||||
. = ALIGN(4);
|
||||
|
||||
|
|
|
@ -147,6 +147,7 @@ SECTIONS
|
|||
_iram_start = ABSOLUTE(.);
|
||||
/* Vectors go to start of IRAM */
|
||||
ASSERT(ABSOLUTE(.) % 0x100 == 0, "vector address must be 256 byte aligned");
|
||||
KEEP(*(.exception_vectors_table.text));
|
||||
KEEP(*(.exception_vectors.text));
|
||||
. = ALIGN(4);
|
||||
|
||||
|
|
|
@ -167,7 +167,8 @@ SECTIONS
|
|||
{
|
||||
_iram_start = ABSOLUTE(.);
|
||||
/* Vectors go to start of IRAM */
|
||||
ASSERT(ABSOLUTE(.) % 0x100 == 0, "vector address must be 256 byte aligned");
|
||||
ASSERT(ABSOLUTE(.) % 0x40 == 0, "vector address must be 64 byte aligned");
|
||||
KEEP(*(.exception_vectors_table.text));
|
||||
KEEP(*(.exception_vectors.text));
|
||||
. = ALIGN(4);
|
||||
|
||||
|
|
|
@ -150,14 +150,22 @@ static void core_intr_matrix_clear(void)
|
|||
for (int i = 0; i < ETS_MAX_INTR_SOURCE; i++) {
|
||||
#if CONFIG_IDF_TARGET_ESP32P4
|
||||
if (core_id == 0) {
|
||||
REG_WRITE(INTERRUPT_CORE0_LP_RTC_INT_MAP_REG + 4 * i, 0);
|
||||
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, 0);
|
||||
REG_WRITE(INTERRUPT_CORE1_LP_RTC_INT_MAP_REG + 4 * i, ETS_INVALID_INUM);
|
||||
}
|
||||
#else
|
||||
esp_rom_route_intr_matrix(core_id, i, ETS_INVALID_INUM);
|
||||
#endif
|
||||
#endif // CONFIG_IDF_TARGET_ESP32P4
|
||||
}
|
||||
|
||||
#if SOC_INT_CLIC_SUPPORTED
|
||||
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 */
|
||||
esprv_intc_int_set_vectored(i, true);
|
||||
}
|
||||
#endif // SOC_INT_CLIC_SUPPORTED
|
||||
|
||||
}
|
||||
|
||||
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#pragma once
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
#include "sdkconfig.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
@ -35,24 +36,99 @@ uint32_t esp_hw_stack_guard_get_pc(void);
|
|||
#define ASSIST_DEBUG_CORE_0_SP_MIN_OFFSET (ASSIST_DEBUG_CORE_0_SP_MIN_REG - ASSIST_DEBUG_CORE_0_INTR_ENA_REG)
|
||||
#define ASSIST_DEBUG_CORE_0_SP_MAX_OFFSET (ASSIST_DEBUG_CORE_0_SP_MAX_REG - ASSIST_DEBUG_CORE_0_INTR_ENA_REG)
|
||||
|
||||
.macro ESP_HW_STACK_GUARD_SET_BOUNDS_CPU0
|
||||
lui t0, ASSIST_DEBUG_CORE_0_INTR_ENA_REG_IMM
|
||||
sw a0, ASSIST_DEBUG_CORE_0_SP_MIN_OFFSET(t0)
|
||||
sw a1, ASSIST_DEBUG_CORE_0_SP_MAX_OFFSET(t0)
|
||||
.macro ESP_HW_STACK_GUARD_SET_BOUNDS_CPU0 reg1
|
||||
lui \reg1, ASSIST_DEBUG_CORE_0_INTR_ENA_REG_IMM
|
||||
sw a0, ASSIST_DEBUG_CORE_0_SP_MIN_OFFSET(\reg1)
|
||||
sw a1, ASSIST_DEBUG_CORE_0_SP_MAX_OFFSET(\reg1)
|
||||
.endm
|
||||
|
||||
.macro ESP_HW_STACK_GUARD_MONITOR_STOP_CPU0
|
||||
lui t0, ASSIST_DEBUG_CORE_0_INTR_ENA_REG_IMM
|
||||
lw t1, 0(t0)
|
||||
andi t1, t1, ~ASSIST_DEBUG_SP_SPILL_BITS
|
||||
sw t1, 0(t0)
|
||||
.macro ESP_HW_STACK_GUARD_MONITOR_STOP_CPU0 reg1 reg2
|
||||
lui \reg1, ASSIST_DEBUG_CORE_0_INTR_ENA_REG_IMM
|
||||
lw \reg2, 0(\reg1)
|
||||
andi \reg2, \reg2, ~ASSIST_DEBUG_SP_SPILL_BITS
|
||||
sw \reg2, 0(\reg1)
|
||||
.endm
|
||||
|
||||
.macro ESP_HW_STACK_GUARD_MONITOR_START_CPU0
|
||||
lui t0, ASSIST_DEBUG_CORE_0_INTR_ENA_REG_IMM
|
||||
lw t1, 0(t0)
|
||||
ori t1, t1, ASSIST_DEBUG_SP_SPILL_BITS
|
||||
sw t1, 0(t0)
|
||||
.macro ESP_HW_STACK_GUARD_MONITOR_START_CPU0 reg1 reg2
|
||||
lui \reg1, ASSIST_DEBUG_CORE_0_INTR_ENA_REG_IMM
|
||||
lw \reg2, 0(\reg1)
|
||||
ori \reg2, \reg2, ASSIST_DEBUG_SP_SPILL_BITS
|
||||
sw \reg2, 0(\reg1)
|
||||
.endm
|
||||
|
||||
|
||||
#if SOC_CPU_CORES_NUM > 1
|
||||
|
||||
#define ASSIST_DEBUG_CORE_1_INTR_ENA_REG_IMM (ASSIST_DEBUG_CORE_1_INTR_ENA_REG >> 12)
|
||||
#define ASSIST_DEBUG_CORE_1_SP_MIN_OFFSET (ASSIST_DEBUG_CORE_1_SP_MIN_REG - ASSIST_DEBUG_CORE_1_INTR_ENA_REG)
|
||||
#define ASSIST_DEBUG_CORE_1_SP_MAX_OFFSET (ASSIST_DEBUG_CORE_1_SP_MAX_REG - ASSIST_DEBUG_CORE_1_INTR_ENA_REG)
|
||||
|
||||
.macro ESP_HW_STACK_GUARD_SET_BOUNDS_CPU1 reg1
|
||||
lui \reg1, ASSIST_DEBUG_CORE_1_INTR_ENA_REG_IMM
|
||||
sw a0, ASSIST_DEBUG_CORE_1_SP_MIN_OFFSET(\reg1)
|
||||
sw a1, ASSIST_DEBUG_CORE_1_SP_MAX_OFFSET(\reg1)
|
||||
.endm
|
||||
|
||||
.macro ESP_HW_STACK_GUARD_MONITOR_STOP_CPU1 reg1 reg2
|
||||
lui \reg1, ASSIST_DEBUG_CORE_1_INTR_ENA_REG_IMM
|
||||
lw \reg2, 0(\reg1)
|
||||
andi \reg2, \reg2, ~ASSIST_DEBUG_SP_SPILL_BITS
|
||||
sw \reg2, 0(\reg1)
|
||||
.endm
|
||||
|
||||
.macro ESP_HW_STACK_GUARD_MONITOR_START_CPU1 reg1 reg2
|
||||
lui \reg1, ASSIST_DEBUG_CORE_1_INTR_ENA_REG_IMM
|
||||
lw \reg2, 0(\reg1)
|
||||
ori \reg2, \reg2, ASSIST_DEBUG_SP_SPILL_BITS
|
||||
sw \reg2, 0(\reg1)
|
||||
.endm
|
||||
|
||||
.macro ESP_HW_STACK_GUARD_SET_BOUNDS_CUR_CORE reg1
|
||||
/* Check the current core ID */
|
||||
csrr \reg1, mhartid
|
||||
beqz \reg1, @1f
|
||||
/* Core 1 */
|
||||
ESP_HW_STACK_GUARD_SET_BOUNDS_CPU1 \reg1
|
||||
j 2f
|
||||
1:
|
||||
/* Core 0 */
|
||||
ESP_HW_STACK_GUARD_SET_BOUNDS_CPU0 \reg1
|
||||
2:
|
||||
.endm
|
||||
|
||||
.macro ESP_HW_STACK_GUARD_MONITOR_START_CUR_CORE reg1 reg2
|
||||
/* Check the current core ID */
|
||||
csrr \reg1, mhartid
|
||||
beqz \reg1, @1f
|
||||
/* Core 1 */
|
||||
ESP_HW_STACK_GUARD_MONITOR_START_CPU1 \reg1 \reg2
|
||||
j 2f
|
||||
1:
|
||||
/* Core 0 */
|
||||
ESP_HW_STACK_GUARD_MONITOR_START_CPU0 \reg1 \reg2
|
||||
2:
|
||||
.endm
|
||||
|
||||
.macro ESP_HW_STACK_GUARD_MONITOR_STOP_CUR_CORE reg1 reg2
|
||||
/* Check the current core ID */
|
||||
csrr \reg1, mhartid
|
||||
beqz \reg1, @1f
|
||||
/* Core 1 */
|
||||
ESP_HW_STACK_GUARD_MONITOR_STOP_CPU1 \reg1 \reg2
|
||||
j 2f
|
||||
1:
|
||||
/* Core 0 */
|
||||
ESP_HW_STACK_GUARD_MONITOR_STOP_CPU0 \reg1 \reg2
|
||||
2:
|
||||
.endm
|
||||
|
||||
#else // SOC_CPU_CORES_NUM <= 1
|
||||
|
||||
#define ESP_HW_STACK_GUARD_SET_BOUNDS_CUR_CORE ESP_HW_STACK_GUARD_SET_BOUNDS_CPU0
|
||||
#define ESP_HW_STACK_GUARD_MONITOR_START_CUR_CORE ESP_HW_STACK_GUARD_MONITOR_START_CPU0
|
||||
#define ESP_HW_STACK_GUARD_MONITOR_STOP_CUR_CORE ESP_HW_STACK_GUARD_MONITOR_STOP_CPU0
|
||||
|
||||
#endif // SOC_CPU_CORES_NUM > 1
|
||||
|
||||
|
||||
#endif // __ASSEMBLER__
|
||||
|
|
|
@ -49,8 +49,8 @@ rtos_int_enter:
|
|||
bne t4,zero, rtos_enter_end
|
||||
|
||||
#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD
|
||||
/* esp_hw_stack_guard_monitor_stop(); */
|
||||
ESP_HW_STACK_GUARD_MONITOR_STOP_CPU0
|
||||
/* esp_hw_stack_guard_monitor_stop(); pass the scratch registers */
|
||||
ESP_HW_STACK_GUARD_MONITOR_STOP_CUR_CORE a0 a1
|
||||
#endif /* CONFIG_ESP_SYSTEM_HW_STACK_GUARD */
|
||||
|
||||
/* Save current TCB and load the ISR stack */
|
||||
|
@ -62,9 +62,9 @@ rtos_int_enter:
|
|||
/* esp_hw_stack_guard_set_bounds(xIsrStack, xIsrStackTop); */
|
||||
la a0, xIsrStack
|
||||
mv a1, sp
|
||||
ESP_HW_STACK_GUARD_SET_BOUNDS_CPU0
|
||||
ESP_HW_STACK_GUARD_SET_BOUNDS_CUR_CORE a2
|
||||
/* esp_hw_stack_guard_monitor_start(); */
|
||||
ESP_HW_STACK_GUARD_MONITOR_START_CPU0
|
||||
ESP_HW_STACK_GUARD_MONITOR_START_CUR_CORE a0 a1
|
||||
#endif /* CONFIG_ESP_SYSTEM_HW_STACK_GUARD */
|
||||
|
||||
rtos_enter_end:
|
||||
|
@ -118,7 +118,7 @@ no_switch:
|
|||
|
||||
#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD
|
||||
/* esp_hw_stack_guard_monitor_stop(); */
|
||||
ESP_HW_STACK_GUARD_MONITOR_STOP_CPU0
|
||||
ESP_HW_STACK_GUARD_MONITOR_STOP_CUR_CORE a0 a1
|
||||
#endif /* CONFIG_ESP_SYSTEM_HW_STACK_GUARD */
|
||||
|
||||
/* Recover the stack of next task */
|
||||
|
@ -131,9 +131,9 @@ no_switch:
|
|||
*/
|
||||
lw a0, PORT_OFFSET_PX_STACK(t0)
|
||||
lw a1, PORT_OFFSET_PX_END_OF_STACK(t0)
|
||||
ESP_HW_STACK_GUARD_SET_BOUNDS_CPU0
|
||||
ESP_HW_STACK_GUARD_SET_BOUNDS_CUR_CORE a2
|
||||
/* esp_hw_stack_guard_monitor_start(); */
|
||||
ESP_HW_STACK_GUARD_MONITOR_START_CPU0
|
||||
ESP_HW_STACK_GUARD_MONITOR_START_CUR_CORE a0 a1
|
||||
#endif /* CONFIG_ESP_SYSTEM_HW_STACK_GUARD */
|
||||
|
||||
rtos_exit_end:
|
||||
|
|
|
@ -92,6 +92,10 @@ volatile UBaseType_t xPortSwitchFlag[portNUM_PROCESSORS] = {0};
|
|||
__attribute__((aligned(16))) StackType_t xIsrStack[portNUM_PROCESSORS][configISR_STACK_SIZE];
|
||||
StackType_t *xIsrStackTop[portNUM_PROCESSORS] = {0};
|
||||
|
||||
#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD
|
||||
StackType_t *xIsrStackBottom[portNUM_PROCESSORS] = {0};
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------ FreeRTOS Portable --------------------------------------------------
|
||||
* - Provides implementation for functions required by FreeRTOS
|
||||
* - Declared in portable.h
|
||||
|
@ -107,9 +111,12 @@ BaseType_t xPortStartScheduler(void)
|
|||
port_uxCriticalNesting[coreID] = 0;
|
||||
port_xSchedulerRunning[coreID] = 0;
|
||||
|
||||
/* Initialize ISR Stack top */
|
||||
/* Initialize ISR Stack(s) */
|
||||
for (int i = 0; i < portNUM_PROCESSORS; i++) {
|
||||
xIsrStackTop[i] = &xIsrStack[i][0] + (configISR_STACK_SIZE & (~((portPOINTER_SIZE_TYPE)portBYTE_ALIGNMENT_MASK)));
|
||||
#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD
|
||||
xIsrStackBottom[i] = &xIsrStack[i][0];
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Setup the hardware to generate the tick. */
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
.global vTaskSwitchContext
|
||||
.global xPortSwitchFlag
|
||||
#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD
|
||||
.global xIsrStack
|
||||
.global xIsrStackBottom
|
||||
.global port_offset_pxStack
|
||||
.global port_offset_pxEndOfStack
|
||||
.global esp_hw_stack_guard_monitor_stop
|
||||
|
@ -34,75 +34,73 @@
|
|||
* current task stack pointer and places it into the pxCurrentTCB.
|
||||
* It then loads the ISR stack into sp.
|
||||
* TODO: ISR nesting code improvements ?
|
||||
* In the routines below, let's use a0-a5 registers to let the compiler generate
|
||||
* 16-bit instructions.
|
||||
*/
|
||||
|
||||
.global rtos_int_enter
|
||||
.type rtos_int_enter, @function
|
||||
rtos_int_enter:
|
||||
#if CONFIG_IDF_TARGET_ESP32P4
|
||||
//TODO: IDF-7861
|
||||
/* preserve the return address */
|
||||
mv t1, ra
|
||||
mv t2, a0
|
||||
#endif
|
||||
|
||||
/* If the scheduler is not enabled, jump directly to the ISR handler */
|
||||
#if ( configNUM_CORES > 1 )
|
||||
csrr t6, mhartid /* t6 = coreID */
|
||||
slli t6, t6, 2 /* t6 = coreID * 4 */
|
||||
la t0, port_xSchedulerRunning /* t0 = &port_xSchedulerRunning */
|
||||
add t0, t0, t6 /* t0 = &port_xSchedulerRunning[coreID] */
|
||||
lw t0, (t0) /* t0 = port_xSchedulerRunning[coreID] */
|
||||
csrr a5, mhartid /* a5 = coreID */
|
||||
slli a5, a5, 2 /* a5 = coreID * 4 */
|
||||
la a0, port_xSchedulerRunning /* a0 = &port_xSchedulerRunning */
|
||||
add a0, a0, a5 /* a0 = &port_xSchedulerRunning[coreID] */
|
||||
lw a0, (a0) /* a0 = port_xSchedulerRunning[coreID] */
|
||||
#else
|
||||
lw t0, port_xSchedulerRunning /* t0 = port_xSchedulerRunning */
|
||||
#endif /* (configNUM_CORES > 1) */
|
||||
beq t0, zero, rtos_int_enter_end /* if (port_xSchedulerRunning[coreID] == 0) jump to rtos_int_enter_end */
|
||||
lw a0, port_xSchedulerRunning /* a0 = port_xSchedulerRunning */
|
||||
#endif /* ( configNUM_CORES > 1 ) */
|
||||
beqz a0, rtos_int_enter_end /* if (port_xSchedulerRunning[coreID] == 0) jump to rtos_int_enter_end */
|
||||
|
||||
/* Increment the ISR nesting count */
|
||||
la t3, port_uxInterruptNesting /* t3 = &port_usInterruptNesting */
|
||||
la a0, port_uxInterruptNesting /* a0 = &port_uxInterruptNesting */
|
||||
#if ( configNUM_CORES > 1 )
|
||||
add t3, t3, t6 /* t3 = &port_uxInterruptNesting[coreID] // t6 already contains coreID * 4 */
|
||||
add a0, a0, a5 /* a0 = &port_uxInterruptNesting[coreID] // a5 already contains coreID * 4 */
|
||||
#endif /* ( configNUM_CORES > 1 ) */
|
||||
lw t4, 0x0(t3) /* t4 = port_uxInterruptNesting[coreID] */
|
||||
addi t5, t4, 1 /* t5 = t4 + 1 */
|
||||
sw t5, 0x0(t3) /* port_uxInterruptNesting[coreID] = t5 */
|
||||
lw a1, 0(a0) /* a1 = port_uxInterruptNesting[coreID] */
|
||||
addi a2, a1, 1 /* a2 = a1 + 1 */
|
||||
sw a2, 0(a0) /* port_uxInterruptNesting[coreID] = a2 */
|
||||
|
||||
/* If we reached here from another low-prio ISR, i.e, port_uxInterruptNesting[coreID] > 0, then skip stack pushing to TCB */
|
||||
bne t4, zero, rtos_int_enter_end /* if (port_uxInterruptNesting[coreID] > 0) jump to rtos_int_enter_end */
|
||||
/* If we reached here from another low-priority ISR, i.e, port_uxInterruptNesting[coreID] > 0, then skip stack pushing to TCB */
|
||||
bnez a1, rtos_int_enter_end /* if (port_uxInterruptNesting[coreID] > 0) jump to rtos_int_enter_end */
|
||||
|
||||
#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD
|
||||
/* esp_hw_stack_guard_monitor_stop(); */
|
||||
ESP_HW_STACK_GUARD_MONITOR_STOP_CPU0
|
||||
/* esp_hw_stack_guard_monitor_stop(); pass the scratch registers */
|
||||
ESP_HW_STACK_GUARD_MONITOR_STOP_CUR_CORE a0 a1
|
||||
#endif /* CONFIG_ESP_SYSTEM_HW_STACK_GUARD */
|
||||
|
||||
/* Save the current sp in pxCurrentTCB[coreID] and load the ISR stack on to sp */
|
||||
#if ( configNUM_CORES > 1 )
|
||||
la t0, pxCurrentTCB /* t0 = &pxCurrentTCB */
|
||||
add t0, t0, t6 /* t0 = &pxCurrentTCB[coreID] // t6 already contains coreID * 4 */
|
||||
lw t0, (t0) /* t0 = pxCurrentTCB[coreID] */
|
||||
sw sp, 0x0(t0) /* pxCurrentTCB[coreID] = sp */
|
||||
la t0, xIsrStackTop /* t0 = &xIsrStackTop */
|
||||
add t0, t0, t6 /* t0 = &xIsrStackTop[coreID] // t6 already contains coreID * 4 */
|
||||
lw sp, 0x0(t0) /* sp = xIsrStackTop[coreID] */
|
||||
la a0, pxCurrentTCB /* a0 = &pxCurrentTCB */
|
||||
add a0, a0, a5 /* a0 = &pxCurrentTCB[coreID] // a5 already contains coreID * 4 */
|
||||
lw a0, (a0) /* a0 = pxCurrentTCB[coreID] */
|
||||
sw sp, 0(a0) /* pxCurrentTCB[coreID] = sp */
|
||||
la a0, xIsrStackTop /* a0 = &xIsrStackTop */
|
||||
add a0, a0, a5 /* a0 = &xIsrStackTop[coreID] // a5 already contains coreID * 4 */
|
||||
lw sp, (a0) /* sp = xIsrStackTop[coreID] */
|
||||
#else
|
||||
lw t0, pxCurrentTCB /* t0 = pxCurrentTCB */
|
||||
sw sp, 0x0(t0) /* pxCurrentTCB = sp */
|
||||
lw a0, pxCurrentTCB /* a0 = pxCurrentTCB */
|
||||
sw sp, 0(a0) /* pxCurrentTCB[0] = sp */
|
||||
lw sp, xIsrStackTop /* sp = xIsrStackTop */
|
||||
#endif /* ( configNUM_CORES > 1 ) */
|
||||
|
||||
#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD
|
||||
/* esp_hw_stack_guard_set_bounds(xIsrStack, xIsrStackTop); */
|
||||
la a0, xIsrStack
|
||||
/* Prepare the parameters for esp_hw_stack_guard_set_bounds(xIsrStackBottom, xIsrStackTop); */
|
||||
#if ( configNUM_CORES > 1 )
|
||||
/* Load the xIsrStack for the current core and set the new bounds */
|
||||
la a0, xIsrStackBottom
|
||||
add a0, a0, a5 /* a0 = &xIsrStackBottom[coreID] */
|
||||
lw a0, (a0) /* a0 = xIsrStackBottom[coreID] */
|
||||
#else
|
||||
lw a0, xIsrStackBottom
|
||||
#endif /* ( configNUM_CORES > 1 ) */
|
||||
mv a1, sp
|
||||
ESP_HW_STACK_GUARD_SET_BOUNDS_CPU0
|
||||
ESP_HW_STACK_GUARD_MONITOR_START_CPU0
|
||||
/* esp_hw_stack_guard_set_bounds(xIsrStackBottom[coreID], xIsrStackTop[coreID]);
|
||||
*/
|
||||
ESP_HW_STACK_GUARD_SET_BOUNDS_CUR_CORE a2
|
||||
ESP_HW_STACK_GUARD_MONITOR_START_CUR_CORE a0 a1
|
||||
#endif /* CONFIG_ESP_SYSTEM_HW_STACK_GUARD */
|
||||
|
||||
rtos_int_enter_end:
|
||||
#if CONFIG_IDF_TARGET_ESP32P4
|
||||
//TODO: IDF-7861
|
||||
mv ra, t1
|
||||
#endif
|
||||
ret
|
||||
|
||||
/**
|
||||
|
@ -111,98 +109,91 @@ rtos_int_enter_end:
|
|||
.global rtos_int_exit
|
||||
.type rtos_int_exit, @function
|
||||
rtos_int_exit:
|
||||
|
||||
/* Skip if the scheduler was not started */
|
||||
#if ( configNUM_CORES > 1 )
|
||||
csrr t1, mhartid /* t1 = coreID */
|
||||
slli t1, t1, 2 /* t1 = t1 * 4 */
|
||||
la t0, port_xSchedulerRunning /* t0 = &port_xSchedulerRunning */
|
||||
add t0, t0, t1 /* t0 = &port_xSchedulerRunning[coreID] */
|
||||
lw t0, (t0) /* t0 = port_xSchedulerRunning[coreID] */
|
||||
csrr a1, mhartid /* a1 = coreID */
|
||||
slli a1, a1, 2 /* a1 = a1 * 4 */
|
||||
la a0, port_xSchedulerRunning /* a0 = &port_xSchedulerRunning */
|
||||
add a0, a0, a1 /* a0 = &port_xSchedulerRunning[coreID] */
|
||||
lw a0, (a0) /* a0 = port_xSchedulerRunning[coreID] */
|
||||
#else
|
||||
lw t0, port_xSchedulerRunning /* t0 = port_xSchedulerRunning */
|
||||
lw a0, port_xSchedulerRunning /* a0 = port_xSchedulerRunning */
|
||||
#endif /* ( configNUM_CORES > 1 ) */
|
||||
beq t0, zero, rtos_int_exit_end /* if (port_uxSchewdulerRunning == 0) jump to rtos_int_exit_end */
|
||||
beqz a0, rtos_int_exit_end /* if (port_uxSchewdulerRunning == 0) jump to rtos_int_exit_end */
|
||||
|
||||
/* Decrement interrupt nesting counter */
|
||||
la t2, port_uxInterruptNesting /* t2 = &port_uxInterruptNesting */
|
||||
/* Update nesting interrupts counter */
|
||||
la a0, port_uxInterruptNesting /* a0 = &port_uxInterruptNesting */
|
||||
#if ( configNUM_CORES > 1 )
|
||||
add t2, t2, t1 /* t2 = &port_uxInterruptNesting[coreID] // t1 already contains coreID * 4 */
|
||||
#endif
|
||||
lw t3, 0x0(t2) /* t3 = port_uxInterruptNesting[coreID] */
|
||||
add a0, a0, a1 /* a0 = &port_uxInterruptNesting[coreID] // a1 already contains coreID * 4 */
|
||||
#endif /* ( configNUM_CORES > 1 ) */
|
||||
lw a2, 0(a0) /* a2 = port_uxInterruptNesting[coreID] */
|
||||
|
||||
/* If the interrupt nesting counter is already zero, then protect against underflow */
|
||||
beq t3, zero, isr_skip_decrement /* if (port_uxInterruptNesting[coreID] == 0) jump to isr_skip_decrement */
|
||||
addi t3, t3, -1 /* t3 = t3 - 1 */
|
||||
sw t3, 0x0(t2) /* port_uxInterruptNesting[coreID] = t3 */
|
||||
/* Already zero, protect against underflow */
|
||||
beqz a2, isr_skip_decrement /* if (port_uxInterruptNesting[coreID] == 0) jump to isr_skip_decrement */
|
||||
addi a2, a2, -1 /* a2 = a2 - 1 */
|
||||
sw a2, 0(a0) /* port_uxInterruptNesting[coreID] = a2 */
|
||||
/* May still have interrupts pending, skip section below and exit */
|
||||
bnez a2, rtos_int_exit_end
|
||||
|
||||
isr_skip_decrement:
|
||||
/* If the CPU reached this label, a2 (uxInterruptNesting) is 0 for sure */
|
||||
|
||||
/* We may still have interrupts pending. Skip the section below and exit */
|
||||
bne t3, zero, rtos_int_exit_end /* (if port_uxInterruptNesting[coreID] > 0) jump to rtos_int_exit_end */
|
||||
|
||||
/* Schedule the next task if an yield is pending */
|
||||
la t0, xPortSwitchFlag /* t0 = &xPortSwitchFlag */
|
||||
/* Schedule the next task if a yield is pending */
|
||||
la a0, xPortSwitchFlag /* a0 = &xPortSwitchFlag */
|
||||
#if ( configNUM_CORES > 1 )
|
||||
add t0, t0, t1 /* t0 = &xPortSwitchFlag[coreID] // t1 already contains coreID * 4 */
|
||||
add a0, a0, a1 /* a0 = &xPortSwitchFlag[coreID] // a1 already contains coreID * 4 */
|
||||
#endif /* ( configNUM_CORES > 1 ) */
|
||||
lw t2, 0x0(t0) /* t2 = xPortSwitchFlag[coreID] */
|
||||
beq t2, zero, no_switch /* if (xPortSwitchFlag[coreID] == 0) jump to no_switch */
|
||||
lw a2, 0(a0) /* a2 = xPortSwitchFlag[coreID] */
|
||||
beqz a2, no_switch /* if (xPortSwitchFlag[coreID] == 0) jump to no_switch */
|
||||
|
||||
/* Save the return address on the stack and create space on the stack for the c-routine call to schedule
|
||||
* the next task. Stack pointer for RISC-V should always be 16 byte aligned. After the switch, restore
|
||||
* the return address and sp.
|
||||
*/
|
||||
addi sp, sp, -16 /* sp = sp - 16 */
|
||||
sw ra, 0(sp) /* sp = ra */
|
||||
call vTaskSwitchContext /* vTaskSwitchContext() */
|
||||
lw ra, 0(sp) /* ra = sp */
|
||||
addi sp, sp, 16 /* sp = sp + 16 */
|
||||
/* Preserve return address and schedule next task. To speed up the process, instead of allocating stack
|
||||
* space, let's use a callee-saved register: s0. Since the caller is not using it, let's use it. */
|
||||
mv s0, ra
|
||||
call vTaskSwitchContext
|
||||
mv ra, s0
|
||||
|
||||
/* Clear the switch pending flag */
|
||||
la t0, xPortSwitchFlag /* t0 = &xPortSwitchFlag */
|
||||
/* Clears the switch pending flag */
|
||||
la a0, xPortSwitchFlag /* a0 = &xPortSwitchFlag */
|
||||
#if ( configNUM_CORES > 1 )
|
||||
/* c routine vTaskSwitchContext may change the temp registers, so we read again */
|
||||
csrr t3, mhartid /* t3 = coreID */
|
||||
slli t3, t3, 2 /* t3 = t3 * 4 */
|
||||
add t0, t0, t3 /* t0 = &xPortSwitchFlag[coreID] */
|
||||
/* C routine vTaskSwitchContext may change the temp registers, so we read again */
|
||||
csrr a1, mhartid /* a1 = coreID */
|
||||
slli a1, a1, 2 /* a1 = a1 * 4 */
|
||||
add a0, a0, a1 /* a0 = &xPortSwitchFlag[coreID]; */
|
||||
#endif /* ( configNUM_CORES > 1 ) */
|
||||
mv t2, zero /* t2 = 0 */
|
||||
sw t2, 0x0(t0) /* xPortSwitchFlag[coreID] = t2 */
|
||||
sw zero, 0(a0) /* xPortSwitchFlag[coreID] = 0; */
|
||||
|
||||
no_switch:
|
||||
|
||||
#if SOC_INT_CLIC_SUPPORTED
|
||||
/* Recover the stack of next task and prepare to exit */
|
||||
la a0, pxCurrentTCB /* a0 = &pxCurrentTCB */
|
||||
#if ( configNUM_CORES > 1 )
|
||||
csrr t3, mhartid /* t3 = coreID */
|
||||
slli t3, t3, 2 /* t3 = t3 * 4 */
|
||||
add a0, a0, t3 /* a0 = &pxCurrentTCB[coreID] */
|
||||
#endif /* ( configNUM_CORES > 1 ) */
|
||||
lw a0, (a0) /* a0 = pxCurrentTCB[coreID] */
|
||||
lw a0, 0x0(a0) /* a0 = previous sp */
|
||||
#else
|
||||
#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD
|
||||
/* esp_hw_stack_guard_monitor_stop(); */
|
||||
ESP_HW_STACK_GUARD_MONITOR_STOP_CPU0
|
||||
/* esp_hw_stack_guard_monitor_stop(); pass the scratch registers */
|
||||
ESP_HW_STACK_GUARD_MONITOR_STOP_CUR_CORE a0 a1
|
||||
#endif /* CONFIG_ESP_SYSTEM_HW_STACK_GUARD */
|
||||
|
||||
|
||||
#if ( configNUM_CORES > 1 )
|
||||
/* Recover the stack of next task and prepare to exit */
|
||||
csrr a1, mhartid
|
||||
slli a1, a1, 2
|
||||
la a0, pxCurrentTCB /* a0 = &pxCurrentTCB */
|
||||
add a0, a0, a1 /* a0 = &pxCurrentTCB[coreID] */
|
||||
lw a0, 0(a0) /* a0 = pxCurrentTCB[coreID] */
|
||||
lw sp, 0(a0) /* sp = previous sp */
|
||||
#else
|
||||
/* Recover the stack of next task */
|
||||
lw t0, pxCurrentTCB
|
||||
lw sp, 0x0(t0)
|
||||
lw a0, pxCurrentTCB
|
||||
lw sp, 0(a0)
|
||||
#endif /* ( configNUM_CORES > 1 ) */
|
||||
|
||||
|
||||
#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD
|
||||
/* esp_hw_stack_guard_set_bounds(pxCurrentTCB[0]->pxStack,
|
||||
* pxCurrentTCB[0]->pxEndOfStack);
|
||||
*/
|
||||
lw a0, PORT_OFFSET_PX_STACK(t0)
|
||||
lw a1, PORT_OFFSET_PX_END_OF_STACK(t0)
|
||||
ESP_HW_STACK_GUARD_SET_BOUNDS_CPU0
|
||||
lw a1, PORT_OFFSET_PX_END_OF_STACK(a0)
|
||||
lw a0, PORT_OFFSET_PX_STACK(a0)
|
||||
ESP_HW_STACK_GUARD_SET_BOUNDS_CUR_CORE a2
|
||||
/* esp_hw_stack_guard_monitor_start(); */
|
||||
ESP_HW_STACK_GUARD_MONITOR_START_CPU0
|
||||
ESP_HW_STACK_GUARD_MONITOR_START_CUR_CORE a0 a1
|
||||
#endif /* CONFIG_ESP_SYSTEM_HW_STACK_GUARD */
|
||||
#endif /* SOC_INT_CLIC_SUPPORTED */
|
||||
|
||||
rtos_int_exit_end:
|
||||
ret
|
||||
|
|
|
@ -14,6 +14,12 @@ else()
|
|||
"instruction_decode.c"
|
||||
"interrupt.c"
|
||||
"vectors.S")
|
||||
|
||||
if(CONFIG_SOC_INT_CLIC_SUPPORTED)
|
||||
list(APPEND srcs "vectors_clic.S")
|
||||
else()
|
||||
list(APPEND srcs "vectors_intc.S")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
idf_component_register(SRCS "${srcs}"
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
||||
/**
|
||||
* The interrupt bit in `mcause` register is always bit 31 regardless of the interrupt controller used
|
||||
*/
|
||||
#define VECTORS_MCAUSE_INTBIT_MASK (0x80000000)
|
||||
|
||||
|
||||
#if SOC_INT_CLIC_SUPPORTED
|
||||
|
||||
/* When using the CLIC as their interrupt controller, the `mcause` register contains more information than
|
||||
* the interrupt bit and cause:
|
||||
* MINHV[30]: CPU is fetching vector interrupt entry address or not
|
||||
* MPP[29:28]: MSTATUS.MPP[1:0]
|
||||
* MPIL[23:16]: interrupt level before entering interrupt ISR
|
||||
*
|
||||
* Define the mask that will only keep the cause.
|
||||
*/
|
||||
#define VECTORS_MCAUSE_REASON_MASK (0x00000fff)
|
||||
|
||||
#else // !if SOC_INT_CLIC_SUPPORTED
|
||||
|
||||
/**
|
||||
* For targets that use the former INTC or CLINT/PLIC, the `mcause` shouldn't contain any more information
|
||||
* but let's be safe and keep the 32 possible cause values.
|
||||
*/
|
||||
#define VECTORS_MCAUSE_REASON_MASK (0x0000001f)
|
||||
|
||||
#endif
|
|
@ -1,11 +1,13 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -124,6 +126,25 @@ void esprv_intc_int_set_threshold(int priority_threshold);
|
|||
*/
|
||||
uint32_t esprv_intc_get_interrupt_unmask(void);
|
||||
|
||||
/**
|
||||
* @brief Check if the given interrupt is hardware vectored
|
||||
*
|
||||
* @param rv_int_num Interrupt number
|
||||
*
|
||||
* @return true if the interrupt is vectored, false if it is not.
|
||||
*/
|
||||
bool esprv_intc_int_is_vectored(int rv_int_num);
|
||||
|
||||
/**
|
||||
* @brief Set interrupt vectored
|
||||
*
|
||||
* Configure the given interrupt number to hardware vectored or non-vectored.
|
||||
*
|
||||
* @param rv_int_num Interrupt number
|
||||
* @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);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -133,8 +133,9 @@ FORCE_INLINE_ATTR void rv_utils_intr_disable(uint32_t intr_mask)
|
|||
RV_SET_CSR(mstatus, old_mstatus & MSTATUS_MIE);
|
||||
}
|
||||
|
||||
//TODO: IDF-7795, clic related
|
||||
#if (SOC_CPU_CORES_NUM > 1)
|
||||
|
||||
#if SOC_INT_CLIC_SUPPORTED
|
||||
|
||||
FORCE_INLINE_ATTR void __attribute__((always_inline)) rv_utils_restore_intlevel(uint32_t restoreval)
|
||||
{
|
||||
REG_SET_FIELD(CLIC_INT_THRESH_REG, CLIC_CPU_INT_THRESH, ((restoreval << (8 - NLBITS))) | 0x1f);
|
||||
|
@ -145,8 +146,10 @@ FORCE_INLINE_ATTR uint32_t __attribute__((always_inline)) rv_utils_set_intlevel(
|
|||
uint32_t old_mstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE);
|
||||
uint32_t old_thresh;
|
||||
|
||||
old_thresh = REG_READ(CLIC_INT_THRESH_REG);
|
||||
old_thresh = old_thresh >> (24 + (8 - NLBITS));
|
||||
old_thresh = REG_GET_FIELD(CLIC_INT_THRESH_REG, CLIC_CPU_INT_THRESH);
|
||||
old_thresh = (old_thresh >> (8 - NLBITS));
|
||||
/* Upper bits should already be 0, but let's be safe and keep NLBITS */
|
||||
old_thresh &= BIT(NLBITS) - 1;
|
||||
|
||||
REG_SET_FIELD(CLIC_INT_THRESH_REG, CLIC_CPU_INT_THRESH, ((intlevel << (8 - NLBITS))) | 0x1f);
|
||||
/**
|
||||
|
@ -166,19 +169,15 @@ FORCE_INLINE_ATTR uint32_t __attribute__((always_inline)) rv_utils_set_intlevel(
|
|||
|
||||
FORCE_INLINE_ATTR uint32_t __attribute__((always_inline)) rv_utils_mask_int_level_lower_than(uint32_t intlevel)
|
||||
{
|
||||
#if SOC_INT_CLIC_SUPPORTED
|
||||
/* CLIC's set interrupt level is inclusive, i.e. it does mask the set level */
|
||||
return rv_utils_set_intlevel(intlevel - 1);
|
||||
#else
|
||||
return rv_utils_set_intlevel(intlevel);
|
||||
#endif /* SOC_INT_CLIC_SUPPORTED */
|
||||
}
|
||||
|
||||
#endif //#if (SOC_CPU_CORES_NUM > 1)
|
||||
#endif /* SOC_INT_CLIC_SUPPORTED */
|
||||
|
||||
|
||||
FORCE_INLINE_ATTR uint32_t rv_utils_intr_get_enabled_mask(void)
|
||||
{
|
||||
//TODO: IDF-7795
|
||||
#if SOC_INT_CLIC_SUPPORTED
|
||||
unsigned intr_ena_mask = 0;
|
||||
unsigned intr_num;
|
||||
|
@ -194,7 +193,6 @@ FORCE_INLINE_ATTR uint32_t rv_utils_intr_get_enabled_mask(void)
|
|||
|
||||
FORCE_INLINE_ATTR void rv_utils_intr_edge_ack(unsigned int intr_num)
|
||||
{
|
||||
//TODO: IDF-7795
|
||||
#if SOC_INT_CLIC_SUPPORTED
|
||||
REG_SET_BIT(CLIC_INT_CTRL_REG(intr_num + CLIC_EXT_INTR_NUM_OFFSET) , CLIC_INT_IP);
|
||||
#else
|
||||
|
|
|
@ -14,21 +14,33 @@
|
|||
#include "riscv/rv_utils.h"
|
||||
|
||||
|
||||
//TODO: IDF-7795, P4, see jira to know what changed and what need to be checked
|
||||
|
||||
|
||||
#define RV_INT_COUNT 32
|
||||
|
||||
static inline void assert_valid_rv_int_num(int rv_int_num)
|
||||
{
|
||||
#if SOC_INT_CLIC_SUPPORTED
|
||||
assert(rv_int_num < RV_INT_COUNT && "Invalid CPU interrupt number");
|
||||
#else
|
||||
assert(rv_int_num != 0 && rv_int_num < RV_INT_COUNT && "Invalid CPU interrupt number");
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************** Software interrupt dispatcher ***************************/
|
||||
/**
|
||||
* 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 {
|
||||
|
@ -36,98 +48,78 @@ typedef struct {
|
|||
void *arg;
|
||||
} intr_handler_item_t;
|
||||
|
||||
#if SOC_INT_CLIC_SUPPORTED
|
||||
static intr_handler_item_t s_intr_handlers_core0[48];
|
||||
static intr_handler_item_t s_intr_handlers_core1[48];
|
||||
#else
|
||||
static intr_handler_item_t s_intr_handlers[32];
|
||||
#endif
|
||||
static intr_handler_item_t s_intr_handlers[SOC_CPU_CORES_NUM][RV_EXTERNAL_INT_COUNT];
|
||||
|
||||
void intr_handler_set(int int_no, intr_handler_t fn, void *arg)
|
||||
|
||||
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)
|
||||
{
|
||||
assert_valid_rv_int_num(int_no);
|
||||
|
||||
#if SOC_INT_CLIC_SUPPORTED
|
||||
if (rv_utils_get_core_id() == 0) {
|
||||
s_intr_handlers_core0[int_no + CLIC_EXT_INTR_NUM_OFFSET] = (intr_handler_item_t) {
|
||||
.handler = fn,
|
||||
.arg = arg,
|
||||
};
|
||||
} else {
|
||||
s_intr_handlers_core1[int_no + CLIC_EXT_INTR_NUM_OFFSET] = (intr_handler_item_t) {
|
||||
.handler = fn,
|
||||
.arg = arg,
|
||||
};
|
||||
}
|
||||
#else
|
||||
s_intr_handlers[int_no] = (intr_handler_item_t) {
|
||||
const uint32_t id = rv_utils_get_core_id();
|
||||
|
||||
return &s_intr_handlers[id][int_no];
|
||||
}
|
||||
|
||||
/*************************** Software interrupt dispatcher ***************************/
|
||||
|
||||
void intr_handler_set(int int_no, intr_handler_t fn, void *arg)
|
||||
{
|
||||
intr_handler_item_t* item = intr_get_item(int_no);
|
||||
|
||||
*item = (intr_handler_item_t) {
|
||||
.handler = fn,
|
||||
.arg = arg
|
||||
};
|
||||
#endif
|
||||
}
|
||||
|
||||
intr_handler_t intr_handler_get(int rv_int_num)
|
||||
{
|
||||
#if SOC_INT_CLIC_SUPPORTED
|
||||
if (rv_utils_get_core_id() == 0)
|
||||
return s_intr_handlers_core0[rv_int_num + CLIC_EXT_INTR_NUM_OFFSET].handler;
|
||||
else
|
||||
return s_intr_handlers_core1[rv_int_num + CLIC_EXT_INTR_NUM_OFFSET].handler;
|
||||
#else
|
||||
return s_intr_handlers[rv_int_num].handler;
|
||||
#endif
|
||||
const intr_handler_item_t* item = intr_get_item(rv_int_num);
|
||||
return item->handler;
|
||||
}
|
||||
|
||||
void *intr_handler_get_arg(int rv_int_num)
|
||||
{
|
||||
#if SOC_INT_CLIC_SUPPORTED
|
||||
if (rv_utils_get_core_id() == 0)
|
||||
return s_intr_handlers_core0[rv_int_num + CLIC_EXT_INTR_NUM_OFFSET].arg;
|
||||
else
|
||||
return s_intr_handlers_core1[rv_int_num + CLIC_EXT_INTR_NUM_OFFSET].arg;
|
||||
#else
|
||||
return s_intr_handlers[rv_int_num].arg;
|
||||
#endif
|
||||
const intr_handler_item_t* item = intr_get_item(rv_int_num);
|
||||
return item->arg;
|
||||
}
|
||||
|
||||
/* called from vectors.S */
|
||||
void _global_interrupt_handler(intptr_t sp, int mcause)
|
||||
{
|
||||
#if SOC_INT_CLIC_SUPPORTED
|
||||
if (rv_utils_get_core_id() == 0) {
|
||||
intr_handler_item_t it = s_intr_handlers_core0[mcause];
|
||||
if (it.handler) {
|
||||
(*it.handler)(it.arg);
|
||||
}
|
||||
} else {
|
||||
intr_handler_item_t it = s_intr_handlers_core1[mcause];
|
||||
if (it.handler) {
|
||||
(*it.handler)(it.arg);
|
||||
}
|
||||
/* mcause contains the interrupt number that triggered the current interrupt, this number
|
||||
* also take into account local/internal interrupt, however, this should not happen in practice,
|
||||
* since we never map any peripheral to those. */
|
||||
assert(mcause >= RV_EXTERNAL_INT_OFFSET && "Interrupt sources must not be mapped to local interrupts");
|
||||
const intr_handler_item_t* item = intr_get_item(mcause - RV_EXTERNAL_INT_OFFSET);
|
||||
if (item->handler) {
|
||||
(*item->handler)(item->arg);
|
||||
}
|
||||
#else
|
||||
intr_handler_item_t it = s_intr_handlers[mcause];
|
||||
if (it.handler) {
|
||||
(*it.handler)(it.arg);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************** RISC-V interrupt enable/disable ***************************/
|
||||
|
||||
void intr_matrix_route(int intr_src, int intr_num)
|
||||
{
|
||||
#if !SOC_INT_CLIC_SUPPORTED
|
||||
assert(intr_num != 0);
|
||||
assert_valid_rv_int_num(intr_num);
|
||||
|
||||
REG_WRITE(DR_REG_INTERRUPT_BASE + 4 * intr_src, intr_num);
|
||||
#else
|
||||
if (rv_utils_get_core_id() == 0)
|
||||
REG_WRITE(DR_REG_INTERRUPT_CORE0_BASE + 4 * intr_src, intr_num + CLIC_EXT_INTR_NUM_OFFSET);
|
||||
else
|
||||
REG_WRITE(DR_REG_INTERRUPT_CORE1_BASE + 4 * intr_src, intr_num + CLIC_EXT_INTR_NUM_OFFSET);
|
||||
#endif
|
||||
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
|
||||
|
@ -141,29 +133,50 @@ uint32_t esprv_intc_get_interrupt_unmask(void)
|
|||
|
||||
/*************************** ESP-RV Interrupt Controller ***************************/
|
||||
|
||||
enum intr_type esprv_intc_int_get_type(int intr_num)
|
||||
{
|
||||
|
||||
#if SOC_INT_CLIC_SUPPORTED
|
||||
uint32_t intr_type_reg = REG_GET_FIELD(CLIC_INT_CTRL_REG(intr_num + CLIC_EXT_INTR_NUM_OFFSET), CLIC_INT_ATTR_TRIG);
|
||||
|
||||
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;
|
||||
// May also support rising edge and falling edge.
|
||||
#else
|
||||
uint32_t intr_type_reg = REG_READ(INTERRUPT_CORE0_CPU_INT_TYPE_REG);
|
||||
return (intr_type_reg & (1 << intr_num)) ? INTR_TYPE_EDGE : INTR_TYPE_LEVEL;
|
||||
#endif
|
||||
}
|
||||
|
||||
int esprv_intc_int_get_priority(int rv_int_num)
|
||||
{
|
||||
#if SOC_INT_CLIC_SUPPORTED
|
||||
uint32_t intr_priority_reg = REG_GET_FIELD(CLIC_INT_CTRL_REG(rv_int_num + CLIC_EXT_INTR_NUM_OFFSET), CLIC_INT_CTL);
|
||||
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));
|
||||
#else
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
#endif // SOC_INT_CLIC_SUPPORTED
|
||||
|
||||
/*************************** Exception names. Used in .gdbinit file. ***************************/
|
||||
|
||||
const char *riscv_excp_names[16] __attribute__((used)) = {
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "riscv/rvruntime-frames.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_private/vectors_const.h"
|
||||
|
||||
|
||||
.equ SAVE_REGS, 32
|
||||
|
@ -60,7 +61,7 @@
|
|||
|
||||
/* Restore the general purpose registers (excluding gp) from the context on
|
||||
* the stack. The context is then deallocated. The default size is CONTEXT_SIZE
|
||||
* but it can be overriden. */
|
||||
* but it can be overridden. */
|
||||
.macro restore_general_regs cxt_size=CONTEXT_SIZE
|
||||
lw ra, RV_STK_RA(sp)
|
||||
lw tp, RV_STK_TP(sp)
|
||||
|
@ -107,92 +108,10 @@
|
|||
#endif
|
||||
|
||||
.section .exception_vectors.text
|
||||
/* This is the vector table. MTVEC points here.
|
||||
*
|
||||
* Use 4-byte intructions here. 1 instruction = 1 entry of the table.
|
||||
* The CPU jumps to MTVEC (i.e. the first entry) in case of an exception,
|
||||
* and (MTVEC & 0xfffffffc) + (mcause & 0x7fffffff) * 4, in case of an interrupt.
|
||||
*
|
||||
* Note: for our CPU, we need to place this on a 256-byte boundary, as CPU
|
||||
* only uses the 24 MSBs of the MTVEC, i.e. (MTVEC & 0xffffff00).
|
||||
*/
|
||||
|
||||
/**
|
||||
* TODO: IDF-7863, P4, see jira to know what changed and what need to be checked
|
||||
*/
|
||||
|
||||
#if SOC_INT_CLIC_SUPPORTED
|
||||
.balign 0x40
|
||||
#else
|
||||
.balign 0x100
|
||||
#endif
|
||||
.global _vector_table
|
||||
.type _vector_table, @function
|
||||
_vector_table:
|
||||
.option push
|
||||
.option norvc
|
||||
#if SOC_INT_CLIC_SUPPORTED
|
||||
j _trap_handler
|
||||
#else
|
||||
j _panic_handler /* exception handler, entry 0 */
|
||||
#if ETS_INT_WDT_INUM != 24
|
||||
#error "ETS_INT_WDT_INUM expected to be 24"
|
||||
#endif
|
||||
.rept (ETS_INT_WDT_INUM - 1)
|
||||
j _interrupt_handler /* 23 identical entries, all pointing to the interrupt handler */
|
||||
.endr
|
||||
j _panic_handler /* 24: ETS_INT_WDT_INUM panic-interrupt (soc-level panic) */
|
||||
j _panic_handler /* 25: ETS_CACHEERR_INUM panic-interrupt (soc-level panic) */
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
|
||||
j _panic_handler /* 26: ETS_MEMPROT_ERR_INUM panic-interrupt (soc-level panic) */
|
||||
#else
|
||||
j _interrupt_handler /* 26: interrupt-handler */
|
||||
#endif // CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
|
||||
#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD
|
||||
j _panic_handler /* 27: ETS_ASSIST_DEBUG_INUM panic-interrupt (soc-level panic) */
|
||||
#else
|
||||
j _interrupt_handler /* 27: interrupt-handler */
|
||||
#endif // CONFIG_ESP_SYSTEM_HW_STACK_GUARD
|
||||
.rept (ETS_MAX_INUM - ETS_ASSIST_DEBUG_INUM)
|
||||
j _interrupt_handler /* remain entries are identical, all pointing to the interrupt handler */
|
||||
.endr
|
||||
#endif
|
||||
.option pop
|
||||
.size _vector_table, .-_vector_table
|
||||
|
||||
#if SOC_INT_CLIC_SUPPORTED
|
||||
.balign 0x40
|
||||
.global _mtvt_table
|
||||
.type _mtvt_table, @function
|
||||
_mtvt_table:
|
||||
.option push
|
||||
.option norvc
|
||||
.rept 48
|
||||
.word _interrupt_handler
|
||||
.endr
|
||||
.option pop
|
||||
.size _mtvt_table, .-_mtvt_table
|
||||
#endif
|
||||
|
||||
#if SOC_INT_CLIC_SUPPORTED
|
||||
.type _trap_handler, @function
|
||||
_trap_handler:
|
||||
addi sp, sp, -RV_STK_FRMSZ
|
||||
sw t0, RV_STK_T0(sp)
|
||||
sw t1, RV_STK_T1(sp)
|
||||
csrr t0, mcause
|
||||
li t1, 0x80000000
|
||||
bltu t0, t1, _panic_handler
|
||||
lw t0, RV_STK_T0(sp)
|
||||
lw t1, RV_STK_T1(sp)
|
||||
addi sp, sp, RV_STK_FRMSZ
|
||||
//ESP32P4-TODO: ETS_T1_WDT_INUM/ETS_CACHEERR_INUM/ETS_MEMPROT_ERR_INUM
|
||||
j _interrupt_handler
|
||||
.size _trap_handler, .-_trap_handler
|
||||
#endif
|
||||
|
||||
/* Exception handler.*/
|
||||
.type _panic_handler, @function
|
||||
.global _panic_handler
|
||||
_panic_handler:
|
||||
/* Allocate space on the stack and store general purpose registers */
|
||||
save_general_regs RV_STK_FRMSZ
|
||||
|
@ -224,16 +143,11 @@ _panic_handler:
|
|||
mv a0, sp
|
||||
csrr a1, mcause
|
||||
|
||||
/*
|
||||
* MINHV[30]: CPU is fetching vector interrupt entry address or not
|
||||
* MPP[29:28]: MSTATUS.MPP[1:0]
|
||||
* MPIL[23:16]: interrupt level before entrering interrupt isr
|
||||
*/
|
||||
#if SOC_INT_CLIC_SUPPORTED
|
||||
la t1, 0x80000fff
|
||||
/* Only keep the interrupt bit and the source cause of the trap */
|
||||
li t1, VECTORS_MCAUSE_INTBIT_MASK | VECTORS_MCAUSE_REASON_MASK
|
||||
and a1, a1, t1
|
||||
#endif
|
||||
/* Branches instructions don't accept immediates values, so use t1 to
|
||||
|
||||
/* Branches instructions don't accept immediate values, so use t1 to
|
||||
* store our comparator */
|
||||
li t0, 0x80000000
|
||||
bgeu a1, t0, _call_panic_handler
|
||||
|
@ -258,6 +172,10 @@ _call_panic_handler:
|
|||
* structure */
|
||||
not t0, t0
|
||||
and a1, a1, t0
|
||||
#if CONFIG_SOC_INT_CLIC_SUPPORTED
|
||||
/* When CLIC is supported, external interrupts are shifted by 16, deduct this difference from mcause */
|
||||
add a1, a1, -16
|
||||
#endif // CONFIG_SOC_INT_CLIC_SUPPORTED
|
||||
sw a1, RV_STK_MCAUSE(sp)
|
||||
jal panic_from_isr
|
||||
|
||||
|
@ -275,6 +193,7 @@ _return_from_exception:
|
|||
mret
|
||||
.size _panic_handler, .-_panic_handler
|
||||
|
||||
|
||||
/* This is the interrupt handler.
|
||||
* It saves the registers on the stack,
|
||||
* prepares for interrupt nesting,
|
||||
|
@ -300,12 +219,8 @@ _interrupt_handler:
|
|||
/* Save SP */
|
||||
sw t0, RV_STK_SP(sp)
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32P4
|
||||
//TODO: IDF-7861
|
||||
/* Before doing anythig preserve the stack pointer */
|
||||
/* It will be saved in current TCB, if needed */
|
||||
mv a0, sp
|
||||
#endif //#if CONFIG_IDF_TARGET_ESP32P4
|
||||
/* Notify the RTOS that an interrupt ocurred, it will save the current stack pointer
|
||||
* in the running TCB, no need to pass it as a parameter */
|
||||
call rtos_int_enter
|
||||
/* If this is a non-nested interrupt, SP now points to the interrupt stack */
|
||||
|
||||
|
@ -313,13 +228,13 @@ _interrupt_handler:
|
|||
csrr s1, mcause
|
||||
csrr s2, mstatus
|
||||
|
||||
#if !SOC_INT_CLIC_SUPPORTED
|
||||
#if !SOC_INT_HW_NESTED_SUPPORTED
|
||||
/* Save the interrupt threshold level */
|
||||
li t0, INTERRUPT_CORE0_CPU_INT_THRESH_REG
|
||||
lw s3, 0(t0)
|
||||
|
||||
/* Increase interrupt threshold level */
|
||||
li t2, 0x7fffffff
|
||||
li t2, VECTORS_MCAUSE_REASON_MASK
|
||||
and t1, s1, t2 /* t1 = mcause & mask */
|
||||
slli t1, t1, 2 /* t1 = mcause * 4 */
|
||||
li t2, INTC_INT_PRIO_REG(0)
|
||||
|
@ -328,7 +243,7 @@ _interrupt_handler:
|
|||
addi t2, t2, 1 /* t2 = t2 +1 */
|
||||
sw t2, 0(t0) /* INTERRUPT_CORE0_CPU_INT_THRESH_REG = t2 */
|
||||
fence
|
||||
#endif
|
||||
#endif // !SOC_INT_HW_NESTED_SUPPORTED
|
||||
|
||||
li t0, 0x8
|
||||
csrrs t0, mstatus, t0
|
||||
|
@ -354,11 +269,7 @@ _interrupt_handler:
|
|||
mv a0, sp /* argument 1, stack pointer */
|
||||
mv a1, s1 /* argument 2, interrupt number (mcause) */
|
||||
/* mask off the interrupt flag of mcause */
|
||||
#if !SOC_INT_CLIC_SUPPORTED
|
||||
li t0, 0x7fffffff
|
||||
#else
|
||||
li t0, 0x00000fff
|
||||
#endif
|
||||
li t0, VECTORS_MCAUSE_REASON_MASK
|
||||
and a1, a1, t0
|
||||
jal _global_interrupt_handler
|
||||
|
||||
|
@ -368,26 +279,20 @@ _interrupt_handler:
|
|||
csrrc t0, mstatus, t0
|
||||
/* MIE cleared. Nested interrupts are disabled */
|
||||
|
||||
#if !SOC_INT_CLIC_SUPPORTED
|
||||
#if !SOC_INT_HW_NESTED_SUPPORTED
|
||||
/* restore the interrupt threshold level */
|
||||
li t0, INTERRUPT_CORE0_CPU_INT_THRESH_REG
|
||||
sw s3, 0(t0)
|
||||
fence
|
||||
#endif
|
||||
#endif // !SOC_INT_HW_NESTED_SUPPORTED
|
||||
|
||||
#if SOC_INT_CLIC_SUPPORTED
|
||||
/* Yield to the next task is needed: */
|
||||
mv a0, sp
|
||||
#endif
|
||||
/* The RTOS will restore the current TCB stack pointer. This routine will preserve s1 and s2 but alter s0. */
|
||||
call rtos_int_exit
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32P4
|
||||
//TODO: IDF-7861
|
||||
/* The next (or current) stack pointer is returned in a0 */
|
||||
mv sp, a0
|
||||
#endif //#if CONFIG_IDF_TARGET_ESP32P4
|
||||
|
||||
/* restore the rest of the registers */
|
||||
/* Restore the rest of the registers.
|
||||
* In case the target uses the CLIC, it is mandatory to restore `mcause` register since it contains
|
||||
* the former CPU priority. When executing `mret`, the hardware will restore the former threshold,
|
||||
* from `mcause` to `mintstatus` CSR */
|
||||
csrw mcause, s1
|
||||
csrw mstatus, s2
|
||||
restore_mepc
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc.h"
|
||||
|
||||
/* If memory protection interrupts are meant to trigger a panic, attach them to panic handler,
|
||||
* else, attach them to the interrupt handler. */
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
|
||||
#define MEMPROT_ISR _panic_handler
|
||||
#else
|
||||
#define MEMPROT_ISR _interrupt_handler
|
||||
#endif // CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
|
||||
|
||||
/* The system interrupts are not used for now, so trigger a panic every time one occurs. */
|
||||
#define _system_int_handler _panic_handler
|
||||
|
||||
/* Handlers defined in the `vector.S` file, common to all RISC-V targets */
|
||||
.global _interrupt_handler
|
||||
.global _panic_handler
|
||||
|
||||
.section .exception_vectors_table.text
|
||||
|
||||
/* Prevent the compiler from generating 2-byte instruction in the vector tables */
|
||||
.option push
|
||||
.option norvc
|
||||
|
||||
/**
|
||||
* Non-hardware vectored interrupt entry. MTVEC CSR points here.
|
||||
*
|
||||
* On targets that use CLIC as their interrupt controller, when an exception occurs, the CPU
|
||||
* jumps to the address stored in MTVEC[31:6] << 6. The CPU will also jump to this location
|
||||
* if an interrupt is configured as non-vectored (CLIC_INT_ATTR.shv = 0).
|
||||
*
|
||||
* Because of the left-shift `<< 6`, this entry must be aligned on 64.
|
||||
*/
|
||||
.global _vector_table
|
||||
.type _vector_table, @function
|
||||
.balign 0x40
|
||||
_vector_table:
|
||||
j _panic_handler
|
||||
.size _vector_table, .-_vector_table
|
||||
|
||||
|
||||
/**
|
||||
* Vectored interrupt table. MTVT CSR points here.
|
||||
*
|
||||
* If an interrupt occurs and is configured as (hardware) vectored, the CPU will jump to
|
||||
* MTVT[31:0] + 4 * interrupt_id
|
||||
*
|
||||
* In the case of the ESP32P4, the interrupt matrix, between the CPU interrupt lines
|
||||
* and the peripherals, offers 32 lines. As such, the interrupt_id between 0 and 31.
|
||||
*
|
||||
* Since the interrupts are initialized as vectored on CPU start, we can manage the special
|
||||
* interrupts ETS_T1_WDT_INUM, ETS_CACHEERR_INUM and ETS_MEMPROT_ERR_INUM here.
|
||||
*/
|
||||
.balign 0x40
|
||||
.global _mtvt_table
|
||||
.type _mtvt_table, @function
|
||||
_mtvt_table:
|
||||
.word _system_int_handler /* 0: System interrupt number. Exceptions are non-vectored, won't load this. */
|
||||
.word _system_int_handler /* 1: System interrupt number */
|
||||
.word _system_int_handler /* 2: System interrupt number */
|
||||
.word _system_int_handler /* 3: System interrupt number */
|
||||
.word _system_int_handler /* 4: System interrupt number */
|
||||
.word _system_int_handler /* 5: System interrupt number */
|
||||
.word _system_int_handler /* 6: System interrupt number */
|
||||
.word _system_int_handler /* 7: System interrupt number */
|
||||
.word _system_int_handler /* 8: System interrupt number */
|
||||
.word _system_int_handler /* 9: System interrupt number */
|
||||
.word _system_int_handler /* 10: System interrupt number */
|
||||
.word _system_int_handler /* 11: System interrupt number */
|
||||
.word _system_int_handler /* 12: System interrupt number */
|
||||
.word _system_int_handler /* 13: System interrupt number */
|
||||
.word _system_int_handler /* 14: System interrupt number */
|
||||
.word _system_int_handler /* 15: System interrupt number */
|
||||
.word _interrupt_handler /* 16: Free interrupt number */
|
||||
.word _interrupt_handler /* 17: Free interrupt number */
|
||||
.word _interrupt_handler /* 18: Free interrupt number */
|
||||
.word _interrupt_handler /* 19: Free interrupt number */
|
||||
.word _interrupt_handler /* 20: Free interrupt number */
|
||||
.word _interrupt_handler /* 21: Free interrupt number */
|
||||
.word _interrupt_handler /* 22: Free interrupt number */
|
||||
.word _interrupt_handler /* 23: Free interrupt number */
|
||||
.word _interrupt_handler /* 24: Free interrupt number */
|
||||
.word _interrupt_handler /* 25: Free interrupt number */
|
||||
.word _interrupt_handler /* 26: Free interrupt number */
|
||||
.word _interrupt_handler /* 27: Free interrupt number */
|
||||
.word _interrupt_handler /* 28: Free interrupt number */
|
||||
.word _interrupt_handler /* 29: Free interrupt number */
|
||||
.word _interrupt_handler /* 30: Free interrupt number */
|
||||
.word _interrupt_handler /* 31: Free interrupt number */
|
||||
.word _interrupt_handler /* 32: Free interrupt number */
|
||||
.word _interrupt_handler /* 33: Free interrupt number */
|
||||
.word _interrupt_handler /* 34: Free interrupt number */
|
||||
.word _interrupt_handler /* 35: Free interrupt number */
|
||||
.word _interrupt_handler /* 36: Free interrupt number */
|
||||
.word _interrupt_handler /* 37: Free interrupt number */
|
||||
.word _interrupt_handler /* 38: Free interrupt number */
|
||||
.word _interrupt_handler /* 39: Free interrupt number */
|
||||
.word _panic_handler /* 40: ETS_INT_WDT_INUM (+16) panic-interrupt (soc-level panic) */
|
||||
.word _panic_handler /* 41: ETS_CACHEERR_INUM (+16) panic-interrupt (soc-level panic) */
|
||||
.word MEMPROT_ISR /* 42: ETS_MEMPROT_ERR_INUM (+16) handler (soc-level panic) */
|
||||
.word _interrupt_handler /* 43: Free interrupt number */
|
||||
.word _interrupt_handler /* 44: Free interrupt number */
|
||||
.word _interrupt_handler /* 45: Free interrupt number */
|
||||
.word _interrupt_handler /* 46: Free interrupt number */
|
||||
.word _interrupt_handler /* 47: Free interrupt number */
|
||||
|
||||
.size _mtvt_table, .-_mtvt_table
|
||||
.option pop
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc.h"
|
||||
|
||||
#if ETS_INT_WDT_INUM != 24
|
||||
#error "ETS_INT_WDT_INUM expected to be 24"
|
||||
#endif
|
||||
|
||||
/* If memory protection interrupts are meant to trigger a panic, attach them to panic handler,
|
||||
* else, attach them to the interrupt handler. */
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
|
||||
#define MEMPROT_ISR _panic_handler
|
||||
#else
|
||||
#define MEMPROT_ISR _interrupt_handler
|
||||
#endif // CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
|
||||
|
||||
/* Same goes for the assist debug interrupt */
|
||||
#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD
|
||||
#define ASTDBG_ISR _panic_handler
|
||||
#else
|
||||
#define ASTDBG_ISR _interrupt_handler
|
||||
#endif // CONFIG_ESP_SYSTEM_HW_STACK_GUARD
|
||||
|
||||
|
||||
/* Handlers defined in the `vector.S` file, common to all RISC-V targets */
|
||||
.global _interrupt_handler
|
||||
.global _panic_handler
|
||||
|
||||
.section .exception_vectors_table.text
|
||||
|
||||
/* This is the vector table. MTVEC points here.
|
||||
*
|
||||
* Use 4-byte instructions here. 1 instruction = 1 entry of the table.
|
||||
* The CPU jumps to MTVEC (i.e. the first entry) in case of an exception,
|
||||
* and (MTVEC & 0xfffffffc) + (mcause & 0x7fffffff) * 4, in case of an interrupt.
|
||||
*
|
||||
* Note: for our CPU, we need to place this on a 256-byte boundary, as CPU
|
||||
* only uses the 24 MSBs of the MTVEC, i.e. (MTVEC & 0xffffff00).
|
||||
*/
|
||||
.balign 0x100
|
||||
|
||||
/* Since each entry must take 4-byte, let's temporarily disable the compressed
|
||||
* instruction set that could potentially generate 2-byte instructions. */
|
||||
.option push
|
||||
.option norvc
|
||||
|
||||
.global _vector_table
|
||||
.type _vector_table, @function
|
||||
_vector_table:
|
||||
j _panic_handler /* 0: Exception entry */
|
||||
j _interrupt_handler /* 1: Free interrupt number */
|
||||
j _interrupt_handler /* 2: Free interrupt number */
|
||||
j _interrupt_handler /* 3: Free interrupt number */
|
||||
j _interrupt_handler /* 4: Free interrupt number */
|
||||
j _interrupt_handler /* 5: Free interrupt number */
|
||||
j _interrupt_handler /* 6: Free interrupt number */
|
||||
j _interrupt_handler /* 7: Free interrupt number */
|
||||
j _interrupt_handler /* 8: Free interrupt number */
|
||||
j _interrupt_handler /* 9: Free interrupt number */
|
||||
j _interrupt_handler /* 10: Free interrupt number */
|
||||
j _interrupt_handler /* 11: Free interrupt number */
|
||||
j _interrupt_handler /* 12: Free interrupt number */
|
||||
j _interrupt_handler /* 13: Free interrupt number */
|
||||
j _interrupt_handler /* 14: Free interrupt number */
|
||||
j _interrupt_handler /* 15: Free interrupt number */
|
||||
j _interrupt_handler /* 16: Free interrupt number */
|
||||
j _interrupt_handler /* 17: Free interrupt number */
|
||||
j _interrupt_handler /* 18: Free interrupt number */
|
||||
j _interrupt_handler /* 19: Free interrupt number */
|
||||
j _interrupt_handler /* 20: Free interrupt number */
|
||||
j _interrupt_handler /* 21: Free interrupt number */
|
||||
j _interrupt_handler /* 22: Free interrupt number */
|
||||
j _interrupt_handler /* 23: Free interrupt number */
|
||||
j _panic_handler /* 24: ETS_INT_WDT_INUM panic-interrupt (soc-level panic) */
|
||||
j _panic_handler /* 25: ETS_CACHEERR_INUM panic-interrupt (soc-level panic) */
|
||||
j MEMPROT_ISR /* 26: ETS_MEMPROT_ERR_INUM handler (soc-level panic) */
|
||||
j ASTDBG_ISR /* 27: ETS_ASSIST_DEBUG_INUM handler (soc-level panic) */
|
||||
j _interrupt_handler /* 28: Free interrupt number */
|
||||
j _interrupt_handler /* 29: Free interrupt number */
|
||||
j _interrupt_handler /* 30: Free interrupt number */
|
||||
j _interrupt_handler /* 31: Free interrupt number */
|
||||
|
||||
.size _vector_table, .-_vector_table
|
||||
|
||||
/* Re-enable the compressed instruction set it is was enabled before */
|
||||
.option pop
|
|
@ -207,6 +207,10 @@ config SOC_INT_CLIC_SUPPORTED
|
|||
bool
|
||||
default y
|
||||
|
||||
config SOC_INT_HW_NESTED_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_BRANCH_PREDICTOR_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
|
|
@ -3,10 +3,30 @@
|
|||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "soc/clic_reg.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
// ESP32P4 uses the CLIC controller as the interrupt controller (SOC_INT_CLIC_SUPPORTED = y)
|
||||
#define INTERRUPT_CORE0_CPU_INT_THRESH_REG CLIC_INT_THRESH_REG
|
||||
#define INTERRUPT_CORE1_CPU_INT_THRESH_REG CLIC_INT_THRESH_REG
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* ESP32P4 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_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_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
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -230,7 +230,7 @@
|
|||
//On RISC-V CPUs, the interrupt sources are all external interrupts, whose type, source and priority are configured by SW.
|
||||
//There is no HW NMI conception. SW should controlled the masked levels through INT_THRESH_REG.
|
||||
|
||||
//CPU0 Interrupt number reserved in riscv/vector.S, not touch this.
|
||||
//CPU0 Interrupt number reserved in riscv/vector_clic.S, do not touch this.
|
||||
#define ETS_T1_WDT_INUM 24
|
||||
#define ETS_CACHEERR_INUM 25
|
||||
#define ETS_MEMPROT_ERR_INUM 26
|
||||
|
|
|
@ -137,6 +137,7 @@
|
|||
#define SOC_CPU_HAS_FLEXIBLE_INTC 1
|
||||
#define SOC_INT_PLIC_SUPPORTED 0 //riscv platform-level interrupt controller
|
||||
#define SOC_INT_CLIC_SUPPORTED 1
|
||||
#define SOC_INT_HW_NESTED_SUPPORTED 1 // Support for hardware interrupts nesting
|
||||
#define SOC_BRANCH_PREDICTOR_SUPPORTED 1
|
||||
|
||||
#define SOC_CPU_BREAKPOINTS_NUM 4
|
||||
|
|
|
@ -7,132 +7,132 @@
|
|||
#include "soc/interrupts.h"
|
||||
|
||||
const char *const esp_isr_names[] = {
|
||||
[0] = "LP_RTC",
|
||||
[1] = "LP_WDT",
|
||||
[2] = "LP_TIMER0",
|
||||
[3] = "LP_TIMER1",
|
||||
[4] = "MB_HP",
|
||||
[5] = "MB_LP",
|
||||
[6] = "PMU0",
|
||||
[7] = "PMU1",
|
||||
[8] = "LP_ANA",
|
||||
[9] = "LP_ADC",
|
||||
[10] = "LP_GPIO",
|
||||
[11] = "LP_I2C",
|
||||
[12] = "LP_I2S",
|
||||
[13] = "LP_SPI",
|
||||
[14] = "LP_TOUCH",
|
||||
[15] = "LP_TSENS",
|
||||
[16] = "LP_UART",
|
||||
[17] = "LP_EFUSE",
|
||||
[18] = "LP_SW",
|
||||
[19] = "LP_SYSREG",
|
||||
[20] = "LP_HUK",
|
||||
[21] = "SYS_ICM",
|
||||
[22] = "USB_DEVICE",
|
||||
[23] = "SDIO_HOST",
|
||||
[24] = "GDMA",
|
||||
[25] = "GPSPI2",
|
||||
[26] = "GPSPI3",
|
||||
[27] = "I2S0",
|
||||
[28] = "I2S1",
|
||||
[29] = "I2S2",
|
||||
[30] = "UHCI0",
|
||||
[31] = "UART0",
|
||||
[32] = "UART1",
|
||||
[33] = "UART2",
|
||||
[34] = "UART3",
|
||||
[35] = "UART4",
|
||||
[36] = "LCD_CAM",
|
||||
[37] = "ADC",
|
||||
[38] = "PWM0",
|
||||
[39] = "PWM1",
|
||||
[40] = "CAN0",
|
||||
[41] = "CAN1",
|
||||
[42] = "CAN2",
|
||||
[43] = "RMT",
|
||||
[44] = "I2C0",
|
||||
[45] = "I2C1",
|
||||
[46] = "TG0_T0",
|
||||
[47] = "TG0_T1",
|
||||
[48] = "TG0_WDT",
|
||||
[49] = "TG1_T0",
|
||||
[50] = "TG1_T1",
|
||||
[51] = "TG1_WDT",
|
||||
[52] = "LEDC",
|
||||
[53] = "SYSTIMER_TARGET0",
|
||||
[54] = "SYSTIMER_TARGET1",
|
||||
[55] = "SYSTIMER_TARGET2",
|
||||
[56] = "AHB_PDMA_IN_CH0",
|
||||
[57] = "AHB_PDMA_IN_CH1",
|
||||
[58] = "AHB_PDMA_IN_CH2",
|
||||
[59] = "AHB_PDMA_OUT_CH0",
|
||||
[60] = "AHB_PDMA_OUT_CH1",
|
||||
[61] = "AHB_PDMA_OUT_CH2",
|
||||
[62] = "AXI_PDMA_IN_CH0",
|
||||
[63] = "AXI_PDMA_IN_CH1",
|
||||
[64] = "AXI_PDMA_IN_CH2",
|
||||
[65] = "AXI_PDMA_OUT_CH0",
|
||||
[66] = "AXI_PDMA_OUT_CH1",
|
||||
[67] = "AXI_PDMA_OUT_CH2",
|
||||
[68] = "RSA",
|
||||
[69] = "AES",
|
||||
[70] = "SHA",
|
||||
[71] = "ECC",
|
||||
[72] = "ECDSA",
|
||||
[73] = "KM",
|
||||
[74] = "GPIO_INT0",
|
||||
[75] = "GPIO_INT1",
|
||||
[76] = "GPIO_INT2",
|
||||
[77] = "GPIO_INT3",
|
||||
[78] = "GPIO_PAD_COMP",
|
||||
[79] = "CPU_INT_FROM_CPU_0",
|
||||
[80] = "CPU_INT_FROM_CPU_1",
|
||||
[81] = "CPU_INT_FROM_CPU_2",
|
||||
[82] = "CPU_INT_FROM_CPU_3",
|
||||
[83] = "CACHE",
|
||||
[84] = "FLASH_MSPI",
|
||||
[85] = "CSI_BRIDGE",
|
||||
[86] = "DSI_BRIDGE",
|
||||
[87] = "CSI",
|
||||
[88] = "DSI",
|
||||
[89] = "GMII_PHY",
|
||||
[90] = "LPI",
|
||||
[91] = "PMT",
|
||||
[92] = "SBD",
|
||||
[93] = "USB_OTG",
|
||||
[94] = "USB_OTG_ENDP_MULTI_PROC",
|
||||
[95] = "JPEG",
|
||||
[96] = "PPA",
|
||||
[97] = "CORE0_TRACE",
|
||||
[98] = "CORE1_TRACE",
|
||||
[99] = "HP_CORE",
|
||||
[100] = "ISP",
|
||||
[101] = "I3C",
|
||||
[102] = "I3C_SLV",
|
||||
[103] = "USB_OTG11",
|
||||
[104] = "DMA2D_IN_CH0",
|
||||
[105] = "DMA2D_IN_CH1",
|
||||
[106] = "DMA2D_OUT_CH0",
|
||||
[107] = "DMA2D_OUT_CH1",
|
||||
[108] = "DMA2D_OUT_CH2",
|
||||
[109] = "PSRAM_MSPI",
|
||||
[110] = "HP_SYSREG",
|
||||
[111] = "PCNT",
|
||||
[112] = "HP_PAU",
|
||||
[113] = "HP_PARLIO_RX",
|
||||
[114] = "HP_PARLIO_TX",
|
||||
[115] = "H264_DMA2D_OUT_CH0",
|
||||
[116] = "H264_DMA2D_OUT_CH1",
|
||||
[117] = "H264_DMA2D_OUT_CH2",
|
||||
[118] = "H264_DMA2D_OUT_CH3",
|
||||
[119] = "H264_DMA2D_OUT_CH4",
|
||||
[120] = "H264_DMA2D_IN_CH0",
|
||||
[121] = "H264_DMA2D_IN_CH1",
|
||||
[122] = "H264_DMA2D_IN_CH2",
|
||||
[123] = "H264_DMA2D_IN_CH3",
|
||||
[124] = "H264_DMA2D_IN_CH4",
|
||||
[125] = "H264_DMA2D_IN_CH5",
|
||||
[126] = "H264_REG",
|
||||
[127] = "ASSIST_DEBUG",
|
||||
[ETS_LP_RTC_INTR_SOURCE] = "LP_RTC",
|
||||
[ETS_LP_WDT_INTR_SOURCE] = "LP_WDT",
|
||||
[ETS_LP_TIMER_REG0_INTR_SOURCE] = "LP_TIMER_REG0",
|
||||
[ETS_LP_TIMER_REG1_INTR_SOURCE] = "LP_TIMER_REG1",
|
||||
[ETS_MB_HP_INTR_SOURCE] = "MB_HP",
|
||||
[ETS_MB_LP_INTR_SOURCE] = "MB_LP",
|
||||
[ETS_PMU_0_INTR_SOURCE] = "PMU_0",
|
||||
[ETS_PMU_1_INTR_SOURCE] = "PMU_1",
|
||||
[ETS_LP_ANAPERI_INTR_SOURCE] = "LP_ANAPERI",
|
||||
[ETS_LP_ADC_INTR_SOURCE] = "LP_ADC",
|
||||
[ETS_LP_GPIO_INTR_SOURCE] = "LP_GPIO",
|
||||
[ETS_LP_I2C_INTR_SOURCE] = "LP_I2C",
|
||||
[ETS_LP_I2S_INTR_SOURCE] = "LP_I2S",
|
||||
[ETS_LP_SPI_INTR_SOURCE] = "LP_SPI",
|
||||
[ETS_LP_TOUCH_INTR_SOURCE] = "LP_TOUCH",
|
||||
[ETS_LP_TSENS_INTR_SOURCE] = "LP_TSENS",
|
||||
[ETS_LP_UART_INTR_SOURCE] = "LP_UART",
|
||||
[ETS_LP_EFUSE_INTR_SOURCE] = "LP_EFUSE",
|
||||
[ETS_LP_SW_INTR_SOURCE] = "LP_SW",
|
||||
[ETS_LP_SYSREG_INTR_SOURCE] = "LP_SYSREG",
|
||||
[ETS_LP_HUK_INTR_SOURCE] = "LP_HUK",
|
||||
[ETS_SYS_ICM_INTR_SOURCE] = "SYS_ICM",
|
||||
[ETS_USB_DEVICE_INTR_SOURCE] = "USB_DEVICE",
|
||||
[ETS_SDIO_HOST_INTR_SOURCE] = "SDIO_HOST",
|
||||
[ETS_GDMA_INTR_SOURCE] = "GDMA",
|
||||
[ETS_SPI2_INTR_SOURCE] = "SPI2",
|
||||
[ETS_SPI3_INTR_SOURCE] = "SPI3",
|
||||
[ETS_I2S0_INTR_SOURCE] = "I2S0",
|
||||
[ETS_I2S1_INTR_SOURCE] = "I2S1",
|
||||
[ETS_I2S2_INTR_SOURCE] = "I2S2",
|
||||
[ETS_UHCI0_INTR_SOURCE] = "UHCI0",
|
||||
[ETS_UART0_INTR_SOURCE] = "UART0",
|
||||
[ETS_UART1_INTR_SOURCE] = "UART1",
|
||||
[ETS_UART2_INTR_SOURCE] = "UART2",
|
||||
[ETS_UART3_INTR_SOURCE] = "UART3",
|
||||
[ETS_UART4_INTR_SOURCE] = "UART4",
|
||||
[ETS_LCD_CAM_INTR_SOURCE] = "LCD_CAM",
|
||||
[ETS_ADC_INTR_SOURCE] = "ADC",
|
||||
[ETS_PWM0_INTR_SOURCE] = "PWM0",
|
||||
[ETS_PWM1_INTR_SOURCE] = "PWM1",
|
||||
[ETS_CAN0_INTR_SOURCE] = "CAN0",
|
||||
[ETS_CAN1_INTR_SOURCE] = "CAN1",
|
||||
[ETS_CAN2_INTR_SOURCE] = "CAN2",
|
||||
[ETS_RMT_INTR_SOURCE] = "RMT",
|
||||
[ETS_I2C0_INTR_SOURCE] = "I2C0",
|
||||
[ETS_I2C1_INTR_SOURCE] = "I2C1",
|
||||
[ETS_TG0_T0_INTR_SOURCE] = "TG0_T0",
|
||||
[ETS_TG0_T1_INTR_SOURCE] = "TG0_T1",
|
||||
[ETS_TG0_WDT_LEVEL_INTR_SOURCE] = "TG0_WDT_LEVEL",
|
||||
[ETS_TG1_T0_INTR_SOURCE] = "TG1_T0",
|
||||
[ETS_TG1_T1_INTR_SOURCE] = "TG1_T1",
|
||||
[ETS_TG1_WDT_LEVEL_INTR_SOURCE] = "TG1_WDT_LEVEL",
|
||||
[ETS_LEDC_INTR_SOURCE] = "LEDC",
|
||||
[ETS_SYSTIMER_TARGET0_INTR_SOURCE] = "SYSTIMER_TARGET0",
|
||||
[ETS_SYSTIMER_TARGET1_INTR_SOURCE] = "SYSTIMER_TARGET1",
|
||||
[ETS_SYSTIMER_TARGET2_INTR_SOURCE] = "SYSTIMER_TARGET2",
|
||||
[ETS_AHB_PDMA_IN_CH0_INTR_SOURCE] = "AHB_PDMA_IN_CH0",
|
||||
[ETS_AHB_PDMA_IN_CH1_INTR_SOURCE] = "AHB_PDMA_IN_CH1",
|
||||
[ETS_AHB_PDMA_IN_CH2_INTR_SOURCE] = "AHB_PDMA_IN_CH2",
|
||||
[ETS_AHB_PDMA_OUT_CH0_INTR_SOURCE] = "AHB_PDMA_OUT_CH0",
|
||||
[ETS_AHB_PDMA_OUT_CH1_INTR_SOURCE] = "AHB_PDMA_OUT_CH1",
|
||||
[ETS_AHB_PDMA_OUT_CH2_INTR_SOURCE] = "AHB_PDMA_OUT_CH2",
|
||||
[ETS_AXI_PDMA_IN_CH0_INTR_SOURCE] = "AXI_PDMA_IN_CH0",
|
||||
[ETS_AXI_PDMA_IN_CH1_INTR_SOURCE] = "AXI_PDMA_IN_CH1",
|
||||
[ETS_AXI_PDMA_IN_CH2_INTR_SOURCE] = "AXI_PDMA_IN_CH2",
|
||||
[ETS_AXI_PDMA_OUT_CH0_INTR_SOURCE] = "AXI_PDMA_OUT_CH0",
|
||||
[ETS_AXI_PDMA_OUT_CH1_INTR_SOURCE] = "AXI_PDMA_OUT_CH1",
|
||||
[ETS_AXI_PDMA_OUT_CH2_INTR_SOURCE] = "AXI_PDMA_OUT_CH2",
|
||||
[ETS_RSA_INTR_SOURCE] = "RSA",
|
||||
[ETS_AES_INTR_SOURCE] = "AES",
|
||||
[ETS_SHA_INTR_SOURCE] = "SHA",
|
||||
[ETS_ECC_INTR_SOURCE] = "ECC",
|
||||
[ETS_ECDSA_INTR_SOURCE] = "ECDSA",
|
||||
[ETS_KM_INTR_SOURCE] = "KM",
|
||||
[ETS_GPIO_INTR0_SOURCE] = "GPIO_INT0",
|
||||
[ETS_GPIO_INTR1_SOURCE] = "GPIO_INT1",
|
||||
[ETS_GPIO_INTR2_SOURCE] = "GPIO_INT2",
|
||||
[ETS_GPIO_INTR3_SOURCE] = "GPIO_INT3",
|
||||
[ETS_GPIO_PAD_COMP_INTR_SOURCE] = "GPIO_PAD_COMP",
|
||||
[ETS_FROM_CPU_INTR0_SOURCE] = "CPU_INT_FROM_CPU_0",
|
||||
[ETS_FROM_CPU_INTR1_SOURCE] = "CPU_INT_FROM_CPU_1",
|
||||
[ETS_FROM_CPU_INTR2_SOURCE] = "CPU_INT_FROM_CPU_2",
|
||||
[ETS_FROM_CPU_INTR3_SOURCE] = "CPU_INT_FROM_CPU_3",
|
||||
[ETS_CACHE_INTR_SOURCE] = "CACHE",
|
||||
[ETS_MSPI_INTR_SOURCE] = "MSPI",
|
||||
[ETS_CSI_BRIDGE_INTR_SOURCE] = "CSI_BRIDGE",
|
||||
[ETS_DSI_BRIDGE_INTR_SOURCE] = "DSI_BRIDGE",
|
||||
[ETS_CSI_INTR_SOURCE] = "CSI",
|
||||
[ETS_DSI_INTR_SOURCE] = "DSI",
|
||||
[ETS_GMII_PHY_INTR_SOURCE] = "GMII_PHY",
|
||||
[ETS_LPI_INTR_SOURCE] = "LPI",
|
||||
[ETS_PMT_INTR_SOURCE] = "PMT",
|
||||
[ETS_SBD_INTR_SOURCE] = "SBD",
|
||||
[ETS_USB_OTG_INTR_SOURCE] = "USB_OTG",
|
||||
[ETS_USB_OTG_ENDP_MULTI_PROC_INTR_SOURCE] = "USB_OTG_ENDP_MULTI_PROC",
|
||||
[ETS_JPEG_INTR_SOURCE] = "JPEG",
|
||||
[ETS_PPA_INTR_SOURCE] = "PPA",
|
||||
[ETS_CORE0_TRACE_INTR_SOURCE] = "CORE0_TRACE",
|
||||
[ETS_CORE1_TRACE_INTR_SOURCE] = "CORE1_TRACE",
|
||||
[ETS_HP_CORE_CTRL_INTR_SOURCE] = "HP_CORE_CTRL",
|
||||
[ETS_ISP_INTR_SOURCE] = "ISP",
|
||||
[ETS_I3C_MST_INTR_SOURCE] = "I3C_MST",
|
||||
[ETS_I3C_SLV_INTR_SOURCE] = "I3C_SLV",
|
||||
[ETS_USB_OTG11_CH0_INTR_SOURCE] = "USB_OTG11_CH0",
|
||||
[ETS_DMA2D_IN_CH0_INTR_SOURCE] = "DMA2D_IN_CH0",
|
||||
[ETS_DMA2D_IN_CH1_INTR_SOURCE] = "DMA2D_IN_CH1",
|
||||
[ETS_DMA2D_OUT_CH0_INTR_SOURCE] = "DMA2D_OUT_CH0",
|
||||
[ETS_DMA2D_OUT_CH1_INTR_SOURCE] = "DMA2D_OUT_CH1",
|
||||
[ETS_DMA2D_OUT_CH2_INTR_SOURCE] = "DMA2D_OUT_CH2",
|
||||
[ETS_PSRAM_MSPI_INTR_SOURCE] = "PSRAM_MSPI",
|
||||
[ETS_HP_SYSREG_INTR_SOURCE] = "HP_SYSREG",
|
||||
[ETS_PCNT_INTR_SOURCE] = "PCNT",
|
||||
[ETS_HP_PAU_INTR_SOURCE] = "HP_PAU",
|
||||
[ETS_HP_PARLIO_RX_INTR_SOURCE] = "HP_PARLIO_RX",
|
||||
[ETS_HP_PARLIO_TX_INTR_SOURCE] = "HP_PARLIO_TX",
|
||||
[ETS_H264_DMA2D_OUT_CH0_INTR_SOURCE] = "H264_DMA2D_OUT_CH0",
|
||||
[ETS_H264_DMA2D_OUT_CH1_INTR_SOURCE] = "H264_DMA2D_OUT_CH1",
|
||||
[ETS_H264_DMA2D_OUT_CH2_INTR_SOURCE] = "H264_DMA2D_OUT_CH2",
|
||||
[ETS_H264_DMA2D_OUT_CH3_INTR_SOURCE] = "H264_DMA2D_OUT_CH3",
|
||||
[ETS_H264_DMA2D_OUT_CH4_INTR_SOURCE] = "H264_DMA2D_OUT_CH4",
|
||||
[ETS_H264_DMA2D_IN_CH0_INTR_SOURCE] = "H264_DMA2D_IN_CH0",
|
||||
[ETS_H264_DMA2D_IN_CH1_INTR_SOURCE] = "H264_DMA2D_IN_CH1",
|
||||
[ETS_H264_DMA2D_IN_CH2_INTR_SOURCE] = "H264_DMA2D_IN_CH2",
|
||||
[ETS_H264_DMA2D_IN_CH3_INTR_SOURCE] = "H264_DMA2D_IN_CH3",
|
||||
[ETS_H264_DMA2D_IN_CH4_INTR_SOURCE] = "H264_DMA2D_IN_CH4",
|
||||
[ETS_H264_DMA2D_IN_CH5_INTR_SOURCE] = "H264_DMA2D_IN_CH5",
|
||||
[ETS_H264_REG_INTR_SOURCE] = "H264_REG",
|
||||
[ETS_ASSIST_DEBUG_INTR_SOURCE] = "ASSIST_DEBUG",
|
||||
};
|
||||
|
|
Ładowanie…
Reference in New Issue