Merge branch 'feature/ipc_allows_recursion_calls_v5.4' into 'release/v5.4'

feat(ipc): Allow IPC recursion calls in esp_ipc_call (v5.4)

See merge request espressif/esp-idf!41939
This commit is contained in:
Jiang Jiang Jian
2025-09-19 02:19:56 +08:00
2 changed files with 87 additions and 2 deletions

View File

@@ -136,8 +136,14 @@ static esp_err_t esp_ipc_call_and_wait(uint32_t cpu_id, esp_ipc_func_t func, voi
return ESP_ERR_INVALID_STATE; return ESP_ERR_INVALID_STATE;
} }
#ifdef CONFIG_ESP_IPC_USES_CALLERS_PRIORITY
TaskHandle_t task_handler = xTaskGetCurrentTaskHandle(); TaskHandle_t task_handler = xTaskGetCurrentTaskHandle();
// It checks the recursion call: esp_ipc_call_... -> ipc_task -> esp_ipc_call_...
if (task_handler == s_ipc_task_handle[cpu_id]) {
// If the caller task is already the ipc_task, we can run the callback function immediately
func(arg);
return ESP_OK;
}
#ifdef CONFIG_ESP_IPC_USES_CALLERS_PRIORITY
UBaseType_t priority_of_current_task = uxTaskPriorityGet(task_handler); UBaseType_t priority_of_current_task = uxTaskPriorityGet(task_handler);
UBaseType_t priority_of_running_ipc_task = uxTaskPriorityGet(s_ipc_task_handle[cpu_id]); UBaseType_t priority_of_running_ipc_task = uxTaskPriorityGet(s_ipc_task_handle[cpu_id]);
if (priority_of_running_ipc_task < priority_of_current_task) { if (priority_of_running_ipc_task < priority_of_current_task) {

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -209,4 +209,83 @@ TEST_CASE("Test ipc call nonblocking when FreeRTOS Scheduler is suspended", "[ip
xTaskResumeAll(); xTaskResumeAll();
#endif #endif
} }
static void test_func_ipc_cb5(void *arg)
{
static int recursion_count = 0;
int cpu = ((recursion_count++) >> 1) & 1;
esp_rom_printf("ipc_task(%d) -> esp_ipc_call(%d) -> test_func_ipc_cb4\n", cpu, cpu);
esp_ipc_call(cpu, test_func_ipc_cb4, arg);
}
static void test_func_ipc_cb6(void *arg)
{
static int recursion_count = 0;
int cpu = ((recursion_count++) >> 1) & 1;
esp_rom_printf("ipc_task(%d) -> esp_ipc_call_blocking(%d) -> test_func_ipc_cb4\n", cpu, cpu);
esp_ipc_call_blocking(cpu, test_func_ipc_cb4, arg);
}
TEST_CASE("Test recursion IPC call", "[ipc]")
{
int val;
esp_rom_printf("esp_ipc_call -> esp_ipc_call:\n");
/*
esp_ipc_call(0) -> test_func_ipc_cb5 -> ipc_task(0) -> esp_ipc_call(0) -> test_func_ipc_cb4
esp_ipc_call(1) -> test_func_ipc_cb5 -> ipc_task(0) -> esp_ipc_call(0) -> test_func_ipc_cb4
esp_ipc_call(0) -> test_func_ipc_cb5 -> ipc_task(1) -> esp_ipc_call(1) -> test_func_ipc_cb4
esp_ipc_call(1) -> test_func_ipc_cb5 -> ipc_task(1) -> esp_ipc_call(1) -> test_func_ipc_cb4
*/
for (int cpu = 0; cpu < CONFIG_FREERTOS_NUMBER_OF_CORES * 2; ++cpu) {
val = 0x5a5a;
esp_rom_printf("esp_ipc_call(%d) -> test_func_ipc_cb5 -> ", cpu % CONFIG_FREERTOS_NUMBER_OF_CORES);
esp_ipc_call(cpu % CONFIG_FREERTOS_NUMBER_OF_CORES, test_func_ipc_cb5, &val);
vTaskDelay(10 / portTICK_PERIOD_MS);
TEST_ASSERT_EQUAL_HEX(val, 0x5a5a + 1);
}
esp_rom_printf("esp_ipc_call_blocking -> esp_ipc_call test:\n");
/*
esp_ipc_call_blocking(0) -> test_func_ipc_cb5 -> ipc_task(0) -> esp_ipc_call(0) -> test_func_ipc_cb4
esp_ipc_call_blocking(1) -> test_func_ipc_cb5 -> ipc_task(0) -> esp_ipc_call(0) -> test_func_ipc_cb4
esp_ipc_call_blocking(0) -> test_func_ipc_cb5 -> ipc_task(1) -> esp_ipc_call(1) -> test_func_ipc_cb4
esp_ipc_call_blocking(1) -> test_func_ipc_cb5 -> ipc_task(1) -> esp_ipc_call(1) -> test_func_ipc_cb4
*/
for (int cpu = 0; cpu < CONFIG_FREERTOS_NUMBER_OF_CORES * 2; ++cpu) {
val = 0xa5a5;
esp_rom_printf("esp_ipc_call_blocking(%d) -> test_func_ipc_cb5 -> ", cpu % CONFIG_FREERTOS_NUMBER_OF_CORES);
esp_ipc_call_blocking(cpu % CONFIG_FREERTOS_NUMBER_OF_CORES, test_func_ipc_cb5, &val);
TEST_ASSERT_EQUAL_HEX(val, 0xa5a5 + 1);
}
esp_rom_printf("esp_ipc_call -> esp_ipc_call_blocking:\n");
/*
esp_ipc_call(0) -> test_func_ipc_cb6 -> ipc_task(0) -> esp_ipc_call_blocking(0) -> test_func_ipc_cb4
esp_ipc_call(1) -> test_func_ipc_cb6 -> ipc_task(0) -> esp_ipc_call_blocking(0) -> test_func_ipc_cb4
esp_ipc_call(0) -> test_func_ipc_cb6 -> ipc_task(1) -> esp_ipc_call_blocking(1) -> test_func_ipc_cb4
esp_ipc_call(1) -> test_func_ipc_cb6 -> ipc_task(1) -> esp_ipc_call_blocking(1) -> test_func_ipc_cb4
*/
for (int cpu = 0; cpu < CONFIG_FREERTOS_NUMBER_OF_CORES * 2; ++cpu) {
val = 0x5a5a;
esp_rom_printf("esp_ipc_call(%d) -> test_func_ipc_cb6 -> ", cpu % CONFIG_FREERTOS_NUMBER_OF_CORES);
esp_ipc_call(cpu % CONFIG_FREERTOS_NUMBER_OF_CORES, test_func_ipc_cb6, &val);
vTaskDelay(10 / portTICK_PERIOD_MS);
TEST_ASSERT_EQUAL_HEX(val, 0x5a5a + 1);
}
esp_rom_printf("esp_ipc_call_blocking -> esp_ipc_call_blocking test:\n");
/*
esp_ipc_call_blocking(0) -> test_func_ipc_cb6 -> ipc_task(0) -> esp_ipc_call_blocking(0) -> test_func_ipc_cb4
esp_ipc_call_blocking(1) -> test_func_ipc_cb6 -> ipc_task(0) -> esp_ipc_call_blocking(0) -> test_func_ipc_cb4
esp_ipc_call_blocking(0) -> test_func_ipc_cb6 -> ipc_task(1) -> esp_ipc_call_blocking(1) -> test_func_ipc_cb4
esp_ipc_call_blocking(1) -> test_func_ipc_cb6 -> ipc_task(1) -> esp_ipc_call_blocking(1) -> test_func_ipc_cb4
*/
for (int cpu = 0; cpu < CONFIG_FREERTOS_NUMBER_OF_CORES * 2; ++cpu) {
val = 0xa5a5;
esp_rom_printf("esp_ipc_call_blocking(%d) -> test_func_ipc_cb6 -> ", cpu % CONFIG_FREERTOS_NUMBER_OF_CORES);
esp_ipc_call_blocking(cpu % CONFIG_FREERTOS_NUMBER_OF_CORES, test_func_ipc_cb6, &val);
TEST_ASSERT_EQUAL_HEX(val, 0xa5a5 + 1);
}
}
#endif /* !CONFIG_FREERTOS_UNICORE */ #endif /* !CONFIG_FREERTOS_UNICORE */