]> granicus.if.org Git - esp-idf/commitdiff
Add esp_intr_set_in_iram
authorDeomid Ryabkov <rojer@cesanta.com>
Thu, 9 Nov 2017 11:21:39 +0000 (14:21 +0300)
committerDeomid Ryabkov <rojer@cesanta.com>
Fri, 8 Dec 2017 02:46:34 +0000 (05:46 +0300)
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
components/esp32/intr_alloc.c

index ad121abb39255745e42dcb165d851f14a89ca242..57e72e4de866f9d3db5e8c91db4820b6d86119dc 100644 (file)
@@ -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
index c01ecf33c811d20e4e1ea6ac35ccd2354a71399c..ab0c3126fae65b1450cb3b1e5921fc49cae5a3c8 100644 (file)
@@ -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)
 {