From e3282a0cac0e0e7b68c896c75d573603e0fc37f3 Mon Sep 17 00:00:00 2001 From: Deomid Ryabkov Date: Thu, 9 Nov 2017 14:21:39 +0300 Subject: [PATCH] Add esp_intr_set_in_iram A function to change "in IRAM" status for an existing interrupt handle, without going through free/allocate of the interrupt. mOS HW timer implementation requires this to make HW timers safe to re-set from an IRAM ISR. --- components/esp32/include/esp_intr_alloc.h | 17 +++++++++++++++-- components/esp32/intr_alloc.c | 19 +++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/components/esp32/include/esp_intr_alloc.h b/components/esp32/include/esp_intr_alloc.h index ad121abb3..57e72e4de 100644 --- a/components/esp32/include/esp_intr_alloc.h +++ b/components/esp32/include/esp_intr_alloc.h @@ -248,8 +248,8 @@ int esp_intr_get_intno(intr_handle_t handle); esp_err_t esp_intr_disable(intr_handle_t handle); /** - * @brief Ensable the interrupt associated with the handle - * + * @brief Enable the interrupt associated with the handle + * * @note For local interrupts (ESP_INTERNAL_* sources), this function has to be called on the * CPU the interrupt is allocated on. Other interrupts have no such restriction. * @@ -260,6 +260,19 @@ esp_err_t esp_intr_disable(intr_handle_t handle); */ esp_err_t esp_intr_enable(intr_handle_t handle); +/** + * @brief Set the "in IRAM" status of the handler. + * + * @note Does not work on shared interrupts. + * + * @param handle The handle, as obtained by esp_intr_alloc or esp_intr_alloc_intrstatus + * @param is_in_iram Whether the handler associated with this handle resides in IRAM. + * Handlers residing in IRAM can be called when cache is disabled. + * + * @return ESP_ERR_INVALID_ARG if the combination of arguments is invalid. + * ESP_OK otherwise + */ +esp_err_t esp_intr_set_in_iram(intr_handle_t handle, bool is_in_iram); /** * @brief Disable interrupts that aren't specifically marked as running from IRAM diff --git a/components/esp32/intr_alloc.c b/components/esp32/intr_alloc.c index c01ecf33c..ab0c3126f 100644 --- a/components/esp32/intr_alloc.c +++ b/components/esp32/intr_alloc.c @@ -685,6 +685,25 @@ esp_err_t esp_intr_alloc(int source, int flags, intr_handler_t handler, void *ar return esp_intr_alloc_intrstatus(source, flags, 0, 0, handler, arg, ret_handle); } +esp_err_t IRAM_ATTR esp_intr_set_in_iram(intr_handle_t handle, bool is_in_iram) +{ + if (!handle) return ESP_ERR_INVALID_ARG; + vector_desc_t *vd = handle->vector_desc; + if (vd->flags & VECDESC_FL_SHARED) { + return ESP_ERR_INVALID_ARG; + } + portENTER_CRITICAL(&spinlock); + uint32_t mask = (1 << vd->intno); + if (is_in_iram) { + vd->flags |= VECDESC_FL_INIRAM; + non_iram_int_mask[vd->cpu] &= ~mask; + } else { + vd->flags &= ~VECDESC_FL_INIRAM; + non_iram_int_mask[vd->cpu] |= mask; + } + portEXIT_CRITICAL(&spinlock); + return ESP_OK; +} esp_err_t esp_intr_free(intr_handle_t handle) {