The Async memcpy API¶
Overview¶
ESP32-S2 has a DMA engine which can help to offload internal memory copy operations from the CPU in a asynchronous way.
The async memcpy API wraps all DMA configurations and operations, the signature of esp_async_memcpy()
is almost the same to the standard libc one.
Thanks to the benefit of the DMA, we don’t have to wait for each memory copy to be done before we issue another memcpy request. By the way, it’s still possible to know when memcpy is finished by listening in the memcpy callback function.
注解
Memory copy from/to external PSRAM is not supported on ESP32-S2, esp_async_memcpy()
will abort returning an error if buffer address is not in SRAM.
Configure and Install driver¶
esp_async_memcpy_install()
is used to install the driver with user’s configuration. Please note that async memcpy has to be called with the handle returned from esp_async_memcpy_install()
.
Driver configuration is described in async_memcpy_config_t
:
backlog
: This is used to configured the maximum number of DMA operation that can be working at the background at the same time.
sram_trans_align
: Declare SRAM alignment for both data address and copy size, set to zero if the data has no restriction in alignment. If set to a quadruple value (i.e. 4X), the driver will enable the burst mode internally, which is helpful for some performance related application.
psram_trans_align
: Declare PSRAM alignment for both data address and copy size. User has to give it a valid value (only 16, 32, 64 are supported) if the destination of memcpy is located in PSRAM. The default alignment (i.e. 16) will be applied if it’s set to zero. Internally, the driver configures the size of block used by DMA to access PSRAM, according to the alignment.
flags
: This is used to enable some special driver features.
ASYNC_MEMCPY_DEFAULT_CONFIG
provides a default configuration, which specifies the backlog to 8.
async_memcpy_config_t config = ASYNC_MEMCPY_DEFAULT_CONFIG();
// update the maximum data stream supported by underlying DMA engine
config.backlog = 16;
async_memcpy_t driver = NULL;
ESP_ERROR_CHECK(esp_async_memcpy_install(&config, &driver)); // install driver, return driver handle
Send memory copy request¶
esp_async_memcpy()
is the API to send memory copy request to DMA engine. It must be called after driver is installed successfully. This API is thread safe, so it can be called from different tasks.
Different from the libc version of memcpy, user should also pass a callback to esp_async_memcpy()
, if it’s necessary to be notified when the memory copy is done. The callback is executed in the ISR context, make sure you won’t violate the the restriction applied to ISR handler.
Besides that, the callback function should reside in IRAM space by applying IRAM_ATTR attribute. The prototype of the callback function is async_memcpy_isr_cb_t
, please note that, the callback function should return true if it wakes up a high priority task by some API like xSemaphoreGiveFromISR()
.
Semphr_Handle_t semphr; //already initialized in somewhere
// Callback implementation, running in ISR context
static IRAM_ATTR bool my_async_memcpy_cb(async_memcpy_t mcp_hdl, async_memcpy_event_t *event, void *cb_args)
{
SemaphoreHandle_t sem = (SemaphoreHandle_t)cb_args;
BaseType_t high_task_wakeup = pdFALSE;
SemphrGiveInISR(semphr, &high_task_wakeup); // high_task_wakeup set to pdTRUE if some high priority task unblocked
return high_task_wakeup == pdTRUE;
}
// Called from user's context
ESP_ERROR_CHECK(esp_async_memcpy(driver_handle, to, from, copy_len, my_async_memcpy_cb, my_semaphore));
//Do something else here
SemphrTake(my_semaphore, ...); //wait until the buffer copy is done
Uninstall driver (optional)¶
esp_async_memcpy_uninstall()
is used to uninstall asynchronous memcpy driver. It’s not necessary to uninstall the driver after each memcpy operation. If you know your application won’t use this driver anymore, then this API can recycle the memory for you.
API Reference¶
Functions¶
-
esp_err_t
esp_async_memcpy_install
(const async_memcpy_config_t *config, async_memcpy_t *asmcp)¶ Install async memcpy driver.
- Return
ESP_OK: Install async memcpy driver successfully
ESP_ERR_INVALID_ARG: Install async memcpy driver failed because of invalid argument
ESP_ERR_NO_MEM: Install async memcpy driver failed because out of memory
ESP_FAIL: Install async memcpy driver failed because of other error
- Parameters
[in] config
: Configuration of async memcpy[out] asmcp
: Handle of async memcpy that returned from this API. If driver installation is failed, asmcp would be assigned to NULL.
-
esp_err_t
esp_async_memcpy_uninstall
(async_memcpy_t asmcp)¶ Uninstall async memcpy driver.
- Return
ESP_OK: Uninstall async memcpy driver successfully
ESP_ERR_INVALID_ARG: Uninstall async memcpy driver failed because of invalid argument
ESP_FAIL: Uninstall async memcpy driver failed because of other error
- Parameters
[in] asmcp
: Handle of async memcpy driver that returned from esp_async_memcpy_install
-
esp_err_t
esp_async_memcpy
(async_memcpy_t asmcp, void *dst, void *src, size_t n, async_memcpy_isr_cb_t cb_isr, void *cb_args)¶ Send an asynchronous memory copy request.
- Return
ESP_OK: Send memory copy request successfully
ESP_ERR_INVALID_ARG: Send memory copy request failed because of invalid argument
ESP_FAIL: Send memory copy request failed because of other error
- Note
The callback function is invoked in interrupt context, never do blocking jobs in the callback.
- Parameters
[in] asmcp
: Handle of async memcpy driver that returned from esp_async_memcpy_install[in] dst
: Destination address (copy to)[in] src
: Source address (copy from)[in] n
: Number of bytes to copy[in] cb_isr
: Callback function, which got invoked in interrupt context. Set to NULL can bypass the callback.[in] cb_args
: User defined argument to be passed to the callback function
Structures¶
-
struct
async_memcpy_event_t
¶ Type of async memcpy event object.
Public Members
-
void *
data
¶ Event data
-
void *
-
struct
async_memcpy_config_t
¶ Type of async memcpy configuration.
Public Members
-
uint32_t
backlog
¶ Maximum number of streams that can be handled simultaneously
-
size_t
sram_trans_align
¶ DMA transfer alignment (both in size and address) for SRAM memory
-
size_t
psram_trans_align
¶ DMA transfer alignment (both in size and address) for PSRAM memory
-
uint32_t
flags
¶ Extra flags to control async memcpy feature
-
uint32_t
Type Definitions¶
-
typedef struct async_memcpy_context_t *
async_memcpy_t
¶ Type of async memcpy handle.
-
typedef bool (*
async_memcpy_isr_cb_t
)(async_memcpy_t mcp_hdl, async_memcpy_event_t *event, void *cb_args)¶ Type of async memcpy interrupt callback function.
- Return
Whether a high priority task is woken up by the callback function
- Note
User can call OS primitives (semaphore, mutex, etc) in the callback function. Keep in mind, if any OS primitive wakes high priority task up, the callback should return true.
- Parameters
mcp_hdl
: Handle of async memcpyevent
: Event object, which contains related data, reserved for futurecb_args
: User defined arguments, passed from esp_async_memcpy function