From 1533cab12bf13564149745e8fd407302a20aebcf Mon Sep 17 00:00:00 2001 From: gaoxu Date: Mon, 2 Jun 2025 14:56:00 +0800 Subject: [PATCH] fix(cam): fix dvp do not generate clock --- .../dvp/include/esp_cam_ctlr_dvp.h | 2 + .../dvp/src/esp_cam_ctlr_dvp_cam.c | 10 +++ .../test_apps/dvp/main/test_dvp_driver.c | 89 ++++++++++++++++++- .../camera/dvp_dsi/main/dvp_dsi_main.c | 2 +- 4 files changed, 101 insertions(+), 2 deletions(-) diff --git a/components/esp_driver_cam/dvp/include/esp_cam_ctlr_dvp.h b/components/esp_driver_cam/dvp/include/esp_cam_ctlr_dvp.h index 01cd362a90..032ab47a21 100644 --- a/components/esp_driver_cam/dvp/include/esp_cam_ctlr_dvp.h +++ b/components/esp_driver_cam/dvp/include/esp_cam_ctlr_dvp.h @@ -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; diff --git a/components/esp_driver_cam/dvp/src/esp_cam_ctlr_dvp_cam.c b/components/esp_driver_cam/dvp/src/esp_cam_ctlr_dvp_cam.c index eaddf9a94a..26cdb6a0e2 100644 --- a/components/esp_driver_cam/dvp/src/esp_cam_ctlr_dvp_cam.c +++ b/components/esp_driver_cam/dvp/src/esp_cam_ctlr_dvp_cam.c @@ -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; diff --git a/components/esp_driver_cam/test_apps/dvp/main/test_dvp_driver.c b/components/esp_driver_cam/test_apps/dvp/main/test_dvp_driver.c index 4f6b7041e8..ec99cc5202 100644 --- a/components/esp_driver_cam/test_apps/dvp/main/test_dvp_driver.c +++ b/components/esp_driver_cam/test_apps/dvp/main/test_dvp_driver.c @@ -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)); +} diff --git a/examples/peripherals/camera/dvp_dsi/main/dvp_dsi_main.c b/examples/peripherals/camera/dvp_dsi/main/dvp_dsi_main.c index 2cc372ac5c..5e5f6d4053 100644 --- a/examples/peripherals/camera/dvp_dsi/main/dvp_dsi_main.c +++ b/examples/peripherals/camera/dvp_dsi/main/dvp_dsi_main.c @@ -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);