Merge branch 'feature/ulp_riscv_interrupt_handling' into 'master'
feat(ulp-riscv): Added interrupt handling for ULP RISC-V Closes IDFGH-9866 and IDF-1713 See merge request espressif/esp-idf!27802
This commit is contained in:
@@ -57,6 +57,7 @@ set(bypassWarning "${IDF_TARGET}")
|
||||
if(ULP_COCPU_IS_RISCV)
|
||||
#risc-v ulp uses extra files for building:
|
||||
list(APPEND ULP_S_SOURCES
|
||||
"${IDF_PATH}/components/ulp/ulp_riscv/ulp_core/ulp_riscv_vectors.S"
|
||||
"${IDF_PATH}/components/ulp/ulp_riscv/ulp_core/start.S"
|
||||
"${IDF_PATH}/components/ulp/ulp_riscv/ulp_core/ulp_riscv_adc.c"
|
||||
"${IDF_PATH}/components/ulp/ulp_riscv/ulp_core/ulp_riscv_lock.c"
|
||||
@@ -64,7 +65,9 @@ if(ULP_COCPU_IS_RISCV)
|
||||
"${IDF_PATH}/components/ulp/ulp_riscv/ulp_core/ulp_riscv_print.c"
|
||||
"${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_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")
|
||||
target_link_options(${ULP_APP_NAME} PRIVATE -Wl,--gc-sections)
|
||||
@@ -72,7 +75,8 @@ if(ULP_COCPU_IS_RISCV)
|
||||
target_sources(${ULP_APP_NAME} PRIVATE ${ULP_S_SOURCES})
|
||||
#Makes the csr utillies for riscv visible:
|
||||
target_include_directories(${ULP_APP_NAME} PRIVATE "${IDF_PATH}/components/ulp/ulp_riscv/ulp_core/include"
|
||||
"${IDF_PATH}/components/ulp/ulp_riscv/shared/include")
|
||||
"${IDF_PATH}/components/ulp/ulp_riscv/shared/include"
|
||||
"${IDF_PATH}/components/riscv/include")
|
||||
target_link_options(${ULP_APP_NAME} PRIVATE SHELL:-T ${IDF_PATH}/components/ulp/ld/${IDF_TARGET}.peripherals.ld)
|
||||
target_link_options(${ULP_APP_NAME} PRIVATE "-Wl,--no-warn-rwx-segments")
|
||||
target_compile_definitions(${ULP_APP_NAME} PRIVATE IS_ULP_COCPU)
|
||||
|
||||
@@ -17,7 +17,7 @@ SECTIONS
|
||||
. = ORIGIN(ram);
|
||||
.text :
|
||||
{
|
||||
*start.S.obj(.text.vectors) /* Default reset vector must link to offset 0x0 */
|
||||
*ulp_riscv_vectors.S.obj(.text.vectors) /* Default reset vector must link to offset 0x0 */
|
||||
*(.text)
|
||||
*(.text*)
|
||||
} >ram
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include "esp_err.h"
|
||||
#include "riscv/interrupt.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/* 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;
|
||||
|
||||
/**
|
||||
* @brief Allocate interrupt handler for a ULP RISC-V interrupt source
|
||||
*
|
||||
* @param source ULP RISC-V interrupt source
|
||||
* @param handler Interrupt handler
|
||||
* @param arg Interrupt handler argument
|
||||
*
|
||||
* @return esp_err_t ESP_OK when successful
|
||||
*/
|
||||
esp_err_t ulp_riscv_intr_alloc(ulp_riscv_interrupt_source_t source, intr_handler_t handler, void *arg);
|
||||
|
||||
/**
|
||||
* @brief Free ULP RISC-V interrupt handler
|
||||
*
|
||||
* @param source ULP RISC-V interrupt source
|
||||
*
|
||||
* @return esp_err_t ESP_OK when successful
|
||||
*/
|
||||
esp_err_t ulp_riscv_intr_free(ulp_riscv_interrupt_source_t source);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2021 Claire Xenia Wolf <claire@yosyshq.com>
|
||||
* SPDX-FileContributor: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This header file defines custom instructions for interrupt handling on the
|
||||
* ULP RISC-V. The architecture of the processor and therefore, the interrupt
|
||||
* handling is based on the PicoRV32 CPU. Details about the operations are
|
||||
* available at https://github.com/YosysHQ/picorv32#custom-instructions-for-irq-handling
|
||||
*/
|
||||
|
||||
/* Define encoding for all general purpose RISC-V registers */
|
||||
#define regnum_zero 0
|
||||
#define regnum_ra 1
|
||||
#define regnum_sp 2
|
||||
#define regnum_gp 3
|
||||
#define regnum_tp 4
|
||||
#define regnum_t0 5
|
||||
#define regnum_t1 6
|
||||
#define regnum_t2 7
|
||||
#define regnum_s0 8
|
||||
#define regnum_s1 9
|
||||
#define regnum_a0 10
|
||||
#define regnum_a1 11
|
||||
#define regnum_a2 12
|
||||
#define regnum_a3 13
|
||||
#define regnum_a4 14
|
||||
#define regnum_a5 15
|
||||
#define regnum_a6 16
|
||||
#define regnum_a7 17
|
||||
#define regnum_s2 18
|
||||
#define regnum_s3 19
|
||||
#define regnum_s4 20
|
||||
#define regnum_s5 21
|
||||
#define regnum_s6 22
|
||||
#define regnum_s7 23
|
||||
#define regnum_s8 24
|
||||
#define regnum_s9 25
|
||||
#define regnum_s10 26
|
||||
#define regnum_s11 27
|
||||
#define regnum_t3 28
|
||||
#define regnum_t4 29
|
||||
#define regnum_t5 30
|
||||
#define regnum_t6 31
|
||||
|
||||
/* Define encoding for special interrupt handling registers, viz., q0, q1, q2 and q3 */
|
||||
#define regnum_q0 0
|
||||
#define regnum_q1 1
|
||||
#define regnum_q2 2
|
||||
#define regnum_q3 3
|
||||
|
||||
/* All custom interrupt handling instructions follow the standard R-type instruction format from RISC-V ISA
|
||||
* with the same opcode of custom0 (0001011).
|
||||
*/
|
||||
#define r_type_insn(_f7, _rs2, _rs1, _f3, _rd, _opc) \
|
||||
.word (((_f7) << 25) | ((_rs2) << 20) | ((_rs1) << 15) | ((_f3) << 12) | ((_rd) << 7) | ((_opc) << 0))
|
||||
|
||||
/**
|
||||
* Instruction: getq rd, qs
|
||||
* Description: This instruction copies the value of Qx into a general purpose register rd
|
||||
*/
|
||||
#define getq_insn(_rd, _qs) \
|
||||
r_type_insn(0b0000000, 0, regnum_ ## _qs, 0b100, regnum_ ## _rd, 0b0001011)
|
||||
|
||||
/**
|
||||
* Instruction: setq qd, rs
|
||||
* Description: This instruction copies the value of general purpose register rs to Qx
|
||||
*/
|
||||
#define setq_insn(_qd, _rs) \
|
||||
r_type_insn(0b0000001, 0, regnum_ ## _rs, 0b010, regnum_ ## _qd, 0b0001011)
|
||||
|
||||
/**
|
||||
* Instruction: retirq
|
||||
* Description: This instruction copies the value of Q0 to CPU PC, and renables interrupts
|
||||
*/
|
||||
#define retirq_insn() \
|
||||
r_type_insn(0b0000010, 0, 0, 0b000, 0, 0b0001011)
|
||||
|
||||
/**
|
||||
* Instruction: maskirq rd, rs
|
||||
* Description: This instruction copies the value of the register IRQ Mask to the register rd, and copies the value
|
||||
* of register rs to to IRQ mask.
|
||||
*/
|
||||
#define maskirq_insn(_rd, _rs) \
|
||||
r_type_insn(0b0000011, 0, regnum_ ## _rs, 0b110, regnum_ ## _rd, 0b0001011)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -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
|
||||
|
||||
@@ -1,28 +1,26 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
.section .text.vectors
|
||||
.global irq_vector
|
||||
.global reset_vector
|
||||
|
||||
/* The reset vector, jumps to startup code */
|
||||
reset_vector:
|
||||
j __start
|
||||
#include "ulp_riscv_interrupt_ops.h"
|
||||
|
||||
/* Interrupt handler */
|
||||
.balign 16
|
||||
irq_vector:
|
||||
ret
|
||||
|
||||
.section .text
|
||||
.section .text
|
||||
.global __start
|
||||
|
||||
.type __start, %function
|
||||
__start:
|
||||
/* setup the stack pointer */
|
||||
la sp, __stack_top
|
||||
call ulp_riscv_rescue_from_monitor
|
||||
call main
|
||||
call ulp_riscv_halt
|
||||
/* setup the stack pointer */
|
||||
la sp, __stack_top
|
||||
|
||||
/* Enable interrupts globally */
|
||||
maskirq_insn(zero, zero)
|
||||
|
||||
/* Start ULP user code */
|
||||
call ulp_riscv_rescue_from_monitor
|
||||
call main
|
||||
call ulp_riscv_halt
|
||||
loop:
|
||||
j loop
|
||||
j loop
|
||||
.size __start, .-__start
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#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 */
|
||||
#define ULP_RISCV_EBREAK_ECALL_ILLEGAL_INSN_INT (1 << 1U) /* EBREAK, ECALL or Illegal instruction */
|
||||
#define ULP_RISCV_BUS_ERROR_INT (1 << 2U) /* Bus Error (Unaligned Memory Access) */
|
||||
#define ULP_RISCV_PERIPHERAL_INTERRUPT (1 << 31U) /* RTC Peripheral Interrupt */
|
||||
#define ULP_RISCV_INTERNAL_INTERRUPT (ULP_RISCV_TIMER_INT | ULP_RISCV_EBREAK_ECALL_ILLEGAL_INSN_INT | ULP_RISCV_BUS_ERROR_INT)
|
||||
|
||||
/* Interrupt handler structure */
|
||||
typedef struct {
|
||||
intr_handler_t handler;
|
||||
void *arg;
|
||||
} ulp_riscv_intr_handler_t;
|
||||
|
||||
/* Statically store all interrupt handlers */
|
||||
static ulp_riscv_intr_handler_t s_intr_handlers[ULP_RISCV_MAX_INTR_SOURCE];
|
||||
|
||||
esp_err_t ulp_riscv_intr_alloc(ulp_riscv_interrupt_source_t source, intr_handler_t handler, void *arg)
|
||||
{
|
||||
/* Check the validity of the interrupt source */
|
||||
if (source < 0 || source >= ULP_RISCV_MAX_INTR_SOURCE || handler == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
/* Register interrupt handler */
|
||||
if (s_intr_handlers[source].handler == NULL) {
|
||||
s_intr_handlers[source].handler = handler;
|
||||
s_intr_handlers[source].arg = arg;
|
||||
} else {
|
||||
/* Error: The interrupt handler for this interrupt source has already been allocated */
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t ulp_riscv_intr_free(ulp_riscv_interrupt_source_t source)
|
||||
{
|
||||
/* Check the validity of the interrupt source */
|
||||
if (source < 0 || source >= ULP_RISCV_MAX_INTR_SOURCE) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
/* De-register interrupt handler */
|
||||
if (s_intr_handlers[source].handler != NULL) {
|
||||
s_intr_handlers[source].handler = NULL;
|
||||
s_intr_handlers[source].arg = NULL;
|
||||
}
|
||||
|
||||
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 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
|
||||
*/
|
||||
void __attribute__((weak)) _ulp_riscv_interrupt_handler(uint32_t q1)
|
||||
{
|
||||
/* Call respective interrupt handlers based on the interrupt status in q1 */
|
||||
|
||||
/* Internal Interrupts */
|
||||
if (q1 & ULP_RISCV_INTERNAL_INTERRUPT) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
/* External/Peripheral interrupts */
|
||||
if (q1 & ULP_RISCV_PERIPHERAL_INTERRUPT) {
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "ulp_riscv_interrupt_ops.h"
|
||||
#include "riscv/rvruntime-frames.h"
|
||||
.equ SAVE_REGS, 17
|
||||
.equ CONTEXT_SIZE, (SAVE_REGS * 4)
|
||||
|
||||
/* Macro which first allocates space on the stack to save general
|
||||
* purpose registers, and then save them. GP register is excluded.
|
||||
* The default size allocated on the stack is CONTEXT_SIZE, but it
|
||||
* can be overridden.
|
||||
*
|
||||
* Note: We don't save the callee-saved s0-s11 registers to save space
|
||||
*/
|
||||
.macro save_general_regs cxt_size=CONTEXT_SIZE
|
||||
addi sp, sp, -\cxt_size
|
||||
sw ra, RV_STK_RA(sp)
|
||||
sw tp, RV_STK_TP(sp)
|
||||
sw t0, RV_STK_T0(sp)
|
||||
sw t1, RV_STK_T1(sp)
|
||||
sw t2, RV_STK_T2(sp)
|
||||
sw a0, RV_STK_A0(sp)
|
||||
sw a1, RV_STK_A1(sp)
|
||||
sw a2, RV_STK_A2(sp)
|
||||
sw a3, RV_STK_A3(sp)
|
||||
sw a4, RV_STK_A4(sp)
|
||||
sw a5, RV_STK_A5(sp)
|
||||
sw a6, RV_STK_A6(sp)
|
||||
sw a7, RV_STK_A7(sp)
|
||||
sw t3, RV_STK_T3(sp)
|
||||
sw t4, RV_STK_T4(sp)
|
||||
sw t5, RV_STK_T5(sp)
|
||||
sw t6, RV_STK_T6(sp)
|
||||
.endm
|
||||
|
||||
/* 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 overridden. */
|
||||
.macro restore_general_regs cxt_size=CONTEXT_SIZE
|
||||
lw ra, RV_STK_RA(sp)
|
||||
lw tp, RV_STK_TP(sp)
|
||||
lw t0, RV_STK_T0(sp)
|
||||
lw t1, RV_STK_T1(sp)
|
||||
lw t2, RV_STK_T2(sp)
|
||||
lw a0, RV_STK_A0(sp)
|
||||
lw a1, RV_STK_A1(sp)
|
||||
lw a2, RV_STK_A2(sp)
|
||||
lw a3, RV_STK_A3(sp)
|
||||
lw a4, RV_STK_A4(sp)
|
||||
lw a5, RV_STK_A5(sp)
|
||||
lw a6, RV_STK_A6(sp)
|
||||
lw a7, RV_STK_A7(sp)
|
||||
lw t3, RV_STK_T3(sp)
|
||||
lw t4, RV_STK_T4(sp)
|
||||
lw t5, RV_STK_T5(sp)
|
||||
lw t6, RV_STK_T6(sp)
|
||||
addi sp,sp, \cxt_size
|
||||
.endm
|
||||
|
||||
.section .text.vectors
|
||||
.global irq_vector
|
||||
.global reset_vector
|
||||
|
||||
/* The reset vector, jumps to startup code */
|
||||
reset_vector:
|
||||
j __start
|
||||
|
||||
/* Interrupt handler */
|
||||
.balign 0x10
|
||||
irq_vector:
|
||||
/* Save the general gurpose register context before handling the interrupt */
|
||||
save_general_regs
|
||||
|
||||
/* Fetch the interrupt status from the custom q1 register into a0 */
|
||||
getq_insn(a0, q1)
|
||||
|
||||
/* Call the global C interrupt handler. The interrupt status is passed as the argument in a0.
|
||||
* We do not re-enable interrupts before calling the C handler as ULP RISC-V does not
|
||||
* support nested interrupts.
|
||||
*/
|
||||
jal _ulp_riscv_interrupt_handler
|
||||
|
||||
/* Restore the register context after returning from the C interrupt handler */
|
||||
restore_general_regs
|
||||
|
||||
/* Exit interrupt handler by executing the custom retirq instruction which will retore pc and re-enable interrupts */
|
||||
retirq_insn()
|
||||
Reference in New Issue
Block a user