/**
* @brief Disable and free an interrupt.
*
- * Use an interrupt handle to disable the interrupt and release the resources
- * associated with it.
+ * Use an interrupt handle to disable the interrupt and release the resources associated with it.
+ * If the current core is not the core that registered this interrupt, this routine will be assigned to
+ * the core that allocated this interrupt, blocking and waiting until the resource is successfully released.
*
* @note
* When the handler shares its source with other handlers, the interrupt status
* bits it's responsible for should be managed properly before freeing it. see
- * ``esp_intr_disable`` for more details.
+ * ``esp_intr_disable`` for more details. Please do not call this function in ``esp_ipc_call_blocking``.
*
* @param handle The handle, as obtained by esp_intr_alloc or esp_intr_alloc_intrstatus
*
- * @return ESP_ERR_INVALID_ARG if handle is invalid, or esp_intr_free runs on another core than
- * where the interrupt is allocated on.
+ * @return ESP_ERR_INVALID_ARG the handle is NULL
+ * ESP_FAIL failed to release this handle
* ESP_OK otherwise
*/
esp_err_t esp_intr_free(intr_handle_t handle);
#include "esp_intr.h"
#include "esp_attr.h"
#include "esp_intr_alloc.h"
+#include "esp_ipc.h"
#include <limits.h>
#include <assert.h>
{
bool free_shared_vector=false;
if (!handle) return ESP_ERR_INVALID_ARG;
- //This routine should be called from the interrupt the task is scheduled on.
- if (handle->vector_desc->cpu!=xPortGetCoreID()) return ESP_ERR_INVALID_ARG;
-
+ //Assign this routine to the core where this interrupt is allocated on.
+ if (handle->vector_desc->cpu!=xPortGetCoreID()) {
+ esp_err_t ret = esp_ipc_call_blocking(handle->vector_desc->cpu, (esp_ipc_func_t)&esp_intr_free, (void *)handle);
+ return ret == ESP_OK ? ESP_OK : ESP_FAIL;
+ }
portENTER_CRITICAL(&spinlock);
esp_intr_disable(handle);
if (handle->vector_desc->flags&VECDESC_FL_SHARED) {
TEST_ASSERT( ctx.flag3 && !ctx.flag4 );
printf("test passed.\n");
}
+
+#ifndef CONFIG_FREERTOS_UNICORE
+
+void isr_free_task(void *param)
+{
+ esp_err_t ret = ESP_FAIL;
+ intr_handle_t *test_handle = (intr_handle_t *)param;
+ if(*test_handle != NULL) {
+ ret = esp_intr_free(*test_handle);
+ if(ret == ESP_OK) {
+ *test_handle = NULL;
+ }
+ }
+ vTaskDelete(NULL);
+}
+
+void isr_alloc_free_test(void)
+{
+ intr_handle_t test_handle = NULL;
+ esp_err_t ret = esp_intr_alloc(ETS_SPI2_INTR_SOURCE, 0, int_handler1, NULL, &test_handle);
+ if(ret != ESP_OK) {
+ printf("alloc isr handle fail\n");
+ } else {
+ printf("alloc isr handle on core %d\n",esp_intr_get_cpu(test_handle));
+ }
+ TEST_ASSERT(ret == ESP_OK);
+ xTaskCreatePinnedToCore(isr_free_task, "isr_free_task", 1024*2, (void *)&test_handle, 10, NULL, !xPortGetCoreID());
+ vTaskDelay(1000/portTICK_RATE_MS);
+ TEST_ASSERT(test_handle == NULL);
+ printf("test passed\n");
+}
+
+TEST_CASE("alloc and free isr handle on different core", "[esp32]")
+{
+ isr_alloc_free_test();
+}
+
+#endif
\ No newline at end of file