diff --git a/components/ulp/cmake/CMakeLists.txt b/components/ulp/cmake/CMakeLists.txt index 4b174402cf..e396502853 100644 --- a/components/ulp/cmake/CMakeLists.txt +++ b/components/ulp/cmake/CMakeLists.txt @@ -66,6 +66,7 @@ if(ULP_COCPU_IS_RISCV) "${IDF_PATH}/components/ulp/ulp_riscv/ulp_core/ulp_riscv_i2c.c" "${IDF_PATH}/components/ulp/ulp_riscv/ulp_core/ulp_riscv_utils.c" "${IDF_PATH}/components/ulp/ulp_riscv/ulp_core/ulp_riscv_touch.c" + "${IDF_PATH}/components/ulp/ulp_riscv/ulp_core/ulp_riscv_gpio.c" "${IDF_PATH}/components/ulp/ulp_riscv/ulp_core/ulp_riscv_interrupt.c") target_link_options(${ULP_APP_NAME} PRIVATE "-nostartfiles") diff --git a/components/ulp/ulp_riscv/ulp_core/include/ulp_riscv_gpio.h b/components/ulp/ulp_riscv/ulp_core/include/ulp_riscv_gpio.h index c675279152..41c4dbbc2f 100644 --- a/components/ulp/ulp_riscv/ulp_core/include/ulp_riscv_gpio.h +++ b/components/ulp/ulp_riscv/ulp_core/include/ulp_riscv_gpio.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2010-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,6 +13,7 @@ extern "C" { #include "soc/rtc_io_reg.h" #include "soc/sens_reg.h" #include "ulp_riscv_register_ops.h" +#include "ulp_riscv_interrupt.h" typedef enum { GPIO_NUM_0 = 0, /*!< GPIO0, input and output */ @@ -35,10 +36,21 @@ typedef enum { GPIO_NUM_17 = 17, /*!< GPIO17, input and output */ GPIO_NUM_18 = 18, /*!< GPIO18, input and output */ GPIO_NUM_19 = 19, /*!< GPIO19, input and output */ - GPIO_NUM_20 = 20, + GPIO_NUM_20 = 20, /*!< GPIO20, input and output */ GPIO_NUM_21 = 21, /*!< GPIO21, input and output */ + GPIO_NUM_MAX, } gpio_num_t; +typedef enum { + ULP_RISCV_GPIO_INTR_DISABLE = 0, /*!< Disable RTC GPIO interrupt */ + ULP_RISCV_GPIO_INTR_POSEDGE = 1, /*!< RTC GPIO interrupt type : rising edge */ + ULP_RISCV_GPIO_INTR_NEGEDGE = 2, /*!< RTC GPIO interrupt type : falling edge */ + ULP_RISCV_GPIO_INTR_ANYEDGE = 3, /*!< RTC GPIO interrupt type : both rising and falling edge */ + ULP_RISCV_GPIO_INTR_LOW_LEVEL = 4, /*!< RTC GPIO interrupt type : input low level trigger */ + ULP_RISCV_GPIO_INTR_HIGH_LEVEL = 5, /*!< RTC GPIO interrupt type : input high level trigger */ + ULP_RISCV_GPIO_INTR_MAX +} ulp_riscv_gpio_int_type_t; + typedef enum { RTCIO_MODE_OUTPUT = 0, RTCIO_MODE_OUTPUT_OD = 1, @@ -119,6 +131,27 @@ static inline void ulp_riscv_gpio_pulldown_disable(gpio_num_t gpio_num) CLEAR_PERI_REG_MASK(RTC_IO_TOUCH_PAD0_REG + gpio_num*4, RTC_IO_TOUCH_PAD0_RDE); } +/** + * @brief Set RTC IO interrupt type and handler + * + * @param gpio_num GPIO number + * @param intr_type Interrupt type (See rtc_io_types.h) + * @param handler Interrupt handler + * @param arg Interrupt handler argument + * + * @return ESP_OK on success + */ +esp_err_t ulp_riscv_gpio_isr_register(gpio_num_t gpio_num, ulp_riscv_gpio_int_type_t intr_type, intr_handler_t handler, void *arg); + +/** + * @brief Remove RTC IO interrupt handler + * + * @param gpio_num GPIO number + * + * @return ESP_OK on success + */ +esp_err_t ulp_riscv_gpio_isr_deregister(gpio_num_t gpio_num); + #ifdef __cplusplus } #endif 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 137129f517..746acf095e 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 @@ -17,6 +17,28 @@ extern "C" /* ULP RISC-V Interrupt sources */ typedef enum { ULP_RISCV_SW_INTR_SOURCE = 0, /**< Interrupt triggered by SW */ + ULP_RISCV_RTCIO0_INTR_SOURCE, /**< Interrupt triggered by RTCIO 0 */ + ULP_RISCV_RTCIO1_INTR_SOURCE, /**< Interrupt triggered by RTCIO 1 */ + ULP_RISCV_RTCIO2_INTR_SOURCE, /**< Interrupt triggered by RTCIO 2 */ + ULP_RISCV_RTCIO3_INTR_SOURCE, /**< Interrupt triggered by RTCIO 3 */ + ULP_RISCV_RTCIO4_INTR_SOURCE, /**< Interrupt triggered by RTCIO 4 */ + ULP_RISCV_RTCIO5_INTR_SOURCE, /**< Interrupt triggered by RTCIO 5 */ + ULP_RISCV_RTCIO6_INTR_SOURCE, /**< Interrupt triggered by RTCIO 6 */ + ULP_RISCV_RTCIO7_INTR_SOURCE, /**< Interrupt triggered by RTCIO 7 */ + ULP_RISCV_RTCIO8_INTR_SOURCE, /**< Interrupt triggered by RTCIO 8 */ + ULP_RISCV_RTCIO9_INTR_SOURCE, /**< Interrupt triggered by RTCIO 9 */ + ULP_RISCV_RTCIO10_INTR_SOURCE, /**< Interrupt triggered by RTCIO 10 */ + ULP_RISCV_RTCIO11_INTR_SOURCE, /**< Interrupt triggered by RTCIO 11 */ + ULP_RISCV_RTCIO12_INTR_SOURCE, /**< Interrupt triggered by RTCIO 12 */ + ULP_RISCV_RTCIO13_INTR_SOURCE, /**< Interrupt triggered by RTCIO 13 */ + ULP_RISCV_RTCIO14_INTR_SOURCE, /**< Interrupt triggered by RTCIO 14 */ + ULP_RISCV_RTCIO15_INTR_SOURCE, /**< Interrupt triggered by RTCIO 15 */ + ULP_RISCV_RTCIO16_INTR_SOURCE, /**< Interrupt triggered by RTCIO 16 */ + ULP_RISCV_RTCIO17_INTR_SOURCE, /**< Interrupt triggered by RTCIO 17 */ + ULP_RISCV_RTCIO18_INTR_SOURCE, /**< Interrupt triggered by RTCIO 18 */ + ULP_RISCV_RTCIO19_INTR_SOURCE, /**< Interrupt triggered by RTCIO 19 */ + ULP_RISCV_RTCIO20_INTR_SOURCE, /**< Interrupt triggered by RTCIO 20 */ + ULP_RISCV_RTCIO21_INTR_SOURCE, /**< Interrupt triggered by RTCIO 21 */ 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/ulp_riscv_gpio.c b/components/ulp/ulp_riscv/ulp_core/ulp_riscv_gpio.c new file mode 100644 index 0000000000..61de5a30c0 --- /dev/null +++ b/components/ulp/ulp_riscv/ulp_core/ulp_riscv_gpio.c @@ -0,0 +1,33 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "ulp_riscv_gpio.h" +#include "include/ulp_riscv_gpio.h" + +esp_err_t ulp_riscv_gpio_isr_register(gpio_num_t gpio_num, ulp_riscv_gpio_int_type_t intr_type, intr_handler_t handler, void *arg) +{ + if (gpio_num < 0 || gpio_num >= GPIO_NUM_MAX) { + return ESP_ERR_INVALID_ARG; + } + + if (intr_type < 0 || intr_type >= ULP_RISCV_GPIO_INTR_MAX) { + return ESP_ERR_INVALID_ARG; + } + + if (!handler) { + return ESP_ERR_INVALID_ARG; + } + + /* Set the interrupt type */ + REG_SET_FIELD(RTC_GPIO_PIN0_REG + 4*gpio_num, RTC_GPIO_PIN0_INT_TYPE, intr_type); + + /* Set the interrupt handler */ + return ulp_riscv_intr_alloc(ULP_RISCV_RTCIO0_INTR_SOURCE + gpio_num, handler, arg); +} + +esp_err_t ulp_riscv_gpio_isr_deregister(gpio_num_t gpio_num) +{ + return ulp_riscv_intr_free(ULP_RISCV_RTCIO0_INTR_SOURCE + gpio_num); +} 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 4f782df63d..e236acd989 100644 --- a/components/ulp/ulp_riscv/ulp_core/ulp_riscv_interrupt.c +++ b/components/ulp/ulp_riscv/ulp_core/ulp_riscv_interrupt.c @@ -4,8 +4,10 @@ * SPDX-License-Identifier: Apache-2.0 */ #include +#include "include/ulp_riscv_interrupt.h" #include "ulp_riscv_register_ops.h" #include "ulp_riscv_interrupt.h" +#include "ulp_riscv_gpio.h" #include "soc/sens_reg.h" #define ULP_RISCV_TIMER_INT (1 << 0U) /* Internal Timer Interrupt */ @@ -77,6 +79,28 @@ static inline void ulp_riscv_handle_rtc_periph_intr(uint32_t status) } } +/* This function - + * - Checks if one or more RTC IO interrupt status bits are set + * - Calls the interrupt handler for the RTC IO if it is registered + * - Clears all interrupt bits + */ +static inline void ulp_riscv_handle_rtc_io_intr(uint32_t status) +{ + uint32_t handler_idx = 0; + for (int i = 0; i < GPIO_NUM_MAX; i++) { + if (status & (1U << i)) { + handler_idx = ULP_RISCV_RTCIO0_INTR_SOURCE + i; + ulp_riscv_intr_handler_t* entry = &s_intr_handlers[handler_idx]; + + if (entry->handler) { + entry->handler(entry->arg); + } + } + } + + REG_SET_FIELD(RTC_GPIO_STATUS_W1TC_REG, RTC_GPIO_STATUS_INT_W1TC, status); +} + /* This is the global interrupt handler for ULP RISC-V. * It is called from ulp_riscv_vectors.S */ @@ -97,7 +121,11 @@ void __attribute__((weak)) _ulp_riscv_interrupt_handler(uint32_t q1) ulp_riscv_handle_rtc_periph_intr(cocpu_int_st); } - /* TODO: RTC IO interrupts */ + /* RTC IO interrupts */ + uint32_t rtcio_int_st = REG_GET_FIELD(RTC_GPIO_STATUS_REG, RTC_GPIO_STATUS_INT); + if (rtcio_int_st) { + ulp_riscv_handle_rtc_io_intr(rtcio_int_st); + } /* TODO: RTC I2C interrupt */ }