diff --git a/components/esp_adc/test_apps/adc/pytest_adc.py b/components/esp_adc/test_apps/adc/pytest_adc.py index 3cc1661ac2..b914333b98 100644 --- a/components/esp_adc/test_apps/adc/pytest_adc.py +++ b/components/esp_adc/test_apps/adc/pytest_adc.py @@ -32,6 +32,7 @@ def test_adc_esp32c2_xtal_26mhz(dut: Dut) -> None: dut.run_all_single_board_cases(timeout=120, reset=True) +# TODO: IDF-15005 # P4 REV2 adc @pytest.mark.adc @pytest.mark.esp32p4_eco4 diff --git a/components/esp_driver_isp/include/driver/isp_ccm.h b/components/esp_driver_isp/include/driver/isp_ccm.h index 1560782894..f779ff3cb7 100644 --- a/components/esp_driver_isp/include/driver/isp_ccm.h +++ b/components/esp_driver_isp/include/driver/isp_ccm.h @@ -26,6 +26,9 @@ typedef struct { * When saturation is true, and final value will be limited to 4.0, and won't rise error * When saturation is false, `esp_isp_ccm_configure` will rise ESP_ERR_INVALID_ARG error */ + struct { + uint32_t update_once_configured : 1; ///< If set, apply configuration to hardware immediately; otherwise defer to frame boundary + } flags; ///< Driver behaviour flags } esp_isp_ccm_config_t; /** diff --git a/components/esp_driver_isp/src/isp_ccm.c b/components/esp_driver_isp/src/isp_ccm.c index 4168a1ad52..cb688dc7f3 100644 --- a/components/esp_driver_isp/src/isp_ccm.c +++ b/components/esp_driver_isp/src/isp_ccm.c @@ -26,7 +26,7 @@ esp_err_t esp_isp_ccm_configure(isp_proc_handle_t proc, const esp_isp_ccm_config portENTER_CRITICAL(&proc->spinlock); isp_ll_ccm_set_clk_ctrl_mode(proc->hal.hw, ISP_LL_PIPELINE_CLK_CTRL_AUTO); ret = isp_hal_ccm_set_matrix(&proc->hal, ccm_cfg->saturation, ccm_cfg->matrix); - valid = isp_ll_shadow_update_ccm(proc->hal.hw); + valid = isp_ll_shadow_update_ccm(proc->hal.hw, ccm_cfg->flags.update_once_configured); portEXIT_CRITICAL(&proc->spinlock); ESP_RETURN_ON_FALSE(ret, ESP_ERR_INVALID_ARG, TAG, "invalid argument: ccm matrix contain NaN or out of range"); ESP_RETURN_ON_FALSE(valid, ESP_ERR_INVALID_STATE, TAG, "failed to update ccm shadow register"); diff --git a/components/esp_driver_isp/test_apps/isp/main/test_isp_driver.c b/components/esp_driver_isp/test_apps/isp/main/test_isp_driver.c index d14f6033a2..e73b45fb4e 100644 --- a/components/esp_driver_isp/test_apps/isp/main/test_isp_driver.c +++ b/components/esp_driver_isp/test_apps/isp/main/test_isp_driver.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -210,15 +210,20 @@ TEST_CASE("ISP CCM basic function", "[isp]") esp_isp_ccm_config_t ccm_cfg = { .matrix = { - {5.0, 0.0, 0.0}, + {16.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0} }, .saturation = false, + .flags = { + .update_once_configured = true, + }, }; // Out of range case TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_isp_ccm_configure(isp_proc, &ccm_cfg)); + // saturation case + ccm_cfg.matrix[0][0] = 5.0; ccm_cfg.saturation = true; TEST_ESP_OK(esp_isp_ccm_configure(isp_proc, &ccm_cfg)); TEST_ESP_OK(esp_isp_ccm_enable(isp_proc)); diff --git a/components/esp_driver_isp/test_apps/isp/pytest_isp.py b/components/esp_driver_isp/test_apps/isp/pytest_isp.py index 92c6291f7c..44884efbeb 100644 --- a/components/esp_driver_isp/test_apps/isp/pytest_isp.py +++ b/components/esp_driver_isp/test_apps/isp/pytest_isp.py @@ -1,7 +1,35 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 -from pytest_embedded_idf import IdfDut +import pytest +from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize +from pytest_embedded_idf.utils import soc_filtered_targets -def test_isp(dut: IdfDut) -> None: +@pytest.mark.camera +@pytest.mark.ov5647 +@pytest.mark.parametrize( + 'config', + [ + ('default'), + ], + indirect=True, +) +@idf_parametrize('target', soc_filtered_targets('SOC_ISP_SUPPORTED == 1'), indirect=['target']) +def test_isp(dut: Dut) -> None: dut.run_all_single_board_cases() + + +# TODO: IDF-15006 +# @pytest.mark.generic +# @pytest.mark.esp32p4_eco4 +# @pytest.mark.parametrize( +# 'config', +# [ +# ('esp32p4_eco4'), +# ], +# indirect=True, +# ) +# @idf_parametrize('target', ['esp32p4'], indirect=['target']) +# def test_isp_esp32p4_rev2(dut: Dut) -> None: +# dut.run_all_single_board_cases() diff --git a/components/esp_driver_isp/test_apps/isp/sdkconfig.ci.default b/components/esp_driver_isp/test_apps/isp/sdkconfig.ci.default new file mode 100644 index 0000000000..7c05891852 --- /dev/null +++ b/components/esp_driver_isp/test_apps/isp/sdkconfig.ci.default @@ -0,0 +1 @@ +# For pytest to run default tests diff --git a/components/esp_driver_isp/test_apps/isp/sdkconfig.ci.esp32p4_eco4 b/components/esp_driver_isp/test_apps/isp/sdkconfig.ci.esp32p4_eco4 new file mode 100644 index 0000000000..2c6c907fab --- /dev/null +++ b/components/esp_driver_isp/test_apps/isp/sdkconfig.ci.esp32p4_eco4 @@ -0,0 +1,2 @@ +CONFIG_IDF_TARGET="esp32p4" +CONFIG_ESP32P4_SELECTS_REV_LESS_V3=y diff --git a/components/hal/esp32p4/include/hal/isp_ll.h b/components/hal/esp32p4/include/hal/isp_ll.h index d5abfc435d..21d5e93d72 100644 --- a/components/hal/esp32p4/include/hal/isp_ll.h +++ b/components/hal/esp32p4/include/hal/isp_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -1965,21 +1965,27 @@ static inline bool isp_ll_shadow_update_wbg(isp_dev_t *hw) /** * @brief Update CCM shadow register * - * @param[in] hw Hardware instance address + * @param[in] hw Hardware instance address + * @param[in] force_update Force update * @return * - True if update is successful, False otherwise */ -static inline bool isp_ll_shadow_update_ccm(isp_dev_t *hw) +static inline bool isp_ll_shadow_update_ccm(isp_dev_t *hw, bool force_update) { //only valid when ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC HAL_ASSERT(hw->shadow_reg_ctrl.shadow_update_sel == ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC); - if (hw->shadow_reg_ctrl.ccm_update == 1) { - return false; - } + if (force_update) { + //don't care shadow register + hw->shadow_reg_ctrl.ccm_update = 1; + } else { + if (hw->shadow_reg_ctrl.ccm_update == 1) { + return false; + } - //self clear when ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC - hw->shadow_reg_ctrl.ccm_update = 1; + //self clear when ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC + hw->shadow_reg_ctrl.ccm_update = 1; + } return true; } @@ -2058,7 +2064,7 @@ static inline bool isp_ll_shadow_update_wbg(isp_dev_t *hw) return true; } -static inline bool isp_ll_shadow_update_ccm(isp_dev_t *hw) +static inline bool isp_ll_shadow_update_ccm(isp_dev_t *hw, bool force_update) { //for compatibility return true;