fix(freertos): Fixed xPortCanYield to correctly determine ISR context on esp32p4

This commit fixes an issue where xPortCanYield() function may not be
able to detect an ISR context when HW interrupt nesting is active on
a CLIC interrupt controller such as on esp32p4.
pull/12486/head
Sudeep Mohanty 2023-09-22 16:25:56 +02:00
rodzic 54f0517724
commit cf55ab899a
2 zmienionych plików z 24 dodań i 5 usunięć

Wyświetl plik

@ -645,13 +645,18 @@ FORCE_INLINE_ATTR bool xPortCanYield(void)
{
uint32_t threshold = REG_READ(INTERRUPT_CURRENT_CORE_INT_THRESH_REG);
#if SOC_INT_CLIC_SUPPORTED
/* When CLIC is supported:
* - The lowest interrupt threshold level is 0. Therefore, an interrupt threshold level above 0 would mean that we
* are in a critical section.
* - Since CLIC enables HW interrupt nesting, we do not have the updated interrupt level in the
* INTERRUPT_CURRENT_CORE_INT_THRESH_REG register when nested interrupts occur. To know the current interrupt
* level, we read the machine-mode interrupt level (mil) field from the mintstatus CSR. A non-zero value indicates
* that we are in an interrupt context.
*/
uint32_t intr_level = rv_utils_get_interrupt_level();
threshold = threshold >> (CLIC_CPU_INT_THRESH_S + (8 - NLBITS));
/* When CLIC is supported, the lowest interrupt threshold level is 0.
* Therefore, an interrupt threshold level above 0 would mean that we
* are either in a critical section or in an ISR.
*/
return (threshold == 0);
return ((intr_level == 0) && (threshold == 0));
#endif /* SOC_INT_CLIC_SUPPORTED */
/* when enter critical code, FreeRTOS will mask threshold to RVHAL_EXCM_LEVEL
* and exit critical code, will recover threshold value (1). so threshold <= 1

Wyświetl plik

@ -113,6 +113,20 @@ FORCE_INLINE_ATTR void rv_utils_set_mtvec(uint32_t mtvec_val)
RV_WRITE_CSR(mtvec, mtvec_val);
}
#if SOC_INT_CLIC_SUPPORTED
FORCE_INLINE_ATTR __attribute__((pure)) uint32_t rv_utils_get_interrupt_level(void)
{
#if CONFIG_IDF_TARGET_ESP32P4
// As per CLIC specs, mintstatus CSR should be at 0xFB1, however esp32p4 implements it at 0x346
#define MINTSTATUS 0x346
#else
#error "rv_utils_get_mintstatus() is not implemented. Check for correct mintstatus register address."
#endif /* CONFIG_IDF_TARGET_ESP32P4 */
uint32_t mintstatus = RV_READ_CSR(MINTSTATUS);
return ((mintstatus >> 24) & 0xFF); // Return the mintstatus[31:24] bits to get the mil field
}
#endif /* SOC_INT_CLIC_SUPPORTED */
// ------------------ Interrupt Control --------------------
FORCE_INLINE_ATTR void rv_utils_intr_enable(uint32_t intr_mask)