fix(esp_hw_support): allow allocating interrupts with handlers in ROM with IRAM attribute

The interrupt allocator now allows allocating an interrupt with a handler in ROM
and flags set to ESP_INTR_FLAG_IRAM
This commit is contained in:
Omar Chebib 2024-08-02 17:51:15 +08:00
parent 7a5c05e7c0
commit 18d545708a
3 changed files with 46 additions and 4 deletions

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -317,6 +317,18 @@ static inline int esp_intr_level_to_flags(int level)
*/
esp_err_t esp_intr_dump(FILE *stream);
/**
* @brief Check if the given pointer is in the safe ISR area.
* In other words, make sure that the pointer's content is accessible at
* any time, regardless of the cache status
*
* @param ptr Pointer to check
*
* @return true if `ptr` points to ISR area, false else
*/
bool esp_intr_ptr_in_isr_region(void* ptr);
/**@}*/

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2010-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2010-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -307,7 +307,7 @@ inline static bool esp_ptr_in_drom(const void *p) {
/* For ESP32-S3, when the DCACHE size is set to 16 kB, the unused 48 kB is
* added to the heap in 2 blocks of 32 kB (from 0x3FCF0000) and 16 kB
* (from 0x3C000000 (SOC_DROM_LOW) - 0x3C004000).
* The drom_start_addr has to be moved by 0x4000 (16kB) to accomodate
* The drom_start_addr has to be moved by 0x4000 (16kB) to accommodate
* this addition. */
drom_start_addr += 0x4000;
#endif
@ -315,6 +315,29 @@ inline static bool esp_ptr_in_drom(const void *p) {
return ((intptr_t)p >= drom_start_addr && (intptr_t)p < SOC_DROM_HIGH);
}
/**
* @brief Check if the given pointer is in ROM
*
* @param ptr Pointer to check
*
* @return true if `ptr` points to ROM, false else
*/
__attribute__((always_inline))
inline static bool esp_ptr_in_rom(const void *p)
{
intptr_t ip = (intptr_t) p;
return
/**
* The following DROM macros are only defined on RISC-V targets, moreover, to prevent
* the compiler from generating a `logical-op` warning, make sure the macros are
* distinct. */
#if CONFIG_IDF_TARGET_ARCH_RISCV && SOC_DROM_MASK_LOW != SOC_IROM_MASK_LOW
(ip >= SOC_DROM_MASK_LOW && ip < SOC_DROM_MASK_HIGH) ||
#endif
(ip >= SOC_IROM_MASK_LOW && ip < SOC_IROM_MASK_HIGH);
}
/**
* @brief Check if the stack pointer is in dram
*

View File

@ -472,6 +472,13 @@ static void IRAM_ATTR non_shared_intr_isr(void *arg)
}
#endif
bool esp_intr_ptr_in_isr_region(void* ptr)
{
return esp_ptr_in_iram(ptr) || esp_ptr_in_rtc_iram_fast(ptr) || esp_ptr_in_rom(ptr);
}
//We use ESP_EARLY_LOG* here because this can be called before the scheduler is running.
esp_err_t esp_intr_alloc_intrstatus(int source, int flags, uint32_t intrstatusreg, uint32_t intrstatusmask, intr_handler_t handler,
void *arg, intr_handle_t *ret_handle)
@ -499,7 +506,7 @@ esp_err_t esp_intr_alloc_intrstatus(int source, int flags, uint32_t intrstatusre
//ToDo: if we are to allow placing interrupt handlers into the 0x400c0000—0x400c2000 region,
//we need to make sure the interrupt is connected to the CPU0.
//CPU1 does not have access to the RTC fast memory through this region.
if ((flags & ESP_INTR_FLAG_IRAM) && handler && !esp_ptr_in_iram(handler) && !esp_ptr_in_rtc_iram_fast(handler)) {
if ((flags & ESP_INTR_FLAG_IRAM) && handler && !esp_intr_ptr_in_isr_region(handler)) {
return ESP_ERR_INVALID_ARG;
}