docs(dma2d): added async color convert programming guide

This commit is contained in:
morris
2026-06-30 12:00:13 +08:00
parent 2d1782900e
commit 3160a1a73f
7 changed files with 596 additions and 0 deletions
+2
View File
@@ -368,6 +368,7 @@ conditional_include_dict = {
'SOC_ECDSA_SUPPORTED': ['api-reference/peripherals/ecdsa.rst'],
'SOC_HMAC_SUPPORTED': ['api-reference/peripherals/hmac.rst'],
'SOC_ASYNC_MEMCPY_SUPPORTED': ['api-reference/system/async_memcpy.rst'],
'SOC_DMA2D_SUPPORTED': ['api-reference/peripherals/async_color_convert.rst'],
'SOC_KEY_MANAGER_SUPPORTED': ['api-reference/peripherals/key_manager.rst'],
'CONFIG_IDF_TARGET_ARCH_XTENSA': XTENSA_DOCS,
'CONFIG_IDF_TARGET_ARCH_RISCV': RISCV_DOCS,
@@ -409,6 +410,7 @@ conditional_include_dict = {
extensions += [ # noqa: F405
'sphinx_copybutton',
'sphinxcontrib.wavedrom',
'sphinxcontrib.mermaid',
# Note: order is important here, events must
# be registered by one extension before they can be
# connected to another extension
+1
View File
@@ -96,6 +96,7 @@ INPUT = \
$(PROJECT_PATH)/components/esp_driver_dac/include/driver/dac_cosine.h \
$(PROJECT_PATH)/components/esp_driver_dac/include/driver/dac_oneshot.h \
$(PROJECT_PATH)/components/esp_driver_dac/include/driver/dac_types.h \
$(PROJECT_PATH)/components/esp_driver_dma/include/esp_async_color_convert.h \
$(PROJECT_PATH)/components/esp_driver_dma/include/esp_async_memcpy.h \
$(PROJECT_PATH)/components/esp_driver_gpio/include/driver/dedic_gpio.h \
$(PROJECT_PATH)/components/esp_driver_gpio/include/driver/gpio.h \
@@ -0,0 +1,295 @@
=============================
Asynchronous Color Conversion
=============================
:link_to_translation:`zh_CN:[中文]`
This document introduces the Async Color Convert driver in ESP-IDF. The table of contents is as follows:
.. contents::
:local:
:depth: 2
Overview
========
{IDF_TARGET_NAME} provides a DMA2D engine that can offload 2D copy and color conversion work from the CPU.
This driver is useful when your application needs to:
- convert an image from one pixel format to another
- copy only a window of a larger image
- queue multiple conversions without doing the work on the CPU
- move between RGB and UYVY formats while selecting the RGB/YUV conversion standard
The Async Color Convert driver wraps DMA2D request preparation, queueing, and completion handling into a small API that supports both:
- asynchronous submission with an ISR callback
- a simpler blocking API built on top of the same request path
Quick Start
===========
If you are new to this driver, start with the simplest workflow:
1. Install the driver
2. Prepare one :cpp:type:`async_color_convert_request_t`
3. Submit the conversion through either the blocking or non-blocking API
4. Consume the converted output buffer after the conversion completes
5. Either submit another request or uninstall the driver when finished
The typical usage flow is:
.. mermaid::
flowchart TD
install["Install driver<br/>esp_async_color_convert_install_dma2d"] --> request["Prepare request<br/>async_color_convert_request_t"]
request --> blocking["Blocking path<br/>esp_color_convert_blocking"]
request --> nonBlocking["Non-blocking path<br/>esp_async_color_convert"]
nonBlocking --> callback["Wait for callback or task notification"]
blocking --> result["Use converted buffer"]
callback --> result
result --> request
result --> uninstall["Optional cleanup<br/>esp_async_color_convert_uninstall"]
Scenario 1: Start with One Blocking Conversion
==============================================
The easiest way to learn the API is to convert one image and wait until the conversion is complete.
The following flow mirrors the :example:`peripherals/dma/async_color_convert` example. It converts one embedded UYVY422 image into BGR24 and then lets the application consume the converted output:
.. code:: c
async_color_convert_handle_t conv_hdl = NULL; // Driver handle returned by the install API
async_color_convert_config_t config = {
.backlog = 1, // One in-flight request is enough for this simple blocking example
.dma_burst_size = 16, // Start with the default burst size used by the example
};
// Create one Async Color Convert driver instance backed by DMA2D.
ESP_ERROR_CHECK(esp_async_color_convert_install_dma2d(&config, &conv_hdl));
async_color_convert_request_t req = {
.src_buffer = sample_96x64_uyvy_yuv_start, // Source image can be in flash or RAM, as long as DMA can access it
.src_stride = 96, // Source image row stride, in pixels
.src_height = 64, // Source image height, in pixels
.src_x = 0, // Start from the left edge of the source image
.src_y = 0,
.dst_buffer = dst_bgr, // Destination buffer in DMA-capable RAM
.dst_stride = 96, // Destination image row stride, in pixels
.dst_height = 64, // Destination image height, in pixels
.dst_x = 0, // Write the converted output from the top-left corner
.dst_y = 0,
.copy_width = 96, // Convert the full image width, in pixels
.copy_height = 64, // Convert the full image height, in pixels
.src_color_format = ESP_COLOR_FOURCC_UYVY, // Source pixels are UYVY422
.dst_color_format = ESP_COLOR_FOURCC_BGR24, // Destination pixels are BGR24 (used as RGB888 in this driver)
.color_conv_std = COLOR_CONV_STD_RGB_YUV_BT601, // RGB/YUV standard used for this conversion pair
};
// Wait until DMA2D finishes the conversion. -1 means wait forever.
ESP_ERROR_CHECK(esp_color_convert_blocking(conv_hdl, &req, -1));
// Release the driver after all conversions are done.
ESP_ERROR_CHECK(esp_async_color_convert_uninstall(conv_hdl));
This flow introduces the most important ideas:
- :cpp:func:`esp_async_color_convert_install_dma2d` creates the driver instance
- :cpp:type:`async_color_convert_request_t` describes the source image, destination image, and conversion window
- :cpp:func:`esp_color_convert_blocking` waits until the hardware finishes the conversion
- :cpp:func:`esp_async_color_convert_uninstall` releases the driver resources
For the blocking API, ``timeout_ms = -1`` means wait forever. Other timeout values are currently unsupported and return ``ESP_ERR_INVALID_ARG``.
Understanding ``async_color_convert_request_t``
-----------------------------------------------
Most application issues come from building the request incorrectly, so it is worth understanding the structure carefully.
.. important::
In :cpp:type:`async_color_convert_request_t`, all geometry fields are measured in **pixels**, not bytes. This includes ``src_stride``, ``src_height``, ``src_x``, ``src_y``, ``dst_stride``, ``dst_height``, ``dst_x``, ``dst_y``, ``copy_width``, and ``copy_height``.
``src_stride`` and ``dst_stride`` are row strides, not conversion widths. They describe how many pixels each full image row spans in memory, so they can be larger than ``copy_width`` when converting a window inside a larger image.
The structure describes two things at the same time:
- the full source and destination images in memory
- the rectangular window that should be converted
The key fields are:
- :cpp:member:`async_color_convert_request_t::src_buffer`
Base address of the source image
- :cpp:member:`async_color_convert_request_t::src_stride`
Source image row stride in pixels
- :cpp:member:`async_color_convert_request_t::src_height`
Source image height in pixels
- :cpp:member:`async_color_convert_request_t::src_x` and :cpp:member:`async_color_convert_request_t::src_y`
Top-left corner of the source window
- :cpp:member:`async_color_convert_request_t::dst_buffer`
Base address of the destination image
- :cpp:member:`async_color_convert_request_t::dst_stride`
Destination image row stride in pixels
- :cpp:member:`async_color_convert_request_t::dst_height`
Destination image height in pixels
- :cpp:member:`async_color_convert_request_t::dst_x` and :cpp:member:`async_color_convert_request_t::dst_y`
Top-left corner of where the converted window should be written
- :cpp:member:`async_color_convert_request_t::copy_width` and :cpp:member:`async_color_convert_request_t::copy_height`
Size of the rectangle to convert
- :cpp:member:`async_color_convert_request_t::src_color_format` and :cpp:member:`async_color_convert_request_t::dst_color_format`
Source and destination pixel formats
- :cpp:member:`async_color_convert_request_t::color_conv_std`
RGB/YUV conversion standard, used for RGB <-> YUV conversions
Both the source window and destination window must stay within the bounds of their corresponding images.
Supported Conversions
---------------------
The following format pairs are supported by this driver:
.. list-table::
:header-rows: 1
* - Source format
- Destination format
- Conversion standard
* - same as destination (skip conversion)
- same as source (skip conversion)
- N/A
* - RGB565
- RGB888
- N/A
* - RGB888
- RGB565
- N/A
* - RGB888
- UYVY422
- BT.601
* - RGB888
- UYVY422
- BT.709
* - UYVY422
- RGB888
- BT.601
* - UYVY422
- RGB888
- BT.709
.. note::
In this driver, RGB888 uses ``ESP_COLOR_FOURCC_BGR24`` and UYVY422 uses ``ESP_COLOR_FOURCC_UYVY``.
Always set :cpp:member:`async_color_convert_request_t::src_color_format` and
:cpp:member:`async_color_convert_request_t::dst_color_format`.
Set :cpp:member:`async_color_convert_request_t::color_conv_std` when converting between RGB and YUV.
Scenario 2: Use the Asynchronous API with a Callback
====================================================
Once the blocking flow is clear, the next step is to queue a request and let the driver notify you from interrupt context when it is finished.
.. code:: c
static bool color_conv_done_cb(async_color_convert_handle_t conv_hdl,
async_color_convert_event_data_t *edata,
void *cb_args)
{
BaseType_t high_task_wakeup = pdFALSE; // Required by FreeRTOS when an ISR wakes a task
SemaphoreHandle_t sem = (SemaphoreHandle_t)cb_args; // User context passed at submit time
// Notify a waiting task that the conversion has finished.
xSemaphoreGiveFromISR(sem, &high_task_wakeup);
// Return true when the unblocked task should run immediately after the ISR.
return high_task_wakeup == pdTRUE;
}
async_color_convert_request_t req = {
.src_buffer = src_buf, // Source image base address
.src_stride = src_width, // Source image row stride, in pixels
.src_height = src_height,
.src_x = 0,
.src_y = 0,
.dst_buffer = dst_buf, // Destination image base address
.dst_stride = dst_width, // Destination image row stride, in pixels
.dst_height = dst_height,
.dst_x = 0,
.dst_y = 0,
.copy_width = copy_width,
.copy_height = copy_height,
.src_color_format = ESP_COLOR_FOURCC_RGB16,
.dst_color_format = ESP_COLOR_FOURCC_BGR24,
};
// Queue one asynchronous request. The callback runs later in ISR context.
ESP_ERROR_CHECK(esp_async_color_convert(conv_hdl, &req, color_conv_done_cb, sem));
// Wait in task context until the callback gives the semaphore.
xSemaphoreTake(sem, portMAX_DELAY);
The callback runs in ISR context, so keep it short and only use ISR-safe APIs such as ``xSemaphoreGiveFromISR`` or ``xQueueSendFromISR``.
Operational Notes
=================
Driver Configuration
--------------------
The driver configuration fields are:
- :cpp:member:`async_color_convert_config_t::backlog`
Maximum number of in-flight or pending requests. ``0`` uses a driver default.
- :cpp:member:`async_color_convert_config_t::dma_burst_size`
DMA burst size in bytes. ``0`` uses a driver default.
- :cpp:member:`async_color_convert_config_t::intr_priority`
DMA2D interrupt priority. ``0`` uses the default low/medium priority.
DMA Burst Size
--------------
The ``dma_burst_size`` affects DMA transfer efficiency:
- Larger burst sizes may improve throughput
- Larger burst sizes can also increase bus occupancy, so they are not always best for every workload
- Common starting values are 16, 32, and 64 bytes
The best value depends on the chip's DMA controller capabilities and how much memory bandwidth is shared with other active components in the system.
Thread Safety and ISR Rules
---------------------------
- The driver is thread-safe. Requests from different tasks are serialized through the internal queue.
- :cpp:func:`esp_async_color_convert` can be called from tasks to enqueue requests.
- The callback type :cpp:type:`async_color_convert_isr_cb_t` runs in ISR context.
- Do not call blocking APIs from the callback.
- :cpp:func:`esp_color_convert_blocking` must not be called from ISR context.
Uninstalling the Driver
-----------------------
When the driver is no longer needed:
.. code:: c
// Uninstall only after all queued conversions have completed.
ESP_ERROR_CHECK(esp_async_color_convert_uninstall(conv_hdl));
If requests are still pending, :cpp:func:`esp_async_color_convert_uninstall` returns :c:macro:`ESP_ERR_INVALID_STATE`.
Application Example
===================
- :example:`peripherals/dma/async_color_convert` shows a beginner-friendly blocking conversion flow:
- an embedded ``.yuv`` image is read directly from mapped flash
- DMA2D converts the image from UYVY422 to BGR24
- the converted output is base64-encoded and printed to the console
- pytest reconstructs the image as a PNG artifact and compares it against a golden reference image
API Reference
=============
Async Color Convert Driver Functions
------------------------------------
.. include-build-file:: inc/esp_async_color_convert.inc
@@ -8,6 +8,7 @@ Peripherals API
:SOC_ADC_SUPPORTED: adc/index
:SOC_ANA_CMPR_SUPPORTED: ana_cmpr
:SOC_DMA2D_SUPPORTED: async_color_convert
:SOC_BITSCRAMBLER_SUPPORTED: bitscrambler
:SOC_MIPI_CSI_SUPPORTED: camera_driver
:SOC_CLK_TREE_SUPPORTED: clk_tree
@@ -0,0 +1,295 @@
================
异步色彩格式转换
================
:link_to_translation:`en:[English]`
本文介绍 ESP-IDF 中的异步色彩转换驱动。目录如下:
.. contents::
:local:
:depth: 2
概述
====
{IDF_TARGET_NAME} 提供 DMA2D 引擎,可以把 2D 拷贝和色彩转换工作从 CPU 卸载到硬件执行。
这个驱动适合用于:
- 将图像从一种像素格式转换为另一种像素格式
- 只转换大图中的一个矩形窗口
- 将多个转换请求排队,而不是让 CPU 自己做像素搬运
- 在 RGB 和 UYVY 格式之间转换,并选择 RGB/YUV 转换标准
异步色彩转换驱动对 DMA2D 的请求准备、队列管理和完成通知做了封装,同时提供两种使用方式:
- 带 ISR 回调通知的异步提交接口
- 基于同一路径实现、对新手更友好的阻塞接口
快速开始
========
如果你是第一次使用这个驱动,建议从最简单的流程开始:
1. 安装驱动
2. 准备一个 :cpp:type:`async_color_convert_request_t`
3. 通过阻塞或非阻塞 API 发起转换
4. 在转换完成后使用输出 buffer
5. 继续提交新请求,或在结束时卸载驱动
典型使用流程如下:
.. mermaid::
flowchart TD
install["安装驱动<br/>esp_async_color_convert_install_dma2d"] --> request["准备请求<br/>async_color_convert_request_t"]
request --> blocking["阻塞路径<br/>esp_color_convert_blocking"]
request --> nonBlocking["非阻塞路径<br/>esp_async_color_convert"]
nonBlocking --> callback["等待回调或任务通知"]
blocking --> result["使用转换结果 buffer"]
callback --> result
result --> request
result --> uninstall["可选清理<br/>esp_async_color_convert_uninstall"]
场景 1:先从一次阻塞转换开始
============================
理解这个驱动的最简单方式,就是先完成一次转换,并在函数返回时直接拿到结果。
下面的流程与 :example:`peripherals/dma/async_color_convert` 示例一致。它把一个嵌入在 flash 中的 UYVY422 图像转换为 BGR24,然后由应用继续处理转换后的输出:
.. code:: c
async_color_convert_handle_t conv_hdl = NULL; // 安装驱动后返回的句柄,后续 API 都要用到它
async_color_convert_config_t config = {
.backlog = 1, // 这个阻塞示例一次只处理一个请求,因此 1 就够了
.dma_burst_size = 16, // 先使用示例里的默认 burst 大小即可
};
// 创建一个基于 DMA2D 后端的异步色彩转换驱动实例。
ESP_ERROR_CHECK(esp_async_color_convert_install_dma2d(&config, &conv_hdl));
async_color_convert_request_t req = {
.src_buffer = sample_96x64_uyvy_yuv_start, // 源图像可以在 flash 或者 RAM 中,只要 DMA 可访问即可
.src_stride = 96, // 源图像的行跨度,单位是像素
.src_height = 64, // 源图像高度,单位是像素
.src_x = 0, // 从源图像左上角开始取窗口
.src_y = 0,
.dst_buffer = dst_bgr, // 目标 buffer 位于 DMA 可访问的 RAM 中
.dst_stride = 96, // 目标图像的行跨度,单位是像素
.dst_height = 64, // 目标图像高度,单位是像素
.dst_x = 0, // 从目标图像左上角开始写入结果
.dst_y = 0,
.copy_width = 96, // 转换整张图的宽度,单位是像素
.copy_height = 64, // 转换整张图的高度,单位是像素
.src_color_format = ESP_COLOR_FOURCC_UYVY, // 源像素格式为 UYVY422
.dst_color_format = ESP_COLOR_FOURCC_BGR24, // 目标像素格式为 BGR24(本驱动里用它表示 RGB888)
.color_conv_std = COLOR_CONV_STD_RGB_YUV_BT601, // 该 RGB/YUV 转换使用的标准
};
// 阻塞等待 DMA2D 完成转换。-1 表示一直等到完成为止。
ESP_ERROR_CHECK(esp_color_convert_blocking(conv_hdl, &req, -1));
// 所有转换结束后,释放驱动资源。
ESP_ERROR_CHECK(esp_async_color_convert_uninstall(conv_hdl));
这个流程里最重要的概念有:
- :cpp:func:`esp_async_color_convert_install_dma2d` 创建驱动实例
- :cpp:type:`async_color_convert_request_t` 描述源图像、目标图像以及要转换的窗口
- :cpp:func:`esp_color_convert_blocking` 会一直等待,直到硬件完成转换
- :cpp:func:`esp_async_color_convert_uninstall` 释放驱动资源
对于阻塞 API,``timeout_ms = -1`` 表示永久等待。其他 timeout 值目前不支持,会返回 ``ESP_ERR_INVALID_ARG``。
理解 ``async_color_convert_request_t``
--------------------------------------
这个驱动最容易出错的地方,通常不是安装驱动,而是请求参数填写不正确,因此理解 :cpp:type:`async_color_convert_request_t` 很重要。
.. important::
在 :cpp:type:`async_color_convert_request_t` 中,所有几何相关字段的单位都是 **像素**,不是字节。包括 ``src_stride``、``src_height``、``src_x``、``src_y``、``dst_stride``、``dst_height``、``dst_x``、``dst_y``、``copy_width`` 和 ``copy_height``。
``src_stride`` 和 ``dst_stride`` 表示的是每一整行在内存中跨越多少像素,也就是行跨度,不是本次转换窗口的宽度。当你只转换大图中的一个窗口时,它们可以大于 ``copy_width``。
这个结构体同时描述了两件事:
- 源图像和目标图像在内存中的完整布局
- 本次实际要转换的矩形窗口
关键字段含义如下:
- :cpp:member:`async_color_convert_request_t::src_buffer`
源图像基地址
- :cpp:member:`async_color_convert_request_t::src_stride`
源图像的行跨度,单位为像素
- :cpp:member:`async_color_convert_request_t::src_height`
源图像高度,单位为像素
- :cpp:member:`async_color_convert_request_t::src_x` 和 :cpp:member:`async_color_convert_request_t::src_y`
源窗口左上角坐标
- :cpp:member:`async_color_convert_request_t::dst_buffer`
目标图像基地址
- :cpp:member:`async_color_convert_request_t::dst_stride`
目标图像的行跨度,单位为像素
- :cpp:member:`async_color_convert_request_t::dst_height`
目标图像高度,单位为像素
- :cpp:member:`async_color_convert_request_t::dst_x` 和 :cpp:member:`async_color_convert_request_t::dst_y`
转换结果写入目标图像时的左上角坐标
- :cpp:member:`async_color_convert_request_t::copy_width` 和 :cpp:member:`async_color_convert_request_t::copy_height`
本次要转换的矩形窗口尺寸
- :cpp:member:`async_color_convert_request_t::src_color_format` 和 :cpp:member:`async_color_convert_request_t::dst_color_format`
源和目标像素格式
- :cpp:member:`async_color_convert_request_t::color_conv_std`
RGB/YUV 转换标准,用于 RGB 和 YUV 之间的转换
源窗口和目标窗口都必须完整落在各自图像的边界之内。
支持的转换格式
--------------
本驱动支持以下格式组合:
.. list-table::
:header-rows: 1
* - 源格式
- 目标格式
- 转换标准
* - 与目标格式相同(跳过转换)
- 与源格式相同(跳过转换)
- 不适用
* - RGB565
- RGB888
- 不适用
* - RGB888
- RGB565
- 不适用
* - RGB888
- UYVY422
- BT.601
* - RGB888
- UYVY422
- BT.709
* - UYVY422
- RGB888
- BT.601
* - UYVY422
- RGB888
- BT.709
.. note::
在本驱动中,RGB888 使用 ``ESP_COLOR_FOURCC_BGR24``,UYVY422 使用 ``ESP_COLOR_FOURCC_UYVY``。
所有请求都需要设置 :cpp:member:`async_color_convert_request_t::src_color_format` 和
:cpp:member:`async_color_convert_request_t::dst_color_format`。
当在 RGB 和 YUV 之间转换时,还需要设置 :cpp:member:`async_color_convert_request_t::color_conv_std`。
场景 2:使用异步接口和回调函数
==============================
理解了阻塞流程之后,下一步就是把请求排入队列,并在硬件完成后由中断上下文中的回调通知你。
.. code:: c
static bool color_conv_done_cb(async_color_convert_handle_t conv_hdl,
async_color_convert_event_data_t *edata,
void *cb_args)
{
BaseType_t high_task_wakeup = pdFALSE; // FreeRTOS 在 ISR 中唤醒任务时需要这个变量
SemaphoreHandle_t sem = (SemaphoreHandle_t)cb_args; // 提交请求时传进来的用户上下文
// 用 ISR-safe 的方式通知等待中的任务:这次转换已经完成。
xSemaphoreGiveFromISR(sem, &high_task_wakeup);
// 如果刚才唤醒了更高优先级任务,就请求在 ISR 退出后立刻切换过去。
return high_task_wakeup == pdTRUE;
}
async_color_convert_request_t req = {
.src_buffer = src_buf, // 源图像基地址
.src_stride = src_width, // 源图像的行跨度,单位是像素
.src_height = src_height,
.src_x = 0,
.src_y = 0,
.dst_buffer = dst_buf, // 目标图像基地址
.dst_stride = dst_width, // 目标图像的行跨度,单位是像素
.dst_height = dst_height,
.dst_x = 0,
.dst_y = 0,
.copy_width = copy_width,
.copy_height = copy_height,
.src_color_format = ESP_COLOR_FOURCC_RGB16,
.dst_color_format = ESP_COLOR_FOURCC_BGR24,
};
// 提交一个异步请求。函数返回时,硬件可能还在执行转换。
ESP_ERROR_CHECK(esp_async_color_convert(conv_hdl, &req, color_conv_done_cb, sem));
// 在任务上下文中等待回调释放信号量。
xSemaphoreTake(sem, portMAX_DELAY);
回调运行在 ISR 上下文中,因此应尽量保持简短,并且只调用 ISR-safe API,例如 ``xSemaphoreGiveFromISR`` 或 ``xQueueSendFromISR``。
运行注意事项
============
驱动配置
--------
驱动配置字段如下:
- :cpp:member:`async_color_convert_config_t::backlog`
最大待处理请求数。``0`` 表示使用驱动默认值。
- :cpp:member:`async_color_convert_config_t::dma_burst_size`
DMA burst 大小,单位为字节。``0`` 表示使用驱动默认值。
- :cpp:member:`async_color_convert_config_t::intr_priority`
DMA2D 中断优先级。``0`` 表示使用默认低/中优先级。
DMA 突发大小
------------
``dma_burst_size`` 会影响 DMA 传输效率:
- 较大的突发大小可能提高吞吐量
- 较大的突发大小也可能增加总线占用,因此并不一定适合所有工作负载
- 常见的起始取值有 16、32 和 64 字节
最佳取值取决于芯片的 DMA 控制器能力,以及系统中其他活跃组件对内存带宽的共享情况。
线程安全与 ISR 规则
-------------------
- 驱动是线程安全的。不同任务提交的请求会通过内部队列串行化。
- :cpp:func:`esp_async_color_convert` 可以在任务上下文中调用,用于排队请求。
- 回调类型 :cpp:type:`async_color_convert_isr_cb_t` 运行在 ISR 上下文中。
- 不要在回调里调用阻塞 API。
- :cpp:func:`esp_color_convert_blocking` 不能在 ISR 上下文中调用。
卸载驱动
--------
当驱动不再需要时:
.. code:: c
// 只有在所有排队请求都完成后,才能安全卸载驱动。
ESP_ERROR_CHECK(esp_async_color_convert_uninstall(conv_hdl));
如果仍有请求未完成,:cpp:func:`esp_async_color_convert_uninstall` 会返回 :c:macro:`ESP_ERR_INVALID_STATE`。
应用示例
========
- :example:`peripherals/dma/async_color_convert` 展示了一个面向初学者的阻塞转换流程:
- 从映射到 flash 的嵌入式 ``.yuv`` 图像直接读取输入
- 使用 DMA2D 将图像从 UYVY422 转换为 BGR24
- 将转换结果做 base64 编码后输出到控制台
- 由 pytest 重建为 PNG 工件,并与 golden 参考图进行比对
API 参考
========
异步颜色转换驱动程序函数
------------------------
.. include-build-file:: inc/esp_async_color_convert.inc
@@ -8,6 +8,7 @@
:SOC_ADC_SUPPORTED: adc/index
:SOC_ANA_CMPR_SUPPORTED: ana_cmpr
:SOC_DMA2D_SUPPORTED: async_color_convert
:SOC_BITSCRAMBLER_SUPPORTED: bitscrambler
:SOC_MIPI_CSI_SUPPORTED: camera_driver
:SOC_CLK_TREE_SUPPORTED: clk_tree
+1
View File
@@ -7,3 +7,4 @@
esp-docs
linuxdoc
sphinxcontrib-mermaid