摄像头控制器驱动程序
简介
ESP32-P4 具有以下硬件,用于与外部摄像头传感器通信:
MIPI 摄像头串行接口 (CSI)
ISP 数字视频端口 (ISP DVP)
摄像头控制器驱动程序是为上述硬件外设而设计的。
功能概述
资源分配 - 涵盖如何通过恰当的配置来分配摄像头控制器实例,以及如何回收资源。
启用和禁用摄像头控制器驱动程序 - 涵盖如何启用和禁用摄像头控制器。
启动和停止摄像头控制器驱动程序 - 涵盖如何启动和停止摄像头控制器。
从摄像头传感器处接收信号 - 涵盖如何从传感器或其他设备接收摄像头信号。
注册事件回调函数 - 涵盖如何将用户特定代码挂接到摄像头控制器驱动程序事件回调函数。
线程安全 - 列出了驱动程序中线程安全的 API。
Kconfig 选项 - 列出了支持的 Kconfig 选项,这些选项可以对驱动程序产生不同的影响。
IRAM 安全 - 描述了当 cache 被禁用时,如何使 CSI 中断和控制功能更好地工作。
资源分配
安装摄像头控制器驱动程序
摄像头控制器驱动程序可以通过 CSI 外设实现,需要应用 esp_cam_ctlr_csi_config_t
指定的配置。
如果指定了 esp_cam_ctlr_csi_config_t
中的配置,就可以调用 esp_cam_new_csi_ctlr()
来分配和初始化 CSI 摄像头控制器句柄。如果函数运行正确,将返回一个 CSI 摄像头控制器句柄。请参考以下代码。
esp_cam_ctlr_csi_config_t csi_config = {
.ctlr_id = 0,
.h_res = MIPI_CSI_DISP_HSIZE,
.v_res = MIPI_CSI_DISP_VSIZE_640P,
.lane_bit_rate_mbps = MIPI_CSI_LANE_BITRATE_MBPS,
.input_data_color_type = CAM_CTLR_COLOR_RAW8,
.output_data_color_type = CAM_CTLR_COLOR_RGB565,
.data_lane_num = 2,
.byte_swap_en = false,
.queue_items = 1,
};
esp_cam_ctlr_handle_t handle = NULL;
ESP_ERROR_CHECK(esp_cam_new_csi_ctlr(&csi_config, &handle));
摄像头控制器驱动程序可以通过 ISP 外设实现,需要应用 esp_cam_ctlr_isp_dvp_cfg_t
指定的配置。
如果指定了 esp_cam_ctlr_isp_dvp_cfg_t
中的配置,就可以调用 esp_cam_new_isp_dvp_ctlr()
来分配和初始化 ISP DVP 摄像头控制器句柄。如果函数运行正确,将返回一个 ISP DVP 摄像头控制器句柄。请参考以下代码。
在调用 esp_cam_new_isp_dvp_ctlr()
之前,还应调用 esp_isp_new_processor()
来创建 ISP 句柄。
isp_proc_handle_t isp_proc = NULL;
esp_isp_processor_cfg_t isp_config = {
.clk_hz = 120 * 1000 * 1000,
.input_data_source = ISP_INPUT_DATA_SOURCE_DVP,
.input_data_color_type = ISP_COLOR_RAW8,
.output_data_color_type = ISP_COLOR_RGB565,
.has_line_start_packet = false,
.has_line_end_packet = false,
.h_res = MIPI_CSI_DISP_HSIZE,
.v_res = MIPI_CSI_DISP_VSIZE,
};
ESP_ERROR_CHECK(esp_isp_new_processor(&isp_config, &isp_proc));
esp_cam_ctlr_isp_dvp_cfg_t dvp_ctlr_config = {
.data_width = 8,
.data_io = {53, 54, 52, 0, 1, 45, 46, 47, -1, -1, -1, -1, -1, -1, -1, -1},
.pclk_io = 21,
.hsync_io = 5,
.vsync_io = 23,
.de_io = 22,
.io_flags.vsync_invert = 1,
.queue_items = 10,
};
ESP_ERROR_CHECK(esp_cam_new_isp_dvp_ctlr(isp_proc, &dvp_ctlr_config, &cam_handle));
卸载摄像头控制器驱动程序
如果不再需要先前安装的摄像头控制器驱动程序,建议通过调用 esp_cam_ctlr_del()
来回收资源,从而释放底层硬件。
启用和禁用摄像头控制器驱动程序
在开始摄像头控制器操作之前,首先要调用 esp_cam_ctlr_enable()
以启用摄像头控制器驱动程序。此函数:
将驱动程序状态从 init 切换到 enable。
ESP_ERROR_CHECK(esp_cam_ctlr_enable(handle));
调用 esp_cam_ctlr_disable()
则会执行与上述过程相反的操作,即将驱动程序切回到 init 状态。
ESP_ERROR_CHECK(esp_cam_ctlr_disable(handle));
启动和停止摄像头控制器驱动程序
从摄像头传感器接收信号之前,首先要调用 esp_cam_ctlr_start()
以启动摄像头控制器驱动程序。此函数:
将驱动程序状态从 enable 切换到 start。
ESP_ERROR_CHECK(esp_cam_ctlr_start(handle));
调用 esp_cam_ctlr_stop()
则会执行与上述过程相反的操作,即将驱动程序切回到 enable 状态。
ESP_ERROR_CHECK(esp_cam_ctlr_stop(handle));
从摄像头传感器处接收信号
调用 esp_cam_ctlr_receive()
,可以接收来自摄像头传感器或其他设备的信号。
ESP_ERROR_CHECK(esp_cam_ctlr_receive(handle, &my_trans, ESP_CAM_CTLR_MAX_DELAY));
注册事件回调函数
摄像头控制器驱动程序开始接收信号时,会动态生成特定事件。如果在事件发生时需要调用一些函数,请通过调用 esp_cam_ctlr_register_event_callbacks()
将这些函数挂接到中断服务程序。所有支持的事件回调函数参见 esp_cam_ctlr_evt_cbs_t
:
esp_cam_ctlr_evt_cbs_t::on_get_new_trans
可设置回调函数,当摄像头控制器驱动程序完成传输并尝试获取新的事务描述符时,该回调函数会被调用。在s_ctlr_csi_start()
中也会调用此回调函数。如果此回调函数未能获取新的事务描述符,但设置了bk_buffer_dis
标志,则摄像头控制器驱动程序将使用内部备份 buffer。esp_cam_ctlr_evt_cbs_t::on_trans_finished
可设置回调函数,当摄像头控制器驱动程序完成传输时,该回调函数会被调用。此函数在 ISR 上下文中被调用,因此必须确保该函数不会尝试阻塞(例如,确保只从该函数中调用带有ISR
后缀的 FreeRTOS API)。
线程安全
以下工厂函数:
由驱动程序保证线程安全。使用时,可以直接从不同的 RTOS 任务中调用此类函数,无需额外锁保护。
Kconfig 选项
当 cache 被禁用时,以下 Kconfig 选项会影响中断处理程序的行为:
IRAM 安全
默认情况下,当 cache 因写入或擦除 flash 等原因而被禁用时,CSI 中断将被推迟。
有以下 Kconfig 选项:
这些选项支持
即使 cache 被禁用也能启用中断服务
将 ISR 使用的所有函数放入 IRAM
将驱动程序对象放入 DRAM(以防意外映射到 PSRAM)
启用上述 Kconfig 选项,保证 cache 被禁用时中断可以正常运行,但这会增加 IRAM 使用量。因此,当 cache 被禁用时,用户回调函数需要注意(回调函数的)代码和数据应该是 IRAM 安全或 DRAM 安全的。
应用示例
peripherals/camera/mipi_isp_dsi 演示了如何使用
esp_driver_cam
组件从 MIPI CSI 摄像头传感器捕获信号,传入 ISP 模块,并通过 DSI 接口将其显示在 LCD 屏幕上。peripherals/camera/dvp_isp_dsi 演示了如何使用
esp_driver_cam
组件从 DVP 摄像头传感器捕获信号,传入 ISP 模块,并通过 DSI 接口将其显示在 LCD 屏幕上。
API 参考
Header File
This header file can be included with:
#include "esp_cam_ctlr.h"
This header file is a part of the API provided by the
esp_driver_cam
component. To declare that your component depends onesp_driver_cam
, add the following to your CMakeLists.txt:REQUIRES esp_driver_cam
or
PRIV_REQUIRES esp_driver_cam
Functions
-
esp_err_t esp_cam_ctlr_enable(esp_cam_ctlr_handle_t handle)
Enable ESP CAM controller.
- 参数
handle -- [in] ESP CAM controller handle
- 返回
ESP_OK
ESP_ERR_INVALID_ARG: Invalid argument
ESP_ERR_INVALID_STATE: Invalid state
-
esp_err_t esp_cam_ctlr_start(esp_cam_ctlr_handle_t handle)
Start ESP CAM controller.
- 参数
handle -- [in] ESP CAM controller handle
- 返回
ESP_OK
ESP_ERR_INVALID_ARG: Invalid argument
ESP_ERR_INVALID_STATE: Invalid state
-
esp_err_t esp_cam_ctlr_stop(esp_cam_ctlr_handle_t handle)
Stop ESP CAM controller.
- 参数
handle -- [in] ESP CAM controller handle
- 返回
ESP_OK
ESP_ERR_INVALID_ARG: Invalid argument
ESP_ERR_INVALID_STATE: Invalid state
-
esp_err_t esp_cam_ctlr_disable(esp_cam_ctlr_handle_t handle)
Disable ESP CAM controller.
- 参数
handle -- [in] ESP CAM controller handle
- 返回
ESP_OK
ESP_ERR_INVALID_ARG: Invalid argument
ESP_ERR_INVALID_STATE: Invalid state
-
esp_err_t esp_cam_ctlr_receive(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, uint32_t timeout_ms)
Receive data to the given transaction.
- 参数
handle -- [in] ESP CAM controller handle
trans -- [in] ESP CAM controller transaction type
timeout_ms -- [in] Timeout in ms
- 返回
ESP_OK
ESP_ERR_INVALID_ARG: Invalid argument
ESP_ERR_INVALID_STATE: Invalid state
-
esp_err_t esp_cam_ctlr_del(esp_cam_ctlr_handle_t handle)
Delete ESP CAM controller handle.
- 参数
handle -- [in] ESP CAM controller handle
- 返回
ESP_OK
ESP_ERR_INVALID_ARG: Invalid argument
ESP_ERR_INVALID_STATE: Invalid state
-
esp_err_t esp_cam_ctlr_register_event_callbacks(esp_cam_ctlr_handle_t handle, const esp_cam_ctlr_evt_cbs_t *cbs, void *user_data)
Register ESP CAM controller event callbacks.
- 参数
handle -- [in] ESP CAM controller handle
cbs -- [in] ESP CAM controller event callbacks
user_data -- [in] User data
- 返回
ESP_OK
ESP_ERR_INVALID_ARG: Invalid argument
ESP_ERR_INVALID_STATE: Invalid state
-
esp_err_t esp_cam_ctlr_get_frame_buffer(esp_cam_ctlr_handle_t handle, uint32_t fb_num, const void **fb0, ...)
Get ESP CAM controller internal malloced backup buffer(s) addr.
备注
Generally, data in internal buffer is ready when
on_trans_finished
event- 参数
handle -- [in] ESP CAM controller handle
fb_num -- [in] Number of frame buffer(s) to get. This value must be the same as the number of the followed fbN parameters
fb0 -- [out] Address of the frame buffer 0 (first frame buffer)
... -- [out] List of other frame buffers if any
- 返回
ESP_OK
ESP_ERR_INVALID_ARG: Invalid argument
ESP_ERR_INVALID_STATE: Invalid driver state
-
esp_err_t esp_cam_ctlr_get_frame_buffer_len(esp_cam_ctlr_handle_t handle, size_t *ret_fb_len)
Get ESP CAM controller internal backup buffer length.
- 参数
handle -- [in] ESP CAM controller handle
ret_fb_len -- [out] Optional, The size of each frame buffer, in bytes.
- 返回
ESP_OK
ESP_ERR_INVALID_ARG: NULL ptr
ESP_ERR_INVALID_STATE: Invalid driver state
Header File
This header file can be included with:
#include "esp_cam_ctlr_types.h"
This header file is a part of the API provided by the
esp_driver_cam
component. To declare that your component depends onesp_driver_cam
, add the following to your CMakeLists.txt:REQUIRES esp_driver_cam
or
PRIV_REQUIRES esp_driver_cam
Structures
-
struct esp_cam_ctlr_trans_t
ESP CAM controller transaction type.
-
struct esp_cam_ctlr_evt_cbs_t
ESP CAM controller event callbacks.
Public Members
-
bool (*on_get_new_trans)(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, void *user_data)
On get new transaction callback.
- Param handle
[in] ESP CAM controller handle
- Param trans
[in] New transaction
- Param user_data
[in] User registered data
- Return
Whether a high priority task is woken up by this function
-
bool (*on_trans_finished)(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, void *user_data)
On transaction finish callback.
- Param handle
[in] ESP CAM controller handle
- Param trans
[out] Finished transaction
- Param user_data
[in] User registered data
- Return
Whether a high priority task is woken up by this function
-
bool (*on_get_new_trans)(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, void *user_data)
Macros
-
ESP_CAM_CTLR_MAX_DELAY
ESP CAM controller max timeout value.
Type Definitions
-
typedef struct esp_cam_ctlr_t *esp_cam_ctlr_handle_t
ESP CAM controller handle.
Header File
This header file can be included with:
#include "esp_cam_ctlr_csi.h"
This header file is a part of the API provided by the
esp_driver_cam
component. To declare that your component depends onesp_driver_cam
, add the following to your CMakeLists.txt:REQUIRES esp_driver_cam
or
PRIV_REQUIRES esp_driver_cam
Functions
-
esp_err_t esp_cam_new_csi_ctlr(const esp_cam_ctlr_csi_config_t *config, esp_cam_ctlr_handle_t *ret_handle)
New ESP CAM CSI controller.
- 参数
config -- [in] CSI controller configurations
ret_handle -- [out] Returned ESP CAM controller handle
- 返回
ESP_OK
ESP_ERR_INVALID_ARG: Invalid argument
ESP_ERR_NO_MEM: Out of memory
ESP_ERR_NOT_SUPPORTED: Currently not support modes or types
ESP_ERR_NOT_FOUND: CSI is registered already
Structures
-
struct esp_cam_ctlr_csi_config_t
ESP CAM CSI controller configurations.
Public Members
-
int ctlr_id
CSI controller ID.
-
mipi_csi_phy_clock_source_t clk_src
CSI phy clock source.
-
uint32_t h_res
Input horizontal resolution, i.e. the number of pixels in a line.
-
uint32_t v_res
Input vertical resolution, i.e. the number of lines in a frame.
-
uint8_t data_lane_num
Data lane num.
-
int lane_bit_rate_mbps
Lane bit rate in Mbps.
-
cam_ctlr_color_t input_data_color_type
Input color type.
-
cam_ctlr_color_t output_data_color_type
Output color type.
-
int queue_items
Queue items.
-
uint32_t byte_swap_en
Enable byte swap.
-
uint32_t bk_buffer_dis
Disable backup buffer.
-
struct esp_cam_ctlr_csi_config_t::[anonymous] [anonymous]
Boolean Flags.
-
int ctlr_id
Header File
components/esp_driver_cam/isp_dvp/include/esp_cam_ctlr_isp_dvp.h
This header file can be included with:
#include "esp_cam_ctlr_isp_dvp.h"
This header file is a part of the API provided by the
esp_driver_cam
component. To declare that your component depends onesp_driver_cam
, add the following to your CMakeLists.txt:REQUIRES esp_driver_cam
or
PRIV_REQUIRES esp_driver_cam
Functions
-
esp_err_t esp_cam_new_isp_dvp_ctlr(isp_proc_handle_t isp_proc, const esp_cam_ctlr_isp_dvp_cfg_t *ctlr_config, esp_cam_ctlr_handle_t *ret_handle)
New ESP CAM ISP DVP controller.
- 参数
isp_proc -- [in] Processor handle
ctlr_config -- [in] ISP DVP controller configurations
ret_handle -- [out] Returned ESP CAM controller handle
- 返回
ESP_OK
ESP_ERR_INVALID_ARG: Invalid argument
ESP_ERR_NO_MEM: Out of memory
ESP_ERR_NOT_SUPPORTED: Currently not support modes or types
ESP_ERR_NOT_FOUND: ISP DVP is registered already
Structures
-
struct esp_cam_ctlr_isp_dvp_cfg_t
ESP CAM ISP DVP controller configurations.
Public Members
-
cam_ctlr_data_width_t data_width
Number of data lines.
-
int data_io[ISP_DVP_DATA_SIG_NUM]
ISP DVP data-in IO numbers.
-
int pclk_io
ISP DVP pclk IO numbers.
-
int hsync_io
ISP DVP hsync IO numbers.
-
int vsync_io
ISP DVP vsync IO numbers.
-
int de_io
ISP DVP de IO numbers.
-
uint32_t pclk_invert
The pclk is inverted.
-
uint32_t hsync_invert
The hsync signal is inverted.
-
uint32_t vsync_invert
The vsync signal is inverted.
-
uint32_t de_invert
The de signal is inverted.
-
struct esp_cam_ctlr_isp_dvp_cfg_t::[anonymous] io_flags
ISP DVP IO flags.
-
int queue_items
Queue items.
-
uint32_t byte_swap_en
Enable byte swap.
-
uint32_t bk_buffer_dis
Disable backup buffer.
-
cam_ctlr_data_width_t data_width