feat(esp_driver_dma): add blocking async memcpy API

Add a blocking wrapper for async memcpy so simple users can wait for one DMA copy without writing their own ISR callback and semaphore plumbing. Update functional tests and documentation to use the simpler API where async completion handling is not needed.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
morris
2026-06-05 12:07:17 +08:00
co-authored by Cursor
parent 1d311a7349
commit 6bc9814ffb
5 changed files with 73 additions and 19 deletions
@@ -4,6 +4,9 @@
* SPDX-License-Identifier: Apache-2.0
*/
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include "freertos/task.h"
#include "esp_check.h"
#include "esp_async_memcpy.h"
#include "esp_async_memcpy_priv.h"
@@ -22,6 +25,38 @@ esp_err_t esp_async_memcpy(async_memcpy_handle_t asmcp, void *dst, void *src, si
return asmcp->memcpy(asmcp, dst, src, n, cb_isr, cb_args);
}
typedef struct {
SemaphoreHandle_t semaphore;
StaticSemaphore_t semaphore_buffer;
} memcpy_blocking_context_t;
static bool memcpy_blocking_callback(async_memcpy_handle_t mcp_hdl, async_memcpy_event_t *event, void *user_data)
{
BaseType_t task_woken = pdFALSE;
memcpy_blocking_context_t *ctx = (memcpy_blocking_context_t *)user_data;
(void)mcp_hdl;
(void)event;
xSemaphoreGiveFromISR(ctx->semaphore, &task_woken);
return task_woken == pdTRUE;
}
esp_err_t esp_memcpy_blocking(async_memcpy_handle_t asmcp, void *dst, void *src, size_t n, int32_t timeout_ms)
{
ESP_RETURN_ON_FALSE(asmcp && dst && src && n, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
ESP_RETURN_ON_FALSE(!xPortInIsrContext(), ESP_ERR_INVALID_STATE, TAG, "called from ISR context is not allowed");
ESP_RETURN_ON_FALSE(timeout_ms == -1, ESP_ERR_INVALID_ARG, TAG, "only timeout_ms=-1 is supported");
memcpy_blocking_context_t ctx = {};
ctx.semaphore = xSemaphoreCreateBinaryStatic(&ctx.semaphore_buffer);
ESP_RETURN_ON_ERROR(esp_async_memcpy(asmcp, dst, src, n, memcpy_blocking_callback, &ctx), TAG, "failed to start memory copy");
xSemaphoreTake(ctx.semaphore, portMAX_DELAY);
return ESP_OK;
}
#if SOC_ETM_SUPPORTED
esp_err_t esp_async_memcpy_new_etm_event(async_memcpy_handle_t asmcp, async_memcpy_etm_event_t event_type, esp_etm_event_handle_t *out_event)
{