forked from espressif/esp-idf
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.
This commit is contained in:
@@ -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;
|
||||
|
||||
|
@@ -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 <stdint.h>
|
||||
#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
|
||||
|
@@ -6,6 +6,7 @@
|
||||
#include <stdint.h>
|
||||
#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 */
|
||||
|
||||
|
@@ -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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user