update camera driver document

This commit is contained in:
Lv Xin Yue
2025-09-23 11:39:53 +08:00
committed by BOT
parent a15ab238fb
commit e559d93da3
2 changed files with 353 additions and 254 deletions

View File

@@ -6,55 +6,60 @@ Camera Controller Driver
Introduction Introduction
------------ ------------
{IDF_TARGET_NAME} has the following hardware that is intended for communication with external camera sensor: {IDF_TARGET_NAME} has the following hardware designed for communication with external camera sensors:
.. list:: .. list::
: SOC_MIPI_CSI_SUPPORTED : - MIPI Camera Serial Interface (MIPI CSI) :SOC_MIPI_CSI_SUPPORTED: - MIPI Camera Serial Interface (MIPI CSI)
: SOC_ISP_DVP_SUPPORTED : - Digital Video Port through ISP module (ISP DVP) :SOC_ISP_DVP_SUPPORTED: - Digital Video Port via ISP module (ISP DVP)
: SOC_LCDCAM_CAM_SUPPORTED : - Digital Video Port through LCD_CAM module(LCD_CAM DVP) :SOC_LCDCAM_CAM_SUPPORTED: - Digital Video Port via LCD_CAM module (LCD_CAM DVP)
The camera controller driver is designed for this hardware peripheral.
The camera controller driver provides an interface for these hardware peripherals.
Functional Overview Functional Overview
------------------- -------------------
.. list:: .. list::
- :ref:`cam-resource-allocation` - covers how to allocate camera controller instances with properly set of configurations. It also covers how to recycle the resources when they are no longer needed. - :ref:`cam-resource-allocation` Describes how to allocate and configure camera controller instances, and how to release resources when no longer needed.
- :ref:`cam-enable-disable` - covers how to enable and disable a camera controller. - :ref:`cam-enable-disable` Explains how to enable and disable a camera controller.
- :ref:`cam-start-stop` - covers how to start and stop a camera controller. - :ref:`cam-start-stop` Details how to start and stop a camera controller.
- :ref:`cam-receive`- covers how to receive camera signal from a sensor or something else. - :ref:`cam-receive` Explains how to receive signals from a camera sensor.
- :ref:`cam-callback`- covers how to hook user specific code to camera controller driver event callback function. - :ref:`cam-callback` Describes how to register user-defined event callback functions.
- :ref:`cam-thread-safety` - lists which APIs are guaranteed to be thread safe by the driver. - :ref:`cam-thread-safety` Lists APIs that are thread-safe.
- :ref:`cam-kconfig-options` - lists the supported Kconfig options that can bring different effects to the driver. - :ref:`cam-kconfig-options` Lists supported Kconfig options that affect driver behavior.
- :ref:`cam-iram-safe` - describes tips on how to make the CSI interrupt and control functions work better along with a disabled cache. - :ref:`cam-iram-safe` Provides guidance on making CSI interrupt and control functions work reliably when the cache is disabled.
.. _cam-resource-allocation: .. _cam-resource-allocation:
Resource Allocation Resource Allocation
^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^
Install Camera Controller Driver Install the Camera Controller Driver
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Camera controller driver can be implemented in one of following ways: You can implement the camera controller driver using one of the following methods:
.. list:: .. list::
: SOC_MIPI_CSI_SUPPORTED : - :cpp:func:`esp_cam_new_csi_ctlr` :SOC_MIPI_CSI_SUPPORTED: - :cpp:func:`esp_cam_new_csi_ctlr`
: SOC_ISP_DVP_SUPPORTED : - :cpp:func:`esp_cam_new_isp_dvp_ctlr` :SOC_ISP_DVP_SUPPORTED: - :cpp:func:`esp_cam_new_isp_dvp_ctlr`
: SOC_LCDCAM_CAM_SUPPORTED : - :cpp:func:`esp_cam_new_lcd_cam_ctlr` :SOC_LCDCAM_CAM_SUPPORTED: - :cpp:func:`esp_cam_new_lcd_cam_ctlr`
.. only:: SOC_MIPI_CSI_SUPPORTED .. only:: SOC_MIPI_CSI_SUPPORTED
A camera controller driver can be implemented by the CSI peripheral, which requires the configuration that specified by :cpp:type:`esp_cam_ctlr_csi_config_t`. You can implement a camera controller driver using the CSI peripheral. This requires configuration via :cpp:type:`esp_cam_ctlr_csi_config_t`.
If the configurations in :cpp:type:`esp_cam_ctlr_csi_config_t` is specified, users can call :cpp:func:`esp_cam_new_csi_ctlr` to allocate and initialize a CSI camera controller handle. This function will return an CSI camera controller handle if it runs correctly. You can take following code as reference. After specifying :cpp:type:`esp_cam_ctlr_csi_config_t`, call :cpp:func:`esp_cam_new_csi_ctlr` to allocate and initialize a CSI camera controller handle. If successful, this function returns a CSI camera controller handle. See the example below.
.. code:: c .. code:: c
#include "esp_cam_ctlr.h"
#include "esp_cam_ctlr_types.h"
#include "esp_cam_ctlr_csi.h"
void app_main(void)
{
esp_cam_ctlr_csi_config_t csi_config = { esp_cam_ctlr_csi_config_t csi_config = {
.ctlr_id = 0, .ctlr_id = 0,
.h_res = MIPI_CSI_DISP_HSIZE, .h_res = MIPI_CSI_DISP_HSIZE,
@@ -66,24 +71,37 @@ Camera controller driver can be implemented in one of following ways:
.byte_swap_en = false, .byte_swap_en = false,
.queue_items = 1, .queue_items = 1,
}; };
esp_cam_ctlr_handle_t handle = NULL; esp_cam_ctlr_handle_t handle = NULL;
ESP_ERROR_CHECK(esp_cam_new_csi_ctlr(&csi_config, &handle)); ESP_ERROR_CHECK(esp_cam_new_csi_ctlr(&csi_config, &handle));
}
The CSI in {IDF_TARGET_NAME} requires stable 2.5V power supply. Please refer to the schematic diagram to ensure that the power supply pins are connected to 2.5V power before using the MIPI CSI driver. The CSI peripheral in {IDF_TARGET_NAME} requires a stable 2.5 V power supply. Refer to the schematic diagram to ensure the power supply pins are connected to 2.5 V before using the MIPI CSI driver.
.. only:: SOC_GP_LDO_SUPPORTED .. only:: SOC_GP_LDO_SUPPORTED
In {IDF_TARGET_NAME}, the CSI can be powered by the internal adjustable LDO. Please connect the LDO channel output pin to the CSI power supply pin. Then, before initializing the CSI driver, use the API provided in :doc:`/api-reference/peripherals/ldo_regulator` to configure the LDO to output 2.5 V voltage. In {IDF_TARGET_NAME}, you can power the CSI using the internal adjustable LDO. Connect the LDO channel output pin to the CSI power supply pin. Before initializing the CSI driver, use the API in :doc:`/api-reference/peripherals/ldo_regulator` to configure the LDO to output 2.5 V.
.. only:: SOC_ISP_DVP_SUPPORTED .. only:: SOC_ISP_DVP_SUPPORTED
A camera controller driver can be implemented by the ISP DVP peripheral, which requires the configuration that specified by :cpp:type:`esp_cam_ctlr_isp_dvp_cfg_t`. You can implement a camera controller driver using the ISP DVP peripheral. This requires configuration via :cpp:type:`esp_cam_ctlr_isp_dvp_cfg_t`.
If the configurations in :cpp:type:`esp_cam_ctlr_isp_dvp_cfg_t` is specified, users can call :cpp:func:`esp_cam_new_isp_dvp_ctlr` to allocate and initialize a ISP DVP camera controller handle. This function will return an ISP DVP camera controller handle if it runs correctly. You can take following code as reference. After specifying :cpp:type:`esp_cam_ctlr_isp_dvp_cfg_t`, call :cpp:func:`esp_cam_new_isp_dvp_ctlr` to allocate and initialize an ISP DVP camera controller handle. If successful, this function returns an ISP DVP camera controller handle. See the example below.
Before calling :cpp:func:`esp_cam_new_isp_dvp_ctlr`, you should also call :cpp:func:`esp_isp_new_processor` to create an ISP handle. Before calling :cpp:func:`esp_cam_new_isp_dvp_ctlr`, create an ISP handle using :cpp:func:`esp_isp_new_processor`.
.. code:: c .. code:: c
#include "esp_err.h"
#include "esp_cam_ctlr.h"
#include "esp_cam_ctlr_isp_dvp.h"
#include "driver/isp.h"
#define MIPI_CSI_DISP_HSIZE 800 // example value, replace with actual resolution
#define MIPI_CSI_DISP_VSIZE 600 // example value, replace with actual resolution
void app_main(void)
{
isp_proc_handle_t isp_proc = NULL; isp_proc_handle_t isp_proc = NULL;
esp_isp_processor_cfg_t isp_config = { esp_isp_processor_cfg_t isp_config = {
.clk_hz = 120 * 1000 * 1000, .clk_hz = 120 * 1000 * 1000,
@@ -97,6 +115,7 @@ Camera controller driver can be implemented in one of following ways:
}; };
ESP_ERROR_CHECK(esp_isp_new_processor(&isp_config, &isp_proc)); ESP_ERROR_CHECK(esp_isp_new_processor(&isp_config, &isp_proc));
esp_cam_ctlr_handle_t cam_handle = NULL;
esp_cam_ctlr_isp_dvp_cfg_t dvp_ctlr_config = { esp_cam_ctlr_isp_dvp_cfg_t dvp_ctlr_config = {
.data_width = 8, .data_width = 8,
.data_io = {53, 54, 52, 0, 1, 45, 46, 47, -1, -1, -1, -1, -1, -1, -1, -1}, .data_io = {53, 54, 52, 0, 1, 45, 46, 47, -1, -1, -1, -1, -1, -1, -1, -1},
@@ -108,30 +127,39 @@ Camera controller driver can be implemented in one of following ways:
.queue_items = 10, .queue_items = 10,
}; };
ESP_ERROR_CHECK(esp_cam_new_isp_dvp_ctlr(isp_proc, &dvp_ctlr_config, &cam_handle)); ESP_ERROR_CHECK(esp_cam_new_isp_dvp_ctlr(isp_proc, &dvp_ctlr_config, &cam_handle));
}
.. only:: SOC_LCDCAM_CAM_SUPPORTED .. only:: SOC_LCDCAM_CAM_SUPPORTED
A camera controller driver can be implemented by the DVP port of LCD_CAM, which requires the configuration that specified by :cpp:type:`esp_cam_ctlr_dvp_config_t`. You can implement a camera controller driver using the DVP port of LCD_CAM. This requires configuration via :cpp:type:`esp_cam_ctlr_dvp_config_t`.
:cpp:member:`esp_cam_ctlr_dvp_config_t::exexternal_xtal`: set this to use externally generated xclk, otherwise the camera driver will generate it internally. :cpp:member:`esp_cam_ctlr_dvp_config_t::exexternal_xtal`: Set this to use an externally generated xclk. Otherwise, the camera driver generates it internally.
If :cpp:type:`esp_cam_ctlr_lcd_cam_cfg_t` is specified, users can call :cpp:func:`esp_cam_new_lcd_cam_ctlr` to allocate and initialize a DVP camera controller handle. This function will return an DVP camera controller handle if it runs correctly. You can take following code as reference. After specifying :cpp:type:`esp_cam_ctlr_lcd_cam_cfg_t`, call :cpp:func:`esp_cam_new_lcd_cam_ctlr` to allocate and initialize a DVP camera controller handle. If successful, this function returns a DVP camera controller handle. See the example below.
After calling :cpp:func:`esp_cam_new_dvp_ctlr`, you should allocate a camera buffer that meets the alignment constraints, or call :cpp:func:`esp_cam_ctlr_alloc_buffer` to automatically allocate. After calling :cpp:func:`esp_cam_new_dvp_ctlr`, allocate a camera buffer that meets alignment constraints, or call :cpp:func:`esp_cam_ctlr_alloc_buffer` to allocate automatically.
You can call :cpp:func:`esp_cam_ctlr_format_conversion` to configure format conversion. The driver supports the following conversion types: To configure format conversion, call :cpp:func:`esp_cam_ctlr_format_conversion`. The driver supports the following conversion types:
* YUV to RGB conversion * YUV to RGB
* RGB to YUV conversion * RGB to YUV
* YUV to YUV conversion * YUV to YUV
Color range support: Supported color ranges:
* Full range: 0-255 for both RGB and YUV * Full range: 0-255 for both RGB and YUV
* Limited range: RGB 16-240, YUV Y:16-240, U-V:16-235 * Limited range: RGB 16-240, YUV Y:16-240, U-V:16-235
.. code:: c .. code:: c
#include "esp_err.h"
#include "esp_cam_ctlr.h"
#include "esp_cam_ctlr_types.h"
#include "esp_cam_ctlr_isp_dvp.h"
void app_main(void)
{
esp_cam_ctlr_handle_t cam_handle = NULL; esp_cam_ctlr_handle_t cam_handle = NULL;
esp_cam_ctlr_dvp_pin_config_t pin_cfg = { esp_cam_ctlr_dvp_pin_config_t pin_cfg = {
.data_width = EXAMPLE_DVP_CAM_DATA_WIDTH, .data_width = EXAMPLE_DVP_CAM_DATA_WIDTH,
.data_io = { .data_io = {
@@ -149,6 +177,7 @@ Camera controller driver can be implemented in one of following ways:
.pclk_io = EXAMPLE_DVP_CAM_PCLK_IO, .pclk_io = EXAMPLE_DVP_CAM_PCLK_IO,
.xclk_io = EXAMPLE_DVP_CAM_XCLK_IO, // Set XCLK pin to generate XCLK signal .xclk_io = EXAMPLE_DVP_CAM_XCLK_IO, // Set XCLK pin to generate XCLK signal
}; };
esp_cam_ctlr_dvp_config_t dvp_config = { esp_cam_ctlr_dvp_config_t dvp_config = {
.ctlr_id = 0, .ctlr_id = 0,
.clk_src = CAM_CLK_SRC_DEFAULT, .clk_src = CAM_CLK_SRC_DEFAULT,
@@ -162,69 +191,94 @@ Camera controller driver can be implemented in one of following ways:
}; };
ESP_ERROR_CHECK(esp_cam_new_dvp_ctlr(&dvp_config, &cam_handle)); ESP_ERROR_CHECK(esp_cam_new_dvp_ctlr(&dvp_config, &cam_handle));
}
const cam_ctlr_format_conv_config_t conv_cfg = { Uninstall the Camera Controller Driver
.src_format = CAM_CTLR_COLOR_YUV422, // Source format: YUV422 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.dst_format = CAM_CTLR_COLOR_RGB565, // Destination format: RGB565
.conv_std = COLOR_CONV_STD_RGB_YUV_BT601,
.data_width = 8,
.input_range = COLOR_RANGE_LIMIT,
.output_range = COLOR_RANGE_LIMIT,
};
ESP_ERROR_CHECK(esp_cam_ctlr_format_conversion(cam_handle, &conv_cfg));
Uninstall Camera Controller Driver To release resources for a camera controller driver that is no longer needed, call :cpp:func:`esp_cam_ctlr_del`. This releases the underlying hardware.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If a previously installed camera controller driver is no longer needed, it's recommended to recycle the resource by calling :cpp:func:`esp_cam_ctlr_del`, so that to release the underlying hardware.
.. _cam-enable-disable: .. _cam-enable-disable:
Enable and Disable Camera Controller Driver Enable and Disable the Camera Controller Driver
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Before starting camera controller operation, you need to enable the camera controller driver first, by calling :cpp:func:`esp_cam_ctlr_enable`. This function: Before operating the camera controller, enable the driver by calling :cpp:func:`esp_cam_ctlr_enable`. This switches the driver state from **init** to **enable**.
* Switches the driver state from **init** to **enable**.
.. code:: c .. code:: c
#include "esp_cam_ctlr.h"
#include "esp_cam_ctlr_types.h"
#include "esp_err.h"
void app_main(void)
{
esp_cam_ctlr_handle_t handle;
ESP_ERROR_CHECK(esp_cam_ctlr_enable(handle)); ESP_ERROR_CHECK(esp_cam_ctlr_enable(handle));
}
Calling :cpp:func:`esp_cam_ctlr_disable` does the opposite, that is, put the driver back to the **init** state. To disable the driver and return to the **init** state, call :cpp:func:`esp_cam_ctlr_disable`.
.. code:: c .. code:: c
#include "esp_err.h"
#include "esp_cam_ctlr.h"
#include "esp_cam_ctlr_types.h"
void app_main(void)
{
esp_cam_ctlr_handle_t handle;
ESP_ERROR_CHECK(esp_cam_ctlr_disable(handle)); ESP_ERROR_CHECK(esp_cam_ctlr_disable(handle));
}
.. _cam-start-stop: .. _cam-start-stop:
Start and Stop Camera Controller Driver Start and Stop the Camera Controller Driver
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Before receiving camera signal from camera sensor, you need to start the camera controller driver first, by calling :cpp:func:`esp_cam_ctlr_start`. This function: Before receiving signals from a camera sensor, start the driver by calling :cpp:func:`esp_cam_ctlr_start`. This switches the driver state from **enable** to **start**.
* Switches the driver state from **enable** to **start**.
.. code:: c .. code:: c
#include "esp_err.h"
#include "esp_log.h"
#include "esp_cam_ctlr.h"
#include "esp_cam_ctlr_types.h"
void app_main(void)
{
esp_cam_ctlr_handle_t handle = NULL;
ESP_ERROR_CHECK(esp_cam_ctlr_start(handle)); ESP_ERROR_CHECK(esp_cam_ctlr_start(handle));
ESP_LOGI("CAM", "Camera controller started successfully");
}
Calling :cpp:func:`esp_cam_ctlr_stop` does the opposite, that is, put the driver back to the **enable** state. To stop the driver and return to the **enable** state, call :cpp:func:`esp_cam_ctlr_stop`.
.. code:: c .. code:: c
#include "esp_err.h"
#include "esp_cam_ctlr.h"
#include "esp_cam_ctlr_types.h"
void app_main(void)
{
esp_cam_ctlr_handle_t handle = NULL;
ESP_ERROR_CHECK(esp_cam_ctlr_stop(handle)); ESP_ERROR_CHECK(esp_cam_ctlr_stop(handle));
}
.. _cam-receive: .. _cam-receive:
Receive from a Camera Sensor Receive Data from a Camera Sensor
^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Now you can call :cpp:func:`esp_cam_ctlr_receive` to receive from a camera sensor or something else. To receive data from a camera sensor, call :cpp:func:`esp_cam_ctlr_receive`.
.. code:: c .. code:: c
#include "esp_err.h"
#include "esp_cam_ctlr.h"
#include "esp_cam_ctlr_types.h"
ESP_ERROR_CHECK(esp_cam_ctlr_receive(handle, &my_trans, ESP_CAM_CTLR_MAX_DELAY)); ESP_ERROR_CHECK(esp_cam_ctlr_receive(handle, &my_trans, ESP_CAM_CTLR_MAX_DELAY));
.. _cam-callback: .. _cam-callback:
@@ -232,18 +286,18 @@ Now you can call :cpp:func:`esp_cam_ctlr_receive` to receive from a camera senso
Register Event Callbacks Register Event Callbacks
^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^
After the camera controller driver starts receiving, it can generate a specific event dynamically. If you have some functions that should be called when the event happens, please hook your function to the interrupt service routine by calling :cpp:func:`esp_cam_ctlr_register_event_callbacks`. All supported event callbacks are listed in :cpp:type:`esp_cam_ctlr_evt_cbs_t`: After the camera controller driver starts receiving data, it can generate events dynamically. To execute user-defined functions when events occur, register your callback function using :cpp:func:`esp_cam_ctlr_register_event_callbacks`. Supported event callbacks are listed in :cpp:type:`esp_cam_ctlr_evt_cbs_t`:
- :cpp:member:`esp_cam_ctlr_evt_cbs_t::on_get_new_trans` sets a callback function which will be called after the camera controller driver finishes previous transaction, and tries to get a new transaction descriptor. It will also be called when in :cpp:func:`s_ctlr_csi_start`. If this callback does not get a new transaction descriptor, the camera controller driver will use the internal backup buffer if ``bk_buffer_dis`` flag is set. - :cpp:member:`esp_cam_ctlr_evt_cbs_t::on_get_new_trans` Called after the driver finishes a transaction and attempts to get a new transaction descriptor. Also called in :cpp:func:`s_ctlr_csi_start`. If this callback does not provide a new transaction descriptor, the driver uses the internal backup buffer if the ``bk_buffer_dis`` flag is set.
- :cpp:member:`esp_cam_ctlr_evt_cbs_t::on_trans_finished` sets a callback function when the camera controller driver finishes a transaction. As this function is called within the ISR context, you must ensure that the function does not attempt to block (e.g., by making sure that only FreeRTOS APIs with ``ISR`` suffix are called from within the function). - :cpp:member:`esp_cam_ctlr_evt_cbs_t::on_trans_finished` Called when the driver finishes a transaction. This function runs in the ISR context. Ensure that it does not block (for example, only use FreeRTOS APIs with the ``ISR`` suffix).
.. _cam-thread-safety: .. _cam-thread-safety:
Thread Safety Thread Safety
^^^^^^^^^^^^^ ^^^^^^^^^^^^^
The factory functions: The following factory functions are thread-safe and can be called from different RTOS tasks without additional locking:
.. list:: .. list::
@@ -251,47 +305,43 @@ The factory functions:
:SOC_ISP_DVP_SUPPORTED: - :cpp:func:`esp_cam_new_isp_dvp_ctlr` :SOC_ISP_DVP_SUPPORTED: - :cpp:func:`esp_cam_new_isp_dvp_ctlr`
- :cpp:func:`esp_cam_ctlr_del` - :cpp:func:`esp_cam_ctlr_del`
are guaranteed to be thread safe by the driver, which means, they can be called from different RTOS tasks without protection by extra locks.
.. _cam-kconfig-options: .. _cam-kconfig-options:
Kconfig Options Kconfig Options
^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
The following Kconfig options affect the behavior of the interrupt handler when cache is disabled: The following Kconfig options affect interrupt handler behavior when the cache is disabled:
.. list:: .. list::
:SOC_MIPI_CSI_SUPPORTED: - :ref:`CONFIG_CAM_CTLR_MIPI_CSI_ISR_CACHE_SAFE`, see :ref:`cam-thread-safety` for more details. :SOC_MIPI_CSI_SUPPORTED: - :ref:`CONFIG_CAM_CTLR_MIPI_CSI_ISR_CACHE_SAFE`, see :ref:`cam-thread-safety` for details.
:SOC_ISP_DVP_SUPPORTED: - :ref:`CONFIG_CAM_CTLR_ISP_DVP_ISR_CACHE_SAFE`, see :ref:`cam-thread-safety` for more details. :SOC_ISP_DVP_SUPPORTED: - :ref:`CONFIG_CAM_CTLR_ISP_DVP_ISR_CACHE_SAFE`, see :ref:`cam-thread-safety` for details.
.. _cam-iram-safe: .. _cam-iram-safe:
IRAM Safe IRAM Safety
^^^^^^^^^ ^^^^^^^^^^^^^^
By default, the CSI interrupt will be deferred when the cache is disabled because of writing or erasing the flash. By default, CSI interrupts are delayed when the cache is disabled during flash write or erase operations. They are handled after the cache is enabled again.
There are Kconfig options The following Kconfig options:
.. list:: .. list::
:SOC_MIPI_CSI_SUPPORTED: - :ref:`CONFIG_CAM_CTLR_MIPI_CSI_ISR_CACHE_SAFE` :SOC_MIPI_CSI_SUPPORTED: - :ref:`CONFIG_CAM_CTLR_MIPI_CSI_ISR_CACHE_SAFE`
:SOC_ISP_DVP_SUPPORTED: - :ref:`CONFIG_CAM_CTLR_ISP_DVP_ISR_CACHE_SAFE` :SOC_ISP_DVP_SUPPORTED: - :ref:`CONFIG_CAM_CTLR_ISP_DVP_ISR_CACHE_SAFE`
that - Enable the interrupt being serviced even when the cache is disabled.
- Place all functions used by the ISR into IRAM.
- Place driver object into DRAM (to avoid mapping to PSRAM).
- Enables the interrupt being serviced even when the cache is disabled This allows interrupts to run while the cache is disabled, but increases IRAM usage. Ensure that user callbacks and related code/data are IRAM-safe or DRAM-safe when the cache is disabled.
- Places all functions that used by the ISR into IRAM
- Places driver object into DRAM (in case it is mapped to PSRAM by accident)
This allows the interrupt to run while the cache is disabled, but comes at the cost of increased IRAM consumption. So user callbacks need to notice that the code and data inside (the callback) should be IRAM-safe or DRAM-safe, when cache is disabled.
Application Examples Application Examples
-------------------- --------------------
* :example:`peripherals/camera/mipi_isp_dsi` demonstrates how to use the ``esp_driver_cam`` component to capture signals from a MIPI CSI camera sensor via the ISP module and display it on a LCD screen via a DSI interface. * :example:`peripherals/camera/mipi_isp_dsi` Demonstrates how to use the ``esp_driver_cam`` component to capture signals from a MIPI CSI camera sensor via the ISP module and display them on an LCD screen via a DSI interface.
* :example:`peripherals/camera/dvp_isp_dsi` demonstrates how to use the ``esp_driver_cam`` component to capture signals from a DVP camera sensor via the ISP module and display it on a LCD screen via a DSI interface. * :example:`peripherals/camera/dvp_isp_dsi` Demonstrates how to use the ``esp_driver_cam`` component to capture signals from a DVP camera sensor via the ISP module and display them on an LCD screen via a DSI interface.
API Reference API Reference
------------- -------------

View File

@@ -10,13 +10,12 @@
.. list:: .. list::
: SOC_MIPI_CSI_SUPPORTED : - MIPI 摄像头串行接口 (MIPI CSI) :SOC_MIPI_CSI_SUPPORTED: - MIPI 摄像头串行接口 (MIPI CSI)
: SOC_ISP_DVP_SUPPORTED : - ISP的DVP端口 (ISP DVP) :SOC_ISP_DVP_SUPPORTED: - ISP的DVP端口 (ISP DVP)
: SOC_LCDCAM_CAM_SUPPORTED : - LCD_CAM的DVP端口 (LCD_CAM DVP) :SOC_LCDCAM_CAM_SUPPORTED: - LCD_CAM的DVP端口 (LCD_CAM DVP)
摄像头控制器驱动程序是为上述硬件外设而设计的。 摄像头控制器驱动程序是为上述硬件外设而设计的。
功能概述 功能概述
------------ ------------
@@ -43,9 +42,9 @@
.. list:: .. list::
: SOC_MIPI_CSI_SUPPORTED : - :cpp:func:`esp_cam_new_csi_ctlr` :SOC_MIPI_CSI_SUPPORTED: - :cpp:func:`esp_cam_new_csi_ctlr`
: SOC_ISP_DVP_SUPPORTED : - :cpp:func:`esp_cam_new_isp_dvp_ctlr` :SOC_ISP_DVP_SUPPORTED: - :cpp:func:`esp_cam_new_isp_dvp_ctlr`
: SOC_LCDCAM_CAM_SUPPORTED : - :cpp:func:`esp_cam_new_lcd_cam_ctlr` :SOC_LCDCAM_CAM_SUPPORTED: - :cpp:func:`esp_cam_new_lcd_cam_ctlr`
.. only:: SOC_MIPI_CSI_SUPPORTED .. only:: SOC_MIPI_CSI_SUPPORTED
@@ -55,6 +54,12 @@
.. code:: c .. code:: c
#include "esp_cam_ctlr.h"
#include "esp_cam_ctlr_types.h"
#include "esp_cam_ctlr_csi.h"
void app_main(void)
{
esp_cam_ctlr_csi_config_t csi_config = { esp_cam_ctlr_csi_config_t csi_config = {
.ctlr_id = 0, .ctlr_id = 0,
.h_res = MIPI_CSI_DISP_HSIZE, .h_res = MIPI_CSI_DISP_HSIZE,
@@ -66,10 +71,12 @@
.byte_swap_en = false, .byte_swap_en = false,
.queue_items = 1, .queue_items = 1,
}; };
esp_cam_ctlr_handle_t handle = NULL; esp_cam_ctlr_handle_t handle = NULL;
ESP_ERROR_CHECK(esp_cam_new_csi_ctlr(&csi_config, &handle)); ESP_ERROR_CHECK(esp_cam_new_csi_ctlr(&csi_config, &handle));
}
{IDF_TARGET_NAME} 中的 CSI 控制器需要稳定的 2.5V 电源供电,请查阅原理图,确保在使用 MIPI CSI 驱动之前,已将其供电管脚连接至 2.5V 电源。 {IDF_TARGET_NAME} 中的 CSI 控制器需要稳定的 2.5 V 电源供电,请查阅原理图,确保在使用 MIPI CSI 驱动之前,已将其供电管脚连接至 2.5 V 电源。
.. only:: SOC_GP_LDO_SUPPORTED .. only:: SOC_GP_LDO_SUPPORTED
@@ -85,6 +92,16 @@
.. code:: c .. code:: c
#include "esp_err.h"
#include "esp_cam_ctlr.h"
#include "esp_cam_ctlr_isp_dvp.h"
#include "driver/isp.h"
#define MIPI_CSI_DISP_HSIZE 800 // example value, replace with actual resolution
#define MIPI_CSI_DISP_VSIZE 600 // example value, replace with actual resolution
void app_main(void)
{
isp_proc_handle_t isp_proc = NULL; isp_proc_handle_t isp_proc = NULL;
esp_isp_processor_cfg_t isp_config = { esp_isp_processor_cfg_t isp_config = {
.clk_hz = 120 * 1000 * 1000, .clk_hz = 120 * 1000 * 1000,
@@ -98,6 +115,7 @@
}; };
ESP_ERROR_CHECK(esp_isp_new_processor(&isp_config, &isp_proc)); ESP_ERROR_CHECK(esp_isp_new_processor(&isp_config, &isp_proc));
esp_cam_ctlr_handle_t cam_handle = NULL;
esp_cam_ctlr_isp_dvp_cfg_t dvp_ctlr_config = { esp_cam_ctlr_isp_dvp_cfg_t dvp_ctlr_config = {
.data_width = 8, .data_width = 8,
.data_io = {53, 54, 52, 0, 1, 45, 46, 47, -1, -1, -1, -1, -1, -1, -1, -1}, .data_io = {53, 54, 52, 0, 1, 45, 46, 47, -1, -1, -1, -1, -1, -1, -1, -1},
@@ -109,6 +127,7 @@
.queue_items = 10, .queue_items = 10,
}; };
ESP_ERROR_CHECK(esp_cam_new_isp_dvp_ctlr(isp_proc, &dvp_ctlr_config, &cam_handle)); ESP_ERROR_CHECK(esp_cam_new_isp_dvp_ctlr(isp_proc, &dvp_ctlr_config, &cam_handle));
}
.. only:: SOC_LCDCAM_CAM_SUPPORTED .. only:: SOC_LCDCAM_CAM_SUPPORTED
@@ -132,7 +151,15 @@
.. code:: c .. code:: c
#include "esp_err.h"
#include "esp_cam_ctlr.h"
#include "esp_cam_ctlr_types.h"
#include "esp_cam_ctlr_isp_dvp.h"
void app_main(void)
{
esp_cam_ctlr_handle_t cam_handle = NULL; esp_cam_ctlr_handle_t cam_handle = NULL;
esp_cam_ctlr_dvp_pin_config_t pin_cfg = { esp_cam_ctlr_dvp_pin_config_t pin_cfg = {
.data_width = EXAMPLE_DVP_CAM_DATA_WIDTH, .data_width = EXAMPLE_DVP_CAM_DATA_WIDTH,
.data_io = { .data_io = {
@@ -150,6 +177,7 @@
.pclk_io = EXAMPLE_DVP_CAM_PCLK_IO, .pclk_io = EXAMPLE_DVP_CAM_PCLK_IO,
.xclk_io = EXAMPLE_DVP_CAM_XCLK_IO, // Set XCLK pin to generate XCLK signal .xclk_io = EXAMPLE_DVP_CAM_XCLK_IO, // Set XCLK pin to generate XCLK signal
}; };
esp_cam_ctlr_dvp_config_t dvp_config = { esp_cam_ctlr_dvp_config_t dvp_config = {
.ctlr_id = 0, .ctlr_id = 0,
.clk_src = CAM_CLK_SRC_DEFAULT, .clk_src = CAM_CLK_SRC_DEFAULT,
@@ -163,16 +191,7 @@
}; };
ESP_ERROR_CHECK(esp_cam_new_dvp_ctlr(&dvp_config, &cam_handle)); ESP_ERROR_CHECK(esp_cam_new_dvp_ctlr(&dvp_config, &cam_handle));
}
const cam_ctlr_format_conv_config_t conv_cfg = {
.src_format = CAM_CTLR_COLOR_YUV422, // 源格式YUV422
.dst_format = CAM_CTLR_COLOR_RGB565, // 目标格式RGB565
.conv_std = COLOR_CONV_STD_RGB_YUV_BT601,
.data_width = 8,
.input_range = COLOR_RANGE_LIMIT,
.output_range = COLOR_RANGE_LIMIT,
};
ESP_ERROR_CHECK(esp_cam_ctlr_format_conversion(cam_handle, &conv_cfg));
卸载摄像头控制器驱动程序 卸载摄像头控制器驱动程序
~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~
@@ -184,38 +203,68 @@
启用和禁用摄像头控制器驱动程序 启用和禁用摄像头控制器驱动程序
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
在开始摄像头控制器操作之前,首先要调用 :cpp:func:`esp_cam_ctlr_enable` 以启用摄像头控制器驱动程序。此函数 在开始摄像头控制器操作之前,首先要调用 :cpp:func:`esp_cam_ctlr_enable` 以启用摄像头控制器驱动程序。此函数将驱动程序状态从 **init** 切换到 **enable**
* 将驱动程序状态从 **init** 切换到 **enable**
.. code:: c .. code:: c
#include "esp_cam_ctlr.h"
#include "esp_cam_ctlr_types.h"
#include "esp_err.h"
void app_main(void)
{
esp_cam_ctlr_handle_t handle;
ESP_ERROR_CHECK(esp_cam_ctlr_enable(handle)); ESP_ERROR_CHECK(esp_cam_ctlr_enable(handle));
}
调用 :cpp:func:`esp_cam_ctlr_disable` 则会执行与上述过程相反的操作,即将驱动程序切回到 **init** 状态。 调用 :cpp:func:`esp_cam_ctlr_disable` 则会执行与上述过程相反的操作,即将驱动程序切回到 **init** 状态。
.. code:: c .. code:: c
#include "esp_err.h"
#include "esp_cam_ctlr.h"
#include "esp_cam_ctlr_types.h"
void app_main(void)
{
esp_cam_ctlr_handle_t handle;
ESP_ERROR_CHECK(esp_cam_ctlr_disable(handle)); ESP_ERROR_CHECK(esp_cam_ctlr_disable(handle));
}
.. _cam-start-stop: .. _cam-start-stop:
启动和停止摄像头控制器驱动程序 启动和停止摄像头控制器驱动程序
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
从摄像头传感器接收信号之前,首先要调用 :cpp:func:`esp_cam_ctlr_start` 以启动摄像头控制器驱动程序。此函数 从摄像头传感器接收信号之前,首先要调用 :cpp:func:`esp_cam_ctlr_start` 以启动摄像头控制器驱动程序。此函数将驱动程序状态从 **enable** 切换到 **start**
* 将驱动程序状态从 **enable** 切换到 **start**
.. code:: c .. code:: c
#include "esp_err.h"
#include "esp_log.h"
#include "esp_cam_ctlr.h"
#include "esp_cam_ctlr_types.h"
void app_main(void)
{
esp_cam_ctlr_handle_t handle = NULL;
ESP_ERROR_CHECK(esp_cam_ctlr_start(handle)); ESP_ERROR_CHECK(esp_cam_ctlr_start(handle));
ESP_LOGI("CAM", "Camera controller started successfully");
}
调用 :cpp:func:`esp_cam_ctlr_stop` 则会执行与上述过程相反的操作,即将驱动程序切回到 **enable** 状态。 调用 :cpp:func:`esp_cam_ctlr_stop` 则会执行与上述过程相反的操作,即将驱动程序切回到 **enable** 状态。
.. code:: c .. code:: c
#include "esp_err.h"
#include "esp_cam_ctlr.h"
#include "esp_cam_ctlr_types.h"
void app_main(void)
{
esp_cam_ctlr_handle_t handle = NULL;
ESP_ERROR_CHECK(esp_cam_ctlr_stop(handle)); ESP_ERROR_CHECK(esp_cam_ctlr_stop(handle));
}
.. _cam-receive: .. _cam-receive:
@@ -226,6 +275,10 @@
.. code:: c .. code:: c
#include "esp_err.h"
#include "esp_cam_ctlr.h"
#include "esp_cam_ctlr_types.h"
ESP_ERROR_CHECK(esp_cam_ctlr_receive(handle, &my_trans, ESP_CAM_CTLR_MAX_DELAY)); ESP_ERROR_CHECK(esp_cam_ctlr_receive(handle, &my_trans, ESP_CAM_CTLR_MAX_DELAY));
.. _cam-callback: .. _cam-callback:
@@ -244,7 +297,7 @@
线程安全 线程安全
^^^^^^^^ ^^^^^^^^
以下工厂函数 以下工厂函数由驱动程序保证线程安全。使用时,可以直接从不同的 RTOS 任务中调用此类函数,无需额外锁保护。
.. list:: .. list::
@@ -252,8 +305,6 @@
:SOC_ISP_DVP_SUPPORTED: - :cpp:func:`esp_cam_new_isp_dvp_ctlr` :SOC_ISP_DVP_SUPPORTED: - :cpp:func:`esp_cam_new_isp_dvp_ctlr`
- :cpp:func:`esp_cam_ctlr_del` - :cpp:func:`esp_cam_ctlr_del`
由驱动程序保证线程安全。使用时,可以直接从不同的 RTOS 任务中调用此类函数,无需额外锁保护。
.. _cam-kconfig-options: .. _cam-kconfig-options:
Kconfig 选项 Kconfig 选项
@@ -271,17 +322,15 @@ Kconfig 选项
IRAM 安全 IRAM 安全
^^^^^^^^^ ^^^^^^^^^
默认情况下,当 cache 因写入或擦除 flash 等原因而被禁用时CSI 中断将被推迟。 默认情况下,当 cache 因写入或擦除 flash 等原因而被禁用时CSI 中断将被推迟。这些中断会在 cache 重新启用后再被处理。
以下 Kconfig 选项: 以下 Kconfig 选项支持
.. list:: .. list::
:SOC_MIPI_CSI_SUPPORTED: - :ref:`CONFIG_CAM_CTLR_MIPI_CSI_ISR_CACHE_SAFE` :SOC_MIPI_CSI_SUPPORTED: - :ref:`CONFIG_CAM_CTLR_MIPI_CSI_ISR_CACHE_SAFE`
:SOC_ISP_DVP_SUPPORTED: - :ref:`CONFIG_CAM_CTLR_ISP_DVP_ISR_CACHE_SAFE` :SOC_ISP_DVP_SUPPORTED: - :ref:`CONFIG_CAM_CTLR_ISP_DVP_ISR_CACHE_SAFE`
这些选项支持
- 即使 cache 被禁用也能启用中断服务 - 即使 cache 被禁用也能启用中断服务
- 将 ISR 使用的所有函数放入 IRAM - 将 ISR 使用的所有函数放入 IRAM
- 将驱动程序对象放入 DRAM以防意外映射到 PSRAM - 将驱动程序对象放入 DRAM以防意外映射到 PSRAM