diff --git a/docs/en/api-reference/system/async_memcpy.rst b/docs/en/api-reference/system/async_memcpy.rst index a16874232b..37ef709aea 100644 --- a/docs/en/api-reference/system/async_memcpy.rst +++ b/docs/en/api-reference/system/async_memcpy.rst @@ -1,6 +1,8 @@ Asynchronous Memory Copy ======================== +:link_to_translation:`zh_CN:[中文]` + Overview -------- @@ -18,29 +20,28 @@ The DMA allows multiple memory copy requests to be queued up before the first on If the async memcpy is constructed upon the AXI GDMA, it is also possible to copy data from/to PSRAM with a proper alignment. + Configure and Install Driver ---------------------------- -There are several ways to install the async memcpy driver, depending on the underlying DMA engine. +There are several ways to install the async memcpy driver, depending on the underlying DMA engine: .. list:: :SOC_CP_DMA_SUPPORTED: - :cpp:func:`esp_async_memcpy_install_cpdma` is used to install the async memcpy driver based on the CP DMA engine. :SOC_AHB_GDMA_SUPPORTED: - :cpp:func:`esp_async_memcpy_install_gdma_ahb` is used to install the async memcpy driver based on the AHB GDMA engine. :SOC_AXI_GDMA_SUPPORTED: - :cpp:func:`esp_async_memcpy_install_gdma_axi` is used to install the async memcpy driver based on the AXI GDMA engine. - - :cpp:func:`esp_async_memcpy_install` is a generic API to install the async memcpy driver with a default DMA engine. If the SOC has the CP_DMA engine, the default DMA engine is CP_DMA. Otherwise, the default DMA engine is AHB_GDMA. + - :cpp:func:`esp_async_memcpy_install` is a generic API to install the async memcpy driver with a default DMA engine. If the SoC has the CP_DMA engine, the default DMA engine is CP_DMA. Otherwise, the default DMA engine is AHB_GDMA. Driver configuration is described in :cpp:type:`async_memcpy_config_t`: -* :cpp:member:`backlog`: This is used to configure the maximum number of memory copy transactions that can be queued up before the first one is completed. If this field is set to zero, then the default value (i.e., 4) will be applied. +* :cpp:member:`backlog`: This is used to configure the maximum number of memory copy transactions that can be queued up before the first one is completed. If this field is set to zero, then the default value 4 will be applied. * :cpp:member:`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. * :cpp:member:`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 is set to zero. Internally, the driver configures the size of block used by DMA to access PSRAM, according to the alignment. * :cpp:member:`flags`: This is used to enable some special driver features. .. code-block:: c -:: - async_memcpy_config_t config = ASYNC_MEMCPY_DEFAULT_CONFIG(); // update the maximum data stream supported by underlying DMA engine config.backlog = 8; @@ -52,14 +53,12 @@ Send Memory Copy Request :cpp:func:`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``, you can optionally pass a callback to :cpp:func:`esp_async_memcpy`, so that you can be notified when the memory copy is finished. Note, the callback is executed in the ISR context, please make sure you will not call any blocking functions in the callback. +Different from the libc version of ``memcpy``, you can optionally pass a callback to :cpp:func:`esp_async_memcpy`, so that you can be notified when the memory copy is finished. Note that the callback is executed in the ISR context, please make sure you will not call any blocking functions in the callback. The prototype of the callback function is :cpp:type:`async_memcpy_isr_cb_t`. The callback function should only return true if it wakes up a high priority task by RTOS APIs like :cpp:func:`xSemaphoreGiveFromISR`. .. code-block:: c -:: - // Callback implementation, running in ISR context static bool my_async_memcpy_cb(async_memcpy_handle_t mcp_hdl, async_memcpy_event_t *event, void *cb_args) { @@ -77,6 +76,7 @@ The prototype of the callback function is :cpp:type:`async_memcpy_isr_cb_t`. The // Do something else here xSemaphoreTake(my_semaphore, portMAX_DELAY); // Wait until the buffer copy is done + Uninstall Driver ---------------- diff --git a/docs/zh_CN/api-reference/system/async_memcpy.rst b/docs/zh_CN/api-reference/system/async_memcpy.rst index 874bf78c2c..bfba6be1da 100644 --- a/docs/zh_CN/api-reference/system/async_memcpy.rst +++ b/docs/zh_CN/api-reference/system/async_memcpy.rst @@ -1 +1,97 @@ -.. include:: ../../../en/api-reference/system/async_memcpy.rst \ No newline at end of file +异步内存复制 +======================== + +:link_to_translation:`en:[English]` + +概述 +-------- + +{IDF_TARGET_NAME} 有一个 DMA 引擎,能够以异步方式帮助 CPU 完成内部内存复制操作。 + +异步 memcpy API 中封装了所有 DMA 配置和操作,:cpp:func:`esp_async_memcpy` 的签名与标准 C 库的 ``memcpy`` 函数基本相同。 + +DMA 允许多个内存复制请求在首个请求完成之前排队,即允许计算和内存复制的重叠。此外,通过注册事件回调函数,还可以知道内存复制请求完成的准确时间。 + +.. only:: SOC_AHB_GDMA_SUPPORT_PSRAM + + 如果异步 memcpy 是基于 AHB GDMA 构建的,那么也可以用适合的对齐方式从 PSRAM 复制数据或向其中复制数据。 + +.. only:: SOC_AXI_GDMA_SUPPORT_PSRAM + + 如果异步 memcpy 是基于 AXI GDMA 构建的,那么也可以用适合的对齐方式从 PSRAM 复制数据或向其中复制数据。 + + +配置并安装驱动 +---------------------------- + +安装异步 memcpy 驱动的方法取决于底层 DMA 引擎: + +.. list:: + + :SOC_CP_DMA_SUPPORTED: - :cpp:func:`esp_async_memcpy_install_cpdma` 用于安装基于 CP DMA 引擎的异步 memcpy 驱动。 + :SOC_AHB_GDMA_SUPPORTED: - :cpp:func:`esp_async_memcpy_install_gdma_ahb` 用于安装基于 AHB GDMA 引擎的异步 memcpy 驱动。 + :SOC_AXI_GDMA_SUPPORTED: - :cpp:func:`esp_async_memcpy_install_gdma_axi` 用于安装基于 AXI GDMA 引擎的异步 memcpy 驱动。 + - :cpp:func:`esp_async_memcpy_install` 是一个通用 API,用于安装带有默认 DMA 引擎的异步 memcpy 驱动。如果 SoC 具有 CP_DMA 引擎,则默认 DMA 引擎为 CP_DMA,否则,默认 DMA 引擎为 AHB_GDMA。 + +在 :cpp:type:`async_memcpy_config_t` 中设置驱动配置: + +* :cpp:member:`backlog`:此项用于配置首个请求完成前可以排队的最大内存复制事务数量。如果将此字段设置为零,会应用默认值 4。 +* :cpp:member:`sram_trans_align`:声明 SRAM 中数据地址和复制大小的对齐方式,如果数据没有对齐限制,则设置为零。如果设置为四的倍数值(即 4X),驱动程序将内部启用突发模式,这有利于某些和性能相关的应用程序。 +* :cpp:member:`psram_trans_align`:声明 PSRAM 中数据地址和复制大小声明对齐方式。如果 memcpy 的目标地址位于 PSRAM 中,用户必须给出有一个效值(只支持 16、32、64)。如果设置为零,会默认采用 16 位对齐。在内部,驱动程序会根据对齐方式来配置 DMA 访问 PSRAM 时所用的块大小。 +* :cpp:member:`flags`:此项可以启用一些特殊的驱动功能。 + +.. code-block:: c + + async_memcpy_config_t config = ASYNC_MEMCPY_DEFAULT_CONFIG(); + // 更新底层 DMA 引擎支持的最大数据流 + config.backlog = 8; + async_memcpy_handle_t driver = NULL; + ESP_ERROR_CHECK(esp_async_memcpy_install(&config, &driver)); // 使用默认 DMA 引擎安装驱动 + +发送内存复制请求 +------------------------ + +使用 :cpp:func:`esp_async_memcpy` API 将内存复制请求发送到 DMA 引擎。在驱动程序成功安装后才能调用该 API。此 API 是线程安全的,因此可以从不同的任务中调用。 + +与 libc 版本的 ``memcpy`` 不同,你可以选择给 :cpp:func:`esp_async_memcpy` 设置一个回调函数,以便在内存复制完成时收到通知。注意,回调是在 ISR 上下文中执行的,请不要在回调中调用任何阻塞函数。 + +回调函数的原型是 :cpp:type:`async_memcpy_isr_cb_t`。回调函数只有在借助 RTOS API(如 :cpp:func:`xSemaphoreGiveFromISR`)唤醒了高优先级任务后才能返回 true。 + +.. code-block:: c + + // 回调实现,在 ISR 上下文中运行 + static bool my_async_memcpy_cb(async_memcpy_handle_t mcp_hdl, async_memcpy_event_t *event, void *cb_args) + { + SemaphoreHandle_t sem = (SemaphoreHandle_t)cb_args; + BaseType_t high_task_wakeup = pdFALSE; + xSemaphoreGiveFromISR(semphr, &high_task_wakeup); // 如果解锁了一些高优先级任务,则将 high_task_wakeup 设置为 pdTRUE + return high_task_wakeup == pdTRUE; + } + + // 创建一个信号量,在异步 memcpy 完成时进行报告 + SemaphoreHandle_t semphr = xSemaphoreCreateBinary(); + + // 从用户的上下文中调用 + ESP_ERROR_CHECK(esp_async_memcpy(driver_handle, to, from, copy_len, my_async_memcpy_cb, my_semaphore)); + // 其他事项 + xSemaphoreTake(my_semaphore, portMAX_DELAY); // 等待 buffer 复制完成 + + +卸载驱动 +---------------- + +使用 :cpp:func:`esp_async_memcpy_uninstall` 卸载异步 memcpy 驱动。无需在每次 memcpy 操作后手动卸载。如果你的应用程序不再需要此驱动,此 API 可以帮助回收内存和其他硬件资源。 + +.. only:: SOC_ETM_SUPPORTED and SOC_GDMA_SUPPORT_ETM + + ETM 事件 + --------- + + 在异步 memcpy 操作完成时会生成一个事件,此事件能够与 :doc:`ETM ` 模块进行交互。可以调用 :cpp:func:`esp_async_memcpy_new_etm_event` 获取 ETM 事件句柄。 + + 如需了解如何将此事件连接到 ETM 通道,请参考文档 :doc:`ETM `。 + +API 参考 +------------- + +.. include-build-file:: inc/esp_async_memcpy.inc