mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
driver(interrupt): fix the issue that interrupt might be allocated and freed on different cores for release/v3.1
This commit is contained in:
parent
027e081622
commit
fb30315d01
@ -194,18 +194,19 @@ esp_err_t esp_intr_alloc_intrstatus(int source, int flags, uint32_t intrstatusre
|
|||||||
/**
|
/**
|
||||||
* @brief Disable and free an interrupt.
|
* @brief Disable and free an interrupt.
|
||||||
*
|
*
|
||||||
* Use an interrupt handle to disable the interrupt and release the resources
|
* Use an interrupt handle to disable the interrupt and release the resources associated with it.
|
||||||
* 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
|
* @note
|
||||||
* When the handler shares its source with other handlers, the interrupt status
|
* 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
|
* 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
|
* @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
|
* @return ESP_ERR_INVALID_ARG the handle is NULL
|
||||||
* where the interrupt is allocated on.
|
* ESP_FAIL failed to release this handle
|
||||||
* ESP_OK otherwise
|
* ESP_OK otherwise
|
||||||
*/
|
*/
|
||||||
esp_err_t esp_intr_free(intr_handle_t handle);
|
esp_err_t esp_intr_free(intr_handle_t handle);
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#include "esp_intr.h"
|
#include "esp_intr.h"
|
||||||
#include "esp_attr.h"
|
#include "esp_attr.h"
|
||||||
#include "esp_intr_alloc.h"
|
#include "esp_intr_alloc.h"
|
||||||
|
#include "esp_ipc.h"
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
@ -709,9 +710,11 @@ esp_err_t esp_intr_free(intr_handle_t handle)
|
|||||||
{
|
{
|
||||||
bool free_shared_vector=false;
|
bool free_shared_vector=false;
|
||||||
if (!handle) return ESP_ERR_INVALID_ARG;
|
if (!handle) return ESP_ERR_INVALID_ARG;
|
||||||
//This routine should be called from the interrupt the task is scheduled on.
|
//Assign this routine to the core where this interrupt is allocated on.
|
||||||
if (handle->vector_desc->cpu!=xPortGetCoreID()) return ESP_ERR_INVALID_ARG;
|
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);
|
portENTER_CRITICAL(&spinlock);
|
||||||
esp_intr_disable(handle);
|
esp_intr_disable(handle);
|
||||||
if (handle->vector_desc->flags&VECDESC_FL_SHARED) {
|
if (handle->vector_desc->flags&VECDESC_FL_SHARED) {
|
||||||
|
@ -297,3 +297,41 @@ TEST_CASE("allocate 2 handlers for a same source and remove the later one","[esp
|
|||||||
TEST_ASSERT( ctx.flag3 && !ctx.flag4 );
|
TEST_ASSERT( ctx.flag3 && !ctx.flag4 );
|
||||||
printf("test passed.\n");
|
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
|
Loading…
Reference in New Issue
Block a user