fix(cam): fix dvp do not generate clock

This commit is contained in:
gaoxu
2025-06-02 14:56:00 +08:00
parent 2a13a36589
commit 1533cab12b
4 changed files with 101 additions and 2 deletions

View File

@ -43,10 +43,12 @@ typedef struct esp_cam_ctlr_dvp_config {
uint32_t bk_buffer_dis : 1; /*!< Disable backup buffer */
uint32_t pin_dont_init : 1; /*!< Don't initialize DVP pins if users have called "esp_cam_ctlr_dvp_init" before */
uint32_t pic_format_jpeg : 1; /*!< Input picture format is JPEG, if set this flag and "input_data_color_type" will be ignored */
uint32_t external_xtal : 1; /*!< Using external XTAL, if set, xclk_io and dvp output clock will be ignored */
}; /*!< Boolean Flags */
uint32_t dma_burst_size; /*!< DVP DMA burst transmission block size, set to 0 means to disable the data burst,
other value must be power of 2, e.g., 4/8/16/32/64/128 */
uint32_t xclk_freq; /*!< DVP output clock frequency in HZ, only valid if `external_xtal` is set to true */
const esp_cam_ctlr_dvp_pin_config_t *pin; /*!< DVP pin configuration, this will be ignored by "esp_cam_new_dvp_ctlr" if "pin_dont_init" is set */
} esp_cam_ctlr_dvp_config_t;

View File

