摄像头控制器驱动程序
简介
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_camcomponent. To declare that your component depends on- esp_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_finishedevent- 参数:
- 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_camcomponent. To declare that your component depends on- esp_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_camcomponent. To declare that your component depends on- esp_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_camcomponent. To declare that your component depends on- esp_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
Header File
- This header file can be included with: - #include "driver/isp_core.h" 
- This header file is a part of the API provided by the - esp_driver_ispcomponent. To declare that your component depends on- esp_driver_isp, add the following to your CMakeLists.txt:- REQUIRES esp_driver_isp - or - PRIV_REQUIRES esp_driver_isp 
Functions
- 
esp_err_t esp_isp_new_processor(const esp_isp_processor_cfg_t *proc_config, isp_proc_handle_t *ret_proc)
- New an ISP processor. - 参数:
- proc_config -- [in] Pointer to ISP config. Refer to - esp_isp_processor_cfg_t.
- ret_proc -- [out] Processor handle 
 
- 返回:
- ESP_OK On success 
- ESP_ERR_INVALID_ARG If the combination of arguments is invalid. 
- ESP_ERR_NOT_FOUND No free interrupt found with the specified flags 
- ESP_ERR_NOT_SUPPORTED Not supported mode 
- ESP_ERR_NO_MEM If out of memory 
 
 
- 
esp_err_t esp_isp_del_processor(isp_proc_handle_t proc)
- Delete an ISP processor. - 参数:
- proc -- [in] Processor handle 
- 返回:
- ESP_OK On success 
- ESP_ERR_INVALID_ARG If the combination of arguments is invalid. 
- ESP_ERR_INVALID_STATE Driver state is invalid. 
 
 
- 
esp_err_t esp_isp_enable(isp_proc_handle_t proc)
- Enable an ISP processor. - 参数:
- proc -- [in] Processor handle 
- 返回:
- ESP_OK On success 
- ESP_ERR_INVALID_ARG If the combination of arguments is invalid. 
- ESP_ERR_INVALID_STATE Driver state is invalid. 
 
 
- 
esp_err_t esp_isp_disable(isp_proc_handle_t proc)
- Disable an ISP processor. - 参数:
- proc -- [in] Processor handle 
- 返回:
- ESP_OK On success 
- ESP_ERR_INVALID_ARG If the combination of arguments is invalid. 
- ESP_ERR_INVALID_STATE Driver state is invalid. 
 
 
- 
esp_err_t esp_isp_register_event_callbacks(isp_proc_handle_t proc, const esp_isp_evt_cbs_t *cbs, void *user_data)
- Register ISP event callbacks. - 备注 - User can deregister a previously registered callback by calling this function and setting the to-be-deregistered callback member in the - cbsstructure to NULL.- 备注 - When CONFIG_ISP_ISR_IRAM_SAFE is enabled, the callback itself and functions called by it should be placed in IRAM. Involved variables (including - user_data) should be in internal RAM as well.- 参数:
- proc -- [in] Processor handle 
- cbs -- [in] Group of callback functions 
- user_data -- [in] User data, which will be delivered to the callback functions directly 
 
- 返回:
- ESP_OK: On success 
- ESP_ERR_INVALID_ARG: Invalid arguments 
- ESP_ERR_INVALID_STATE: Driver state is invalid, you shouldn't call this API at this moment 
 
 
Structures
- 
struct esp_isp_processor_cfg_t
- ISP configurations. - Public Members - 
isp_clk_src_t clk_src
- Clock source. 
 - 
uint32_t clk_hz
- Clock frequency in Hz, suggest twice higher than cam sensor speed. 
 - 
isp_input_data_source_t input_data_source
- Input data source. 
 - 
isp_color_t input_data_color_type
- Input color type. 
 - 
isp_color_t output_data_color_type
- Output color type. 
 - 
isp_color_range_t yuv_range
- When the - output_data_color_typeis any YUV color space, this field is to describe its color range.
 - 
isp_yuv_conv_std_t yuv_std
- This field is to describe YUV<->RGB conversion standard. 
 - 
bool has_line_start_packet
- Enable line start packet. 
 - 
bool has_line_end_packet
- Enable line end packet. 
 - 
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. 
 - 
color_raw_element_order_t bayer_order
- Bayer order. 
 - 
int intr_priority
- The interrupt priority, range 0~3, if set to 0, the driver will try to allocate an interrupt with a relative low priority (1,2,3) 
 
- 
isp_clk_src_t clk_src