From a01961b74e18ff76acd7dc6fd7c69da21d343853 Mon Sep 17 00:00:00 2001 From: armando Date: Tue, 9 Dec 2025 16:14:54 +0800 Subject: [PATCH 1/4] ci(isp): reenable tests --- .../esp_driver_isp/test_apps/isp/pytest_isp.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) 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..501c1fb873 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,13 @@ -# 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 +@idf_parametrize('target', soc_filtered_targets('SOC_ISP_SUPPORTED == 1'), indirect=['target']) +def test_isp(dut: Dut) -> None: dut.run_all_single_board_cases() From 4f660e5ee1a0f2bbc40bf8d5ed680a989f33a2cb Mon Sep 17 00:00:00 2001 From: armando Date: Thu, 11 Dec 2025 10:24:31 +0800 Subject: [PATCH 2/4] feat(isp): allow ccm to bypass shadow register --- .../esp_driver_isp/include/driver/isp_ccm.h | 3 +++ components/esp_driver_isp/src/isp_ccm.c | 2 +- .../test_apps/isp/main/test_isp_driver.c | 9 ++++++-- components/hal/esp32p4/include/hal/isp_ll.h | 22 ++++++++++++------- 4 files changed, 25 insertions(+), 11 deletions(-) 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/hal/esp32p4/include/hal/isp_ll.h b/components/hal/esp32p4/include/hal/isp_ll.h index d5abfc435d..4a1715d335 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; } From 874f7c4f34bc54f73160641e46d7c5f41458cf1c Mon Sep 17 00:00:00 2001 From: armando Date: Fri, 12 Dec 2025 10:04:29 +0800 Subject: [PATCH 3/4] fix(isp): fix isp rev012 build --- components/esp_adc/test_apps/adc/pytest_adc.py | 1 + .../esp_driver_isp/test_apps/isp/pytest_isp.py | 15 +++++++++++++++ .../test_apps/isp/sdkconfig.ci.esp32p4_eco4 | 2 ++ components/hal/esp32p4/include/hal/isp_ll.h | 2 +- 4 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 components/esp_driver_isp/test_apps/isp/sdkconfig.ci.esp32p4_eco4 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/test_apps/isp/pytest_isp.py b/components/esp_driver_isp/test_apps/isp/pytest_isp.py index 501c1fb873..c92c3db11e 100644 --- a/components/esp_driver_isp/test_apps/isp/pytest_isp.py +++ b/components/esp_driver_isp/test_apps/isp/pytest_isp.py @@ -11,3 +11,18 @@ from pytest_embedded_idf.utils import soc_filtered_targets @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.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 4a1715d335..21d5e93d72 100644 --- a/components/hal/esp32p4/include/hal/isp_ll.h +++ b/components/hal/esp32p4/include/hal/isp_ll.h @@ -2064,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; From 502a10b5dcd2e9e3d7f661aac54191ad769ffd8a Mon Sep 17 00:00:00 2001 From: armando Date: Mon, 15 Dec 2025 11:54:38 +0800 Subject: [PATCH 4/4] ci: enable isp default tests --- components/esp_driver_isp/test_apps/isp/pytest_isp.py | 7 +++++++ .../esp_driver_isp/test_apps/isp/sdkconfig.ci.default | 1 + 2 files changed, 8 insertions(+) create mode 100644 components/esp_driver_isp/test_apps/isp/sdkconfig.ci.default 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 c92c3db11e..44884efbeb 100644 --- a/components/esp_driver_isp/test_apps/isp/pytest_isp.py +++ b/components/esp_driver_isp/test_apps/isp/pytest_isp.py @@ -8,6 +8,13 @@ from pytest_embedded_idf.utils import soc_filtered_targets @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() 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