forked from espressif/esp-idf
Merge branch 'refactor/supplement_plic_intr_rv_util_apis' into 'master'
refactor(intr): add plic and intc interrupt rv util apis See merge request espressif/esp-idf!33244
This commit is contained in:
@@ -476,38 +476,20 @@ BaseType_t IRAM_ATTR xPortInterruptedFromISRContext(void)
|
|||||||
|
|
||||||
UBaseType_t xPortSetInterruptMaskFromISR(void)
|
UBaseType_t xPortSetInterruptMaskFromISR(void)
|
||||||
{
|
{
|
||||||
UBaseType_t prev_int_level = 0;
|
UBaseType_t prev_int_level = 0, int_level = 0;
|
||||||
|
|
||||||
#if !SOC_INT_CLIC_SUPPORTED
|
#if !SOC_INT_CLIC_SUPPORTED
|
||||||
unsigned old_mstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE);
|
int_level = RVHAL_EXCM_LEVEL;
|
||||||
prev_int_level = REG_READ(INTERRUPT_CURRENT_CORE_INT_THRESH_REG);
|
|
||||||
REG_WRITE(INTERRUPT_CURRENT_CORE_INT_THRESH_REG, RVHAL_EXCM_LEVEL);
|
|
||||||
RV_SET_CSR(mstatus, old_mstatus & MSTATUS_MIE);
|
|
||||||
#else
|
#else
|
||||||
/* When CLIC is supported, all interrupt priority levels less than or equal to the threshold level are masked. */
|
int_level = RVHAL_EXCM_LEVEL_CLIC;
|
||||||
prev_int_level = rv_utils_set_intlevel_regval(RVHAL_EXCM_LEVEL_CLIC);
|
#endif
|
||||||
#endif /* !SOC_INIT_CLIC_SUPPORTED */
|
|
||||||
/**
|
prev_int_level = rv_utils_set_intlevel_regval(int_level);
|
||||||
* In theory, this function should not return immediately as there is a
|
|
||||||
* delay between the moment we mask the interrupt threshold register and
|
|
||||||
* the moment a potential lower-priority interrupt is triggered (as said
|
|
||||||
* above), it should have a delay of 2 machine cycles/instructions.
|
|
||||||
*
|
|
||||||
* However, in practice, this function has an epilogue of one instruction,
|
|
||||||
* thus the instruction masking the interrupt threshold register is
|
|
||||||
* followed by two instructions: `ret` and `csrrs` (RV_SET_CSR).
|
|
||||||
* That's why we don't need any additional nop instructions here.
|
|
||||||
*/
|
|
||||||
return prev_int_level;
|
return prev_int_level;
|
||||||
}
|
}
|
||||||
|
|
||||||
void vPortClearInterruptMaskFromISR(UBaseType_t prev_int_level)
|
void vPortClearInterruptMaskFromISR(UBaseType_t prev_int_level)
|
||||||
{
|
{
|
||||||
#if !SOC_INT_CLIC_SUPPORTED
|
|
||||||
REG_WRITE(INTERRUPT_CURRENT_CORE_INT_THRESH_REG, prev_int_level);
|
|
||||||
#else
|
|
||||||
rv_utils_restore_intlevel_regval(prev_int_level);
|
rv_utils_restore_intlevel_regval(prev_int_level);
|
||||||
#endif /* SOC_INIT_CLIC_SUPPORTED */
|
|
||||||
/**
|
/**
|
||||||
* The delay between the moment we unmask the interrupt threshold register
|
* The delay between the moment we unmask the interrupt threshold register
|
||||||
* and the moment the potential requested interrupt is triggered is not
|
* and the moment the potential requested interrupt is triggered is not
|
||||||
|
@@ -11,6 +11,7 @@
|
|||||||
#include "esp_attr.h"
|
#include "esp_attr.h"
|
||||||
#include "soc/interrupt_reg.h"
|
#include "soc/interrupt_reg.h"
|
||||||
#include "soc/soc_caps.h"
|
#include "soc/soc_caps.h"
|
||||||
|
#include "riscv/csr.h"
|
||||||
|
|
||||||
#if !SOC_INT_CLIC_SUPPORTED && !SOC_INT_PLIC_SUPPORTED
|
#if !SOC_INT_CLIC_SUPPORTED && !SOC_INT_PLIC_SUPPORTED
|
||||||
|
|
||||||
@@ -63,6 +64,33 @@ FORCE_INLINE_ATTR void rv_utils_intr_edge_ack(uint32_t intr_num)
|
|||||||
REG_SET_BIT(INTERRUPT_CORE0_CPU_INT_CLEAR_REG, intr_num);
|
REG_SET_BIT(INTERRUPT_CORE0_CPU_INT_CLEAR_REG, intr_num);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Restore the CPU interrupt level to the value returned by `rv_utils_set_intlevel_regval`.
|
||||||
|
*
|
||||||
|
* @param restoreval Former raw interrupt level, it is NOT necessarily a value between 0 and 7, this is hardware and configuration dependent.
|
||||||
|
*/
|
||||||
|
FORCE_INLINE_ATTR void rv_utils_restore_intlevel_regval(uint32_t restoreval)
|
||||||
|
{
|
||||||
|
REG_WRITE(INTERRUPT_CURRENT_CORE_INT_THRESH_REG, restoreval);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the interrupt threshold to `intlevel` while getting the current level.
|
||||||
|
*
|
||||||
|
* @param intlevel New raw interrupt level, it is NOT necessarily a value between 0 and 7, this is hardware and configuration dependent.
|
||||||
|
*
|
||||||
|
* @return Current raw interrupt level, can be restored by calling `rv_utils_restore_intlevel_regval`.
|
||||||
|
*/
|
||||||
|
FORCE_INLINE_ATTR uint32_t rv_utils_set_intlevel_regval(uint32_t intlevel)
|
||||||
|
{
|
||||||
|
uint32_t old_mstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE);
|
||||||
|
uint32_t old_thresh = REG_READ(INTERRUPT_CURRENT_CORE_INT_THRESH_REG);
|
||||||
|
rv_utils_restore_intlevel_regval(intlevel);
|
||||||
|
RV_SET_CSR(mstatus, old_mstatus & MSTATUS_MIE);
|
||||||
|
|
||||||
|
return old_thresh;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@@ -11,6 +11,7 @@
|
|||||||
#include "esp_attr.h"
|
#include "esp_attr.h"
|
||||||
#include "soc/interrupt_reg.h"
|
#include "soc/interrupt_reg.h"
|
||||||
#include "soc/soc_caps.h"
|
#include "soc/soc_caps.h"
|
||||||
|
#include "riscv/csr.h"
|
||||||
|
|
||||||
#if SOC_INT_PLIC_SUPPORTED
|
#if SOC_INT_PLIC_SUPPORTED
|
||||||
|
|
||||||
@@ -64,6 +65,33 @@ FORCE_INLINE_ATTR void rv_utils_intr_edge_ack(uint32_t intr_num)
|
|||||||
REG_SET_BIT(INTERRUPT_CORE0_CPU_INT_CLEAR_REG, intr_num);
|
REG_SET_BIT(INTERRUPT_CORE0_CPU_INT_CLEAR_REG, intr_num);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Restore the CPU interrupt level to the value returned by `rv_utils_set_intlevel_regval`.
|
||||||
|
*
|
||||||
|
* @param restoreval Former raw interrupt level, it is NOT necessarily a value between 0 and 7, this is hardware and configuration dependent.
|
||||||
|
*/
|
||||||
|
FORCE_INLINE_ATTR void rv_utils_restore_intlevel_regval(uint32_t restoreval)
|
||||||
|
{
|
||||||
|
REG_WRITE(INTERRUPT_CURRENT_CORE_INT_THRESH_REG, restoreval);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the interrupt threshold to `intlevel` while getting the current level.
|
||||||
|
*
|
||||||
|
* @param intlevel New raw interrupt level, it is NOT necessarily a value between 0 and 7, this is hardware and configuration dependent.
|
||||||
|
*
|
||||||
|
* @return Current raw interrupt level, can be restored by calling `rv_utils_restore_intlevel_regval`.
|
||||||
|
*/
|
||||||
|
FORCE_INLINE_ATTR uint32_t rv_utils_set_intlevel_regval(uint32_t intlevel)
|
||||||
|
{
|
||||||
|
uint32_t old_mstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE);
|
||||||
|
uint32_t old_thresh = REG_READ(INTERRUPT_CURRENT_CORE_INT_THRESH_REG);
|
||||||
|
rv_utils_restore_intlevel_regval(intlevel);
|
||||||
|
RV_SET_CSR(mstatus, old_mstatus & MSTATUS_MIE);
|
||||||
|
|
||||||
|
return old_thresh;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user