From b9ecc1e57ab5b2ad1bdaacdb0c600f05b694853f Mon Sep 17 00:00:00 2001 From: Sudeep Mohanty Date: Wed, 13 Dec 2023 09:46:36 +0100 Subject: [PATCH] feat(ulp-riscv): Added SW interrupt capability for ULP RISC-V This commit adds a feature to ULP RISC-V where the user can trigger a software interrupt on the ULP RISC-V core. --- .../ulp_core/include/ulp_riscv_interrupt.h | 1 + .../ulp_core/include/ulp_riscv_utils.h | 23 ++++++++++++++- .../ulp_riscv/ulp_core/ulp_riscv_interrupt.c | 26 ++++++++++++++++- .../ulp/ulp_riscv/ulp_core/ulp_riscv_utils.c | 28 ++++++++++++++++++- 4 files changed, 75 insertions(+), 3 deletions(-) diff --git a/components/ulp/ulp_riscv/ulp_core/include/ulp_riscv_interrupt.h b/components/ulp/ulp_riscv/ulp_core/include/ulp_riscv_interrupt.h index b452707379..137129f517 100644 --- a/components/ulp/ulp_riscv/ulp_core/include/ulp_riscv_interrupt.h +++ b/components/ulp/ulp_riscv/ulp_core/include/ulp_riscv_interrupt.h @@ -16,6 +16,7 @@ extern "C" /* ULP RISC-V Interrupt sources */ typedef enum { + ULP_RISCV_SW_INTR_SOURCE = 0, /**< Interrupt triggered by SW */ ULP_RISCV_MAX_INTR_SOURCE, /**< Total number of ULP RISC-V interrupt sources */ } ulp_riscv_interrupt_source_t; diff --git a/components/ulp/ulp_riscv/ulp_core/include/ulp_riscv_utils.h b/components/ulp/ulp_riscv/ulp_core/include/ulp_riscv_utils.h index c4e89b9906..274395d3f1 100644 --- a/components/ulp/ulp_riscv/ulp_core/include/ulp_riscv_utils.h +++ b/components/ulp/ulp_riscv/ulp_core/include/ulp_riscv_utils.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,6 +13,7 @@ extern "C" { #include "sdkconfig.h" #include #include "ulp_riscv_register_ops.h" +#include "ulp_riscv_interrupt.h" /** * @brief Wakeup main CPU from sleep or deep sleep. @@ -112,6 +113,26 @@ void static inline ulp_riscv_delay_cycles(uint32_t cycles) */ void ulp_riscv_gpio_wakeup_clear(void); +/** + * @brief Enable ULP RISC-V SW Interrupt + * + * @param handler Interrupt handler + * @param arg Interrupt handler argument + */ +void ulp_riscv_enable_sw_intr(intr_handler_t handler, void *arg); + +/** + * @brief Disable ULP RISC-V SW Interrupt + */ +void ulp_riscv_disable_sw_intr(void); + +/** + * @brief Trigger ULP RISC-V SW Interrupt + * + * @note The SW interrupt will only trigger if it has been enabled previously using ulp_riscv_enable_sw_intr(). + */ +void ulp_riscv_trigger_sw_intr(void); + #ifdef __cplusplus } #endif diff --git a/components/ulp/ulp_riscv/ulp_core/ulp_riscv_interrupt.c b/components/ulp/ulp_riscv/ulp_core/ulp_riscv_interrupt.c index 1c105383fa..4f782df63d 100644 --- a/components/ulp/ulp_riscv/ulp_core/ulp_riscv_interrupt.c +++ b/components/ulp/ulp_riscv/ulp_core/ulp_riscv_interrupt.c @@ -6,6 +6,7 @@ #include #include "ulp_riscv_register_ops.h" #include "ulp_riscv_interrupt.h" +#include "soc/sens_reg.h" #define ULP_RISCV_TIMER_INT (1 << 0U) /* Internal Timer Interrupt */ #define ULP_RISCV_EBREAK_ECALL_ILLEGAL_INSN_INT (1 << 1U) /* EBREAK, ECALL or Illegal instruction */ @@ -57,6 +58,25 @@ esp_err_t ulp_riscv_intr_free(ulp_riscv_interrupt_source_t source) return ESP_OK; } +/* This function - + * - Checks RTC peripheral interrupt status bit + * - Calls interrupt handler if it is registered + * - Clears interrupt bit + */ +static inline void ulp_riscv_handle_rtc_periph_intr(uint32_t status) +{ + /* SW interrupt */ + if (status & SENS_COCPU_SW_INT_ST) { + const ulp_riscv_intr_handler_t* entry = &s_intr_handlers[ULP_RISCV_SW_INTR_SOURCE]; + + if (entry->handler) { + entry->handler(entry->arg); + } + + SET_PERI_REG_MASK(SENS_SAR_COCPU_INT_CLR_REG, SENS_COCPU_SW_INT_CLR); + } +} + /* This is the global interrupt handler for ULP RISC-V. * It is called from ulp_riscv_vectors.S */ @@ -71,7 +91,11 @@ void __attribute__((weak)) _ulp_riscv_interrupt_handler(uint32_t q1) /* External/Peripheral interrupts */ if (q1 & ULP_RISCV_PERIPHERAL_INTERRUPT) { - /* TODO: RTC Peripheral interrupts */ + /* RTC Peripheral interrupts */ + uint32_t cocpu_int_st = READ_PERI_REG(SENS_SAR_COCPU_INT_ST_REG); + if (cocpu_int_st) { + ulp_riscv_handle_rtc_periph_intr(cocpu_int_st); + } /* TODO: RTC IO interrupts */ diff --git a/components/ulp/ulp_riscv/ulp_core/ulp_riscv_utils.c b/components/ulp/ulp_riscv/ulp_core/ulp_riscv_utils.c index 293c16080c..e1b88676b2 100644 --- a/components/ulp/ulp_riscv/ulp_core/ulp_riscv_utils.c +++ b/components/ulp/ulp_riscv/ulp_core/ulp_riscv_utils.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -9,6 +9,7 @@ #include "soc/soc.h" #include "soc/rtc_cntl_reg.h" #include "soc/soc_ulp.h" +#include "soc/sens_reg.h" void ulp_riscv_rescue_from_monitor(void) { @@ -46,3 +47,28 @@ void ulp_riscv_gpio_wakeup_clear(void) { SET_PERI_REG_MASK(RTC_CNTL_ULP_CP_TIMER_REG, RTC_CNTL_ULP_CP_GPIO_WAKEUP_CLR); } + +void ulp_riscv_enable_sw_intr(intr_handler_t handler, void *arg) +{ + /* Enable ULP RISC-V SW interrupt */ + SET_PERI_REG_MASK(SENS_SAR_COCPU_INT_ENA_REG, SENS_COCPU_SW_INT_ENA); + + /* Register interrupt handler */ + if (handler) { + ulp_riscv_intr_alloc(ULP_RISCV_SW_INTR_SOURCE, handler, arg); + } +} + +void ulp_riscv_disable_sw_intr(void) +{ + /* Disable ULP RISC-V SW interrupt */ + CLEAR_PERI_REG_MASK(SENS_SAR_COCPU_INT_ENA_REG, SENS_COCPU_SW_INT_ENA); + + /* De-register interrupt handler */ + ulp_riscv_intr_free(ULP_RISCV_SW_INTR_SOURCE); +} + +void ulp_riscv_trigger_sw_intr(void) +{ + SET_PERI_REG_MASK(RTC_CNTL_COCPU_CTRL_REG, RTC_CNTL_COCPU_SW_INT_TRIGGER); +}