@ -707,6 +707,9 @@ esp_err_t esp_cam_new_dvp_ctlr(const esp_cam_ctlr_dvp_config_t *config, esp_cam_
ESP_RETURN_ON_FALSE(config && ret_handle, ESP_ERR_INVALID_ARG, TAG, "invalid argument: config or ret_handle is null");
ESP_RETURN_ON_FALSE(config->ctlr_id < CAP_DVP_PERIPH_NUM, ESP_ERR_INVALID_ARG, TAG, "invalid argument: ctlr_id >= %d", CAP_DVP_PERIPH_NUM);
ESP_RETURN_ON_FALSE(config->pin_dont_init || config->pin, ESP_ERR_INVALID_ARG, TAG, "invalid argument: pin_dont_init is unset and pin is null");
ESP_RETURN_ON_FALSE(config->external_xtal || config->pin_dont_init || config->pin->xclk_io != GPIO_NUM_NC, ESP_ERR_INVALID_ARG, TAG, "invalid argument: xclk_io is not set");
ESP_RETURN_ON_FALSE(config->external_xtal || config->xclk_freq, ESP_ERR_INVALID_ARG, TAG, "invalid argument: xclk_freq is not set");
ESP_RETURN_ON_ERROR(esp_cache_get_alignment(MALLOC_CAP_SPIRAM | MALLOC_CAP_DMA, &alignment_size), TAG, "failed to get cache alignment");
ESP_RETURN_ON_ERROR(esp_cam_ctlr_dvp_cam_get_frame_size(config, &fb_size_in_bytes), TAG, "invalid argument: input frame pixel format is not supported");
ESP_RETURN_ON_ERROR(dvp_shared_ctrl_claim_io_signals(), TAG, "failed to claim io signals");
@ -745,10 +748,17 @@ esp_err_t esp_cam_new_dvp_ctlr(const esp_cam_ctlr_dvp_config_t *config, esp_cam_
};
if (!config->pin_dont_init) {
// Initialzie DVP clock and GPIO internally
ESP_GOTO_ON_ERROR(esp_cam_ctlr_dvp_init(config->ctlr_id, config->clk_src, config->pin),
fail5, TAG, "failed to initialize clock and GPIO");
}
if (!config->external_xtal) {
// Generate DVP xtal clock internally
ESP_GOTO_ON_ERROR(esp_cam_ctlr_dvp_output_clock(config->ctlr_id, config->clk_src, config->xclk_freq),
fail5, TAG, "failed to generate xtal clock");
}
cam_hal_init(&ctlr->hal, &cam_hal_config);
ctlr->ctlr_id = config->ctlr_id;

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -20,6 +20,7 @@ TEST_CASE("TEST DVP driver allocation", "[DVP]")
.dma_burst_size = 128,
.byte_swap_en = false,
.pin_dont_init = true,
.external_xtal = true,
};
esp_cam_ctlr_handle_t handle = NULL;
TEST_ESP_OK(esp_cam_new_dvp_ctlr(&dvp_config, &handle));
@ -45,6 +46,7 @@ TEST_CASE("TEST DVP driver allocation with JPEG input", "[DVP]")
.byte_swap_en = false,
.pin_dont_init = true,
.pic_format_jpeg = true,
.external_xtal = true,
};
esp_cam_ctlr_handle_t handle = NULL;
TEST_ESP_OK(esp_cam_new_dvp_ctlr(&dvp_config, &handle));
@ -71,6 +73,7 @@ TEST_CASE("TEST DVP driver no backup buffer usage", "[DVP]")
.byte_swap_en = false,
.bk_buffer_dis = true,
.pin_dont_init = true,
.external_xtal = true,
};
esp_cam_ctlr_handle_t handle = NULL;
TEST_ESP_OK(esp_cam_new_dvp_ctlr(&dvp_config, &handle));
@ -84,3 +87,87 @@ TEST_CASE("TEST DVP driver no backup buffer usage", "[DVP]")
TEST_ASSERT_EQUAL((dvp_config.h_res * dvp_config.v_res * 2), bk_buffer_len); // out type RGB565 using 2 byte / pixel
TEST_ESP_OK(esp_cam_ctlr_del(handle));
}
TEST_CASE("TEST DVP driver intern/extern init", "[DVP]")
{
esp_cam_ctlr_dvp_config_t dvp_config = {
.ctlr_id = 0,
.clk_src = CAM_CLK_SRC_DEFAULT,
.h_res = 800,
.v_res = 640,
.input_data_color_type = CAM_CTLR_COLOR_RGB565,
.dma_burst_size = 128,
.byte_swap_en = false,
.external_xtal = true,
};
esp_cam_ctlr_handle_t handle = NULL;
//Init externally, do not check pin
dvp_config.pin_dont_init = true;
TEST_ESP_OK(esp_cam_new_dvp_ctlr(&dvp_config, &handle));
TEST_ESP_OK(esp_cam_ctlr_del(handle));
//Init internally but not set pin
dvp_config.pin_dont_init = false;
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_cam_new_dvp_ctlr(&dvp_config, &handle));
//Init internally and set pin
esp_cam_ctlr_dvp_pin_config_t pin_cfg = {
.data_width = 8,
};
dvp_config.pin = &pin_cfg;
TEST_ESP_OK(esp_cam_new_dvp_ctlr(&dvp_config, &handle));
TEST_ESP_OK(esp_cam_ctlr_del(handle));
}
TEST_CASE("TEST DVP driver intern/extern generate xclk", "[DVP]")
{
esp_cam_ctlr_dvp_config_t dvp_config = {
.ctlr_id = 0,
.clk_src = CAM_CLK_SRC_DEFAULT,
.h_res = 800,
.v_res = 640,
.input_data_color_type = CAM_CTLR_COLOR_RGB565,
.dma_burst_size = 128,
.byte_swap_en = false,
.external_xtal = true,
};
esp_cam_ctlr_handle_t handle = NULL;
//Init externally, generate xclk externally, check nothing
dvp_config.pin_dont_init = true;
dvp_config.external_xtal = true;
TEST_ESP_OK(esp_cam_new_dvp_ctlr(&dvp_config, &handle));
TEST_ESP_OK(esp_cam_ctlr_del(handle));
//Init externally, generate xclk internally, do not check pin, check xclk_freq
dvp_config.pin_dont_init = true;
dvp_config.external_xtal = false;
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_cam_new_dvp_ctlr(&dvp_config, &handle));
dvp_config.xclk_freq = 20000000;
TEST_ESP_OK(esp_cam_new_dvp_ctlr(&dvp_config, &handle));
TEST_ESP_OK(esp_cam_ctlr_del(handle));
esp_cam_ctlr_dvp_pin_config_t pin_cfg = {
.data_width = 8,
.xclk_io = GPIO_NUM_NC,
};
//Init internally, generate xclk externally, check nothing
dvp_config.pin = &pin_cfg;
dvp_config.pin_dont_init = false;
dvp_config.external_xtal = true;
TEST_ESP_OK(esp_cam_new_dvp_ctlr(&dvp_config, &handle));
TEST_ESP_OK(esp_cam_ctlr_del(handle));
//Init internally, generate xclk internally, check xclk_io and xclk_freq
dvp_config.pin = &pin_cfg;
dvp_config.pin_dont_init = false;
dvp_config.external_xtal = false;
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_cam_new_dvp_ctlr(&dvp_config, &handle));
pin_cfg.xclk_io = 20;
dvp_config.pin = &pin_cfg;
TEST_ESP_OK(esp_cam_new_dvp_ctlr(&dvp_config, &handle));
TEST_ESP_OK(esp_cam_ctlr_del(handle));
}

View File

@ -104,9 +104,9 @@ void app_main(void)
.v_res = CONFIG_EXAMPLE_CAM_VRES,
.input_data_color_type = CAM_CTLR_COLOR_RGB565,
.dma_burst_size = 128,
.pin_dont_init = false,
.pin = &pin_cfg,
.bk_buffer_dis = 1,
.xclk_freq = EXAMPLE_DVP_CAM_XCLK_FREQ_HZ,
};
ret = esp_cam_new_dvp_ctlr(&dvp_config, &cam_handle);