interrupt_controller: intc_esp32c3: added intc driver
For esp32c3 and replaces the hardcoded interrupt attaching procedures with this new driver. Signed-off-by: Felipe Neves <felipe.neves@espressif.com>
This commit is contained in:
parent
a8f02ed5ee
commit
b97c2da2f2
12 changed files with 381 additions and 37 deletions
|
@ -23,5 +23,6 @@ zephyr_library_sources_ifdef(CONFIG_RV32M1_INTMUX intc_rv32m1_intmux.c
|
|||
zephyr_library_sources_ifdef(CONFIG_SAM0_EIC intc_sam0_eic.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_SHARED_IRQ intc_shared_irq.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_INTC_ESP32 intc_esp32.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_INTC_ESP32C3 intc_esp32c3.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_SWERV_PIC intc_swerv_pic.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_VEXRISCV_LITEX_IRQ intc_vexriscv_litex.c)
|
||||
|
|
|
@ -69,6 +69,8 @@ source "drivers/interrupt_controller/Kconfig.intel_vtd"
|
|||
|
||||
source "drivers/interrupt_controller/Kconfig.esp32"
|
||||
|
||||
source "drivers/interrupt_controller/Kconfig.esp32c3"
|
||||
|
||||
source "drivers/interrupt_controller/Kconfig.xec"
|
||||
|
||||
endmenu
|
||||
|
|
10
drivers/interrupt_controller/Kconfig.esp32c3
Normal file
10
drivers/interrupt_controller/Kconfig.esp32c3
Normal file
|
@ -0,0 +1,10 @@
|
|||
# Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config INTC_ESP32C3
|
||||
bool "Enables ESP32C3 interrupt controller driver"
|
||||
depends on SOC_ESP32C3
|
||||
default y
|
||||
help
|
||||
Enables the esp32c3 interrupt controller driver to handle ISR
|
||||
management at SoC level.
|
193
drivers/interrupt_controller/intc_esp32c3.c
Normal file
193
drivers/interrupt_controller/intc_esp32c3.c
Normal file
|
@ -0,0 +1,193 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <soc/periph_defs.h>
|
||||
#include <limits.h>
|
||||
#include <assert.h>
|
||||
#include "soc/soc.h"
|
||||
#include <soc.h>
|
||||
#include <zephyr.h>
|
||||
#include <drivers/interrupt_controller/intc_esp32c3.h>
|
||||
#include <sw_isr_table.h>
|
||||
|
||||
#include <logging/log.h>
|
||||
LOG_MODULE_REGISTER(intc_esp32c3, CONFIG_LOG_DEFAULT_LEVEL);
|
||||
|
||||
#define ESP32C3_INTC_DEFAULT_PRIORITY 15
|
||||
#define ESP32C3_INTC_DEFAULT_THRESHOLD 1
|
||||
#define ESP32C3_INTC_DISABLED_SLOT 31
|
||||
#define ESP32C3_INTC_SRCS_PER_IRQ 2
|
||||
#define ESP32C3_INTC_AVAILABLE_IRQS 30
|
||||
|
||||
static uint32_t esp_intr_enabled_mask[2] = {0, 0};
|
||||
|
||||
static void esp_intr_default_isr(const void *arg)
|
||||
{
|
||||
ARG_UNUSED(arg);
|
||||
ulong_t mcause;
|
||||
|
||||
__asm__ volatile("csrr %0, mcause" : "=r" (mcause));
|
||||
mcause &= SOC_MCAUSE_EXP_MASK;
|
||||
|
||||
LOG_DBG("Spurious interrupt, mcause: %ld, source %d", mcause, soc_intr_get_next_source());
|
||||
}
|
||||
|
||||
static uint32_t esp_intr_find_irq_for_source(uint32_t source)
|
||||
{
|
||||
/* in general case, each 2 sources goes routed to
|
||||
* 1 IRQ line.
|
||||
*/
|
||||
uint32_t irq = (source / ESP32C3_INTC_SRCS_PER_IRQ);
|
||||
|
||||
if (irq > ESP32C3_INTC_AVAILABLE_IRQS) {
|
||||
LOG_DBG("Clamping the source: %d no more IRQs available", source);
|
||||
irq = ESP32C3_INTC_AVAILABLE_IRQS;
|
||||
} else if (irq == 0) {
|
||||
irq = 1;
|
||||
}
|
||||
|
||||
LOG_DBG("Found IRQ: %d for source: %d", irq, source);
|
||||
|
||||
return irq;
|
||||
}
|
||||
|
||||
void esp_intr_initialize(void)
|
||||
{
|
||||
/* IRQ 31 is reserved for disabled interrupts,
|
||||
* so route all sources to it
|
||||
*/
|
||||
for (int i = 0 ; i < ESP32C3_INTC_AVAILABLE_IRQS + 2; i++) {
|
||||
irq_disable(i);
|
||||
}
|
||||
|
||||
for (int i = 0; i < ETS_MAX_INTR_SOURCE; i++) {
|
||||
esp_rom_intr_matrix_set(0,
|
||||
i,
|
||||
ESP32C3_INTC_DISABLED_SLOT);
|
||||
|
||||
irq_connect_dynamic(i,
|
||||
ESP32C3_INTC_DEFAULT_PRIORITY,
|
||||
esp_intr_default_isr,
|
||||
NULL,
|
||||
0);
|
||||
}
|
||||
|
||||
/* set global esp32c3's INTC masking level */
|
||||
esprv_intc_int_set_threshold(ESP32C3_INTC_DEFAULT_THRESHOLD);
|
||||
}
|
||||
|
||||
int esp_intr_alloc(int source,
|
||||
int flags,
|
||||
isr_handler_t handler,
|
||||
void *arg,
|
||||
void **ret_handle)
|
||||
{
|
||||
ARG_UNUSED(flags);
|
||||
ARG_UNUSED(ret_handle);
|
||||
|
||||
if (handler == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (source < 0 || source >= ETS_MAX_INTR_SOURCE) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
uint32_t key = irq_lock();
|
||||
uint32_t irq = esp_intr_find_irq_for_source(source);
|
||||
|
||||
esp_rom_intr_matrix_set(0, source, irq);
|
||||
|
||||
irq_connect_dynamic(source,
|
||||
ESP32C3_INTC_DEFAULT_PRIORITY,
|
||||
handler,
|
||||
arg,
|
||||
0);
|
||||
|
||||
if (source < 32) {
|
||||
esp_intr_enabled_mask[0] |= (1 << source);
|
||||
} else {
|
||||
esp_intr_enabled_mask[1] |= (1 << (source - 32));
|
||||
}
|
||||
|
||||
LOG_DBG("Enabled isrs -- 0: 0x%X -- 1: 0x%X",
|
||||
esp_intr_enabled_mask[0], esp_intr_enabled_mask[1]);
|
||||
|
||||
irq_unlock(key);
|
||||
irq_enable(irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int esp_intr_disable(int source)
|
||||
{
|
||||
if (source < 0 || source >= ETS_MAX_INTR_SOURCE) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
uint32_t key = irq_lock();
|
||||
|
||||
esp_rom_intr_matrix_set(source,
|
||||
source,
|
||||
ESP32C3_INTC_DISABLED_SLOT);
|
||||
|
||||
if (source < 32) {
|
||||
esp_intr_enabled_mask[0] &= ~(1 << source);
|
||||
} else {
|
||||
esp_intr_enabled_mask[1] &= ~(1 << (source - 32));
|
||||
}
|
||||
|
||||
LOG_DBG("Enabled isrs -- 0: 0x%X -- 1: 0x%X",
|
||||
esp_intr_enabled_mask[0], esp_intr_enabled_mask[1]);
|
||||
|
||||
irq_unlock(key);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int esp_intr_enable(int source)
|
||||
{
|
||||
if (source < 0 || source >= ETS_MAX_INTR_SOURCE) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
uint32_t key = irq_lock();
|
||||
uint32_t irq = esp_intr_find_irq_for_source(source);
|
||||
|
||||
irq_disable(irq);
|
||||
esp_rom_intr_matrix_set(0, source, irq);
|
||||
|
||||
if (source < 32) {
|
||||
esp_intr_enabled_mask[0] |= (1 << source);
|
||||
} else {
|
||||
esp_intr_enabled_mask[1] |= (1 << (source - 32));
|
||||
}
|
||||
|
||||
LOG_DBG("Enabled isrs -- 0: 0x%X -- 1: 0x%X",
|
||||
esp_intr_enabled_mask[0], esp_intr_enabled_mask[1]);
|
||||
|
||||
irq_enable(irq);
|
||||
irq_unlock(key);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t esp_intr_get_enabled_intmask(int status_mask_number)
|
||||
{
|
||||
LOG_DBG("Enabled isrs -- 0: 0x%X -- 1: 0x%X",
|
||||
esp_intr_enabled_mask[0], esp_intr_enabled_mask[1]);
|
||||
|
||||
if (status_mask_number == 0) {
|
||||
return esp_intr_enabled_mask[0];
|
||||
} else {
|
||||
return esp_intr_enabled_mask[1];
|
||||
}
|
||||
}
|
|
@ -13,12 +13,11 @@
|
|||
#include <rom/ets_sys.h>
|
||||
#include <esp_attr.h>
|
||||
|
||||
#include <drivers/interrupt_controller/intc_esp32c3.h>
|
||||
#include <drivers/timer/system_timer.h>
|
||||
#include <sys_clock.h>
|
||||
#include <soc.h>
|
||||
|
||||
#define SYS_TIMER_CPU_IRQ 16
|
||||
|
||||
#define CYC_PER_TICK ((uint32_t)((uint64_t)sys_clock_hw_cycles_per_sec() \
|
||||
/ (uint64_t)CONFIG_SYS_CLOCK_TICKS_PER_SEC))
|
||||
#define MAX_CYC 0xffffffffu
|
||||
|
@ -45,7 +44,6 @@ static uint64_t systimer_alarm(void)
|
|||
static void sys_timer_isr(const void *arg)
|
||||
{
|
||||
ARG_UNUSED(arg);
|
||||
|
||||
systimer_ll_clear_alarm_int(SYSTIMER_ALARM_0);
|
||||
|
||||
k_spinlock_key_t key = k_spin_lock(&lock);
|
||||
|
@ -72,17 +70,18 @@ int sys_clock_driver_init(const struct device *dev)
|
|||
{
|
||||
ARG_UNUSED(dev);
|
||||
|
||||
esp_rom_intr_matrix_set(0,
|
||||
ETS_SYSTIMER_TARGET0_EDGE_INTR_SOURCE,
|
||||
SYS_TIMER_CPU_IRQ);
|
||||
IRQ_CONNECT(SYS_TIMER_CPU_IRQ, 0, sys_timer_isr, NULL, 0);
|
||||
esp_intr_alloc(ETS_SYSTIMER_TARGET0_EDGE_INTR_SOURCE,
|
||||
0,
|
||||
sys_timer_isr,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
systimer_hal_init();
|
||||
systimer_hal_connect_alarm_counter(SYSTIMER_ALARM_0, SYSTIMER_COUNTER_1);
|
||||
systimer_hal_enable_counter(SYSTIMER_COUNTER_1);
|
||||
systimer_hal_counter_can_stall_by_cpu(SYSTIMER_COUNTER_1, 0, true);
|
||||
last_count = systimer_alarm();
|
||||
set_systimer_alarm(last_count + CYC_PER_TICK);
|
||||
irq_enable(SYS_TIMER_CPU_IRQ);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
89
include/drivers/interrupt_controller/intc_esp32c3.h
Normal file
89
include/drivers/interrupt_controller/intc_esp32c3.h
Normal file
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_INCLUDE_DRIVERS_ESP_INTR_ALLOC_H__
|
||||
#define ZEPHYR_INCLUDE_DRIVERS_ESP_INTR_ALLOC_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <soc.h>
|
||||
/*
|
||||
* Interrupt allocation flags - These flags can be used to specify
|
||||
* which interrupt qualities the code calling esp_intr_alloc* needs.
|
||||
*
|
||||
*/
|
||||
|
||||
/* Keep the LEVELx values as they are here; they match up with (1<<level) */
|
||||
#define ESP_INTR_FLAG_LEVEL1 (1<<1) /* Accept a Level 1 int vector, lowest priority */
|
||||
#define ESP_INTR_FLAG_EDGE (1<<9) /* Edge-triggered interrupt */
|
||||
|
||||
/* Function prototype for interrupt handler function */
|
||||
typedef void (*isr_handler_t)(const void *arg);
|
||||
|
||||
/**
|
||||
* @brief Initializes interrupt table to its defaults
|
||||
*/
|
||||
void esp_intr_initialize(void);
|
||||
|
||||
/**
|
||||
* @brief Allocate an interrupt with the given parameters.
|
||||
*
|
||||
* This finds an interrupt that matches the restrictions as given in the flags
|
||||
* parameter, maps the given interrupt source to it and hooks up the given
|
||||
* interrupt handler (with optional argument) as well. If needed, it can return
|
||||
* a handle for the interrupt as well.
|
||||
*
|
||||
* @param source The interrupt source.
|
||||
* @param flags An ORred mask of the ESP_INTR_FLAG_* defines. These restrict the
|
||||
* choice of interrupts that this routine can choose from. If this value
|
||||
* is 0, it will default to allocating a non-shared interrupt of level
|
||||
* 1, 2 or 3. If this is ESP_INTR_FLAG_SHARED, it will allocate a shared
|
||||
* interrupt of level 1. Setting ESP_INTR_FLAG_INTRDISABLED will return
|
||||
* from this function with the interrupt disabled.
|
||||
* @param handler The interrupt handler.
|
||||
* @param arg Optional argument for passed to the interrupt handler
|
||||
* @param ret_handle Pointer to a struct intr_handle_data_t pointer to store a handle that can
|
||||
* later be used to request details or free the interrupt. Can be NULL if no handle
|
||||
* is required.
|
||||
*
|
||||
* @return -EINVAL if the combination of arguments is invalid.
|
||||
* -ENODEV No free interrupt found with the specified flags
|
||||
* 0 otherwise
|
||||
*/
|
||||
int esp_intr_alloc(int source,
|
||||
int flags,
|
||||
isr_handler_t handler,
|
||||
void *arg,
|
||||
void **ret_handle);
|
||||
|
||||
/**
|
||||
* @brief Disable the interrupt associated with the source
|
||||
*
|
||||
* @param source The interrupt source
|
||||
*
|
||||
* @return -EINVAL if the combination of arguments is invalid.
|
||||
* 0 otherwise
|
||||
*/
|
||||
int esp_intr_disable(int source);
|
||||
|
||||
/**
|
||||
* @brief Enable the interrupt associated with the source
|
||||
*
|
||||
* @param source The interrupt source
|
||||
* @return -EINVAL if the combination of arguments is invalid.
|
||||
* 0 otherwise
|
||||
*/
|
||||
int esp_intr_enable(int source);
|
||||
|
||||
/**
|
||||
* @brief Gets the current enabled interrupts
|
||||
*
|
||||
* @param status_mask_number the status mask can be 0 or 1
|
||||
* @return bitmask of enabled interrupt sources
|
||||
*/
|
||||
uint32_t esp_intr_get_enabled_intmask(int status_mask_number);
|
||||
|
||||
#endif
|
|
@ -4,5 +4,6 @@ zephyr_sources(
|
|||
idle.c
|
||||
vectors.S
|
||||
soc_irq.S
|
||||
soc_irq.c
|
||||
soc.c
|
||||
)
|
||||
|
|
|
@ -9,7 +9,7 @@ config SOC
|
|||
default "esp32c3"
|
||||
|
||||
config NUM_IRQS
|
||||
default 32
|
||||
default 62
|
||||
|
||||
config GEN_ISR_TABLES
|
||||
default y
|
||||
|
|
|
@ -13,18 +13,15 @@
|
|||
#include <soc/cache_memory.h>
|
||||
#include "hal/soc_ll.h"
|
||||
#include "esp_spi_flash.h"
|
||||
#include <riscv/interrupt.h>
|
||||
#include <soc/interrupt_reg.h>
|
||||
#include <drivers/interrupt_controller/intc_esp32c3.h>
|
||||
|
||||
#include <kernel_structs.h>
|
||||
#include <string.h>
|
||||
#include <toolchain/gcc.h>
|
||||
#include <soc.h>
|
||||
|
||||
#define ESP32C3_INTC_DEFAULT_PRIO 15
|
||||
|
||||
extern void _PrepC(void);
|
||||
extern void esprv_intc_int_set_threshold(int priority_threshold);
|
||||
|
||||
/*
|
||||
* This is written in C rather than assembly since, during the port bring up,
|
||||
|
@ -94,15 +91,15 @@ void __attribute__((section(".iram1"))) __start(void)
|
|||
esp_rom_cache_set_idrom_mmu_size(cache_mmu_irom_size,
|
||||
CACHE_DROM_MMU_MAX_END - cache_mmu_irom_size);
|
||||
|
||||
/* set global esp32c3's INTC masking level */
|
||||
esprv_intc_int_set_threshold(1);
|
||||
|
||||
/* Enable wireless phy subsystem clock,
|
||||
* This needs to be done before the kernel starts
|
||||
*/
|
||||
REG_CLR_BIT(SYSTEM_WIFI_CLK_EN_REG, SYSTEM_WIFI_CLK_SDIOSLAVE_EN);
|
||||
SET_PERI_REG_MASK(SYSTEM_WIFI_CLK_EN_REG, SYSTEM_WIFI_CLK_EN);
|
||||
|
||||
/*Initialize the esp32c3 interrupt controller */
|
||||
esp_intr_initialize();
|
||||
|
||||
/* Start Zephyr */
|
||||
_PrepC();
|
||||
|
||||
|
@ -167,24 +164,3 @@ void sys_arch_reboot(int type)
|
|||
{
|
||||
esp_restart_noos();
|
||||
}
|
||||
|
||||
void arch_irq_enable(unsigned int irq)
|
||||
{
|
||||
uint32_t key = irq_lock();
|
||||
|
||||
esprv_intc_int_set_priority(irq, ESP32C3_INTC_DEFAULT_PRIO);
|
||||
esprv_intc_int_set_type(irq, 0);
|
||||
esprv_intc_int_enable(1 << irq);
|
||||
|
||||
irq_unlock(key);
|
||||
}
|
||||
|
||||
void arch_irq_disable(unsigned int irq)
|
||||
{
|
||||
esprv_intc_int_disable(1 << irq);
|
||||
}
|
||||
|
||||
int arch_irq_is_enabled(unsigned int irq)
|
||||
{
|
||||
return (REG_READ(INTERRUPT_CORE0_CPU_INT_ENABLE_REG) & (1 << irq));
|
||||
}
|
||||
|
|
|
@ -41,6 +41,8 @@ extern void esp_rom_uart_tx_wait_idle(uint8_t uart_no);
|
|||
extern STATUS esp_rom_uart_tx_one_char(uint8_t chr);
|
||||
extern STATUS esp_rom_uart_rx_one_char(uint8_t *chr);
|
||||
extern void esp_rom_ets_set_user_start(uint32_t start);
|
||||
extern void esprv_intc_int_set_threshold(int priority_threshold);
|
||||
uint32_t soc_intr_get_next_source(void);
|
||||
|
||||
#endif /* _ASMLANGUAGE */
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
/* Exports */
|
||||
GTEXT(__soc_is_irq)
|
||||
GTEXT(__soc_handle_irq)
|
||||
GTEXT(soc_intr_get_next_source)
|
||||
|
||||
SECTION_FUNC(exception.other, __soc_is_irq)
|
||||
csrr a0, mcause
|
||||
|
@ -16,4 +17,10 @@ SECTION_FUNC(exception.other, __soc_is_irq)
|
|||
ret
|
||||
|
||||
SECTION_FUNC(exception.other, __soc_handle_irq)
|
||||
addi sp, sp,-4
|
||||
sw ra, 0x00(sp)
|
||||
la t1, soc_intr_get_next_source
|
||||
jalr ra, t1
|
||||
lw ra, 0x00(sp)
|
||||
addi sp, sp, 4
|
||||
ret
|
||||
|
|
64
soc/riscv/esp32c3/soc_irq.c
Normal file
64
soc/riscv/esp32c3/soc_irq.c
Normal file
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <soc/rtc_cntl_reg.h>
|
||||
#include <soc/timer_group_reg.h>
|
||||
#include <soc/gpio_reg.h>
|
||||
#include <soc/syscon_reg.h>
|
||||
#include <soc/system_reg.h>
|
||||
#include <soc/cache_memory.h>
|
||||
#include "hal/soc_ll.h"
|
||||
#include <riscv/interrupt.h>
|
||||
#include <soc/interrupt_reg.h>
|
||||
#include <soc/periph_defs.h>
|
||||
#include <drivers/interrupt_controller/intc_esp32c3.h>
|
||||
|
||||
#include <kernel_structs.h>
|
||||
#include <string.h>
|
||||
#include <toolchain/gcc.h>
|
||||
#include <soc.h>
|
||||
|
||||
#define ESP32C3_INTC_DEFAULT_PRIO 15
|
||||
#define ESP32C3_INTSTATUS_SLOT1_THRESHOLD 32
|
||||
|
||||
void arch_irq_enable(unsigned int irq)
|
||||
{
|
||||
uint32_t key = irq_lock();
|
||||
|
||||
esprv_intc_int_set_priority(irq, ESP32C3_INTC_DEFAULT_PRIO);
|
||||
esprv_intc_int_set_type(irq, INTR_TYPE_LEVEL);
|
||||
esprv_intc_int_enable(1 << irq);
|
||||
irq_unlock(key);
|
||||
}
|
||||
|
||||
void arch_irq_disable(unsigned int irq)
|
||||
{
|
||||
esprv_intc_int_disable(1 << irq);
|
||||
}
|
||||
|
||||
int arch_irq_is_enabled(unsigned int irq)
|
||||
{
|
||||
return (REG_READ(INTERRUPT_CORE0_CPU_INT_ENABLE_REG) & (1 << irq));
|
||||
}
|
||||
|
||||
uint32_t soc_intr_get_next_source(void)
|
||||
{
|
||||
uint32_t status;
|
||||
uint32_t source;
|
||||
|
||||
status = REG_READ(INTERRUPT_CORE0_INTR_STATUS_0_REG) &
|
||||
esp_intr_get_enabled_intmask(0);
|
||||
|
||||
if (status) {
|
||||
source = __builtin_ffs(status) - 1;
|
||||
} else {
|
||||
status = REG_READ(INTERRUPT_CORE0_INTR_STATUS_1_REG) &
|
||||
esp_intr_get_enabled_intmask(1);
|
||||
source = (__builtin_ffs(status) - 1 + ESP32C3_INTSTATUS_SLOT1_THRESHOLD);
|
||||
}
|
||||
|
||||
return source;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue