From e0b530bd6474227a8014c186c28202a585405892 Mon Sep 17 00:00:00 2001 From: armando Date: Fri, 17 Oct 2025 15:29:33 +0800 Subject: [PATCH] feat(isp): added shadow reg settings --- components/esp_driver_isp/src/isp_bf.c | 3 + components/esp_driver_isp/src/isp_blc.c | 3 + components/esp_driver_isp/src/isp_ccm.c | 3 + components/esp_driver_isp/src/isp_color.c | 3 + components/esp_driver_isp/src/isp_core.c | 2 + components/esp_driver_isp/src/isp_sharpen.c | 3 + components/esp_driver_isp/src/isp_wbg.c | 3 + components/hal/esp32p4/include/hal/isp_ll.h | 226 +++++++++++++++++++ docs/en/api-reference/peripherals/isp.rst | 2 +- docs/zh_CN/api-reference/peripherals/isp.rst | 2 +- 10 files changed, 248 insertions(+), 2 deletions(-) diff --git a/components/esp_driver_isp/src/isp_bf.c b/components/esp_driver_isp/src/isp_bf.c index 066076624f..1c71d0eefd 100644 --- a/components/esp_driver_isp/src/isp_bf.c +++ b/components/esp_driver_isp/src/isp_bf.c @@ -43,6 +43,9 @@ esp_err_t esp_isp_bf_configure(isp_proc_handle_t proc, const esp_isp_bf_config_t isp_hal_bf_config(&(proc->hal), NULL); } + bool valid = isp_ll_shadow_update_bf(proc->hal.hw); + ESP_RETURN_ON_FALSE_ISR(valid, ESP_ERR_INVALID_STATE, TAG, "failed to update bf shadow register"); + return ESP_OK; } diff --git a/components/esp_driver_isp/src/isp_blc.c b/components/esp_driver_isp/src/isp_blc.c index c808e66d04..f8faa2774b 100644 --- a/components/esp_driver_isp/src/isp_blc.c +++ b/components/esp_driver_isp/src/isp_blc.c @@ -58,6 +58,9 @@ esp_err_t esp_isp_blc_configure(isp_proc_handle_t isp_proc, const esp_isp_blc_co // Configure stretch enable for each channel isp_ll_blc_enable_stretch(isp_proc->hal.hw, config->stretch.top_left_chan_stretch_en, config->stretch.top_right_chan_stretch_en, config->stretch.bottom_left_chan_stretch_en, config->stretch.bottom_right_chan_stretch_en); + bool valid = isp_ll_shadow_update_blc(isp_proc->hal.hw); + ESP_RETURN_ON_FALSE_ISR(valid, ESP_ERR_INVALID_STATE, TAG, "failed to update blc shadow register"); + return ESP_OK; } diff --git a/components/esp_driver_isp/src/isp_ccm.c b/components/esp_driver_isp/src/isp_ccm.c index b8b28bad44..d41bfd64ec 100644 --- a/components/esp_driver_isp/src/isp_ccm.c +++ b/components/esp_driver_isp/src/isp_ccm.c @@ -33,11 +33,14 @@ esp_err_t esp_isp_ccm_configure(isp_proc_handle_t proc, const esp_isp_ccm_config } bool ret = true; + bool valid = false; 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); 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"); return ESP_OK; } diff --git a/components/esp_driver_isp/src/isp_color.c b/components/esp_driver_isp/src/isp_color.c index d10504e3f2..c3da6d5cdc 100644 --- a/components/esp_driver_isp/src/isp_color.c +++ b/components/esp_driver_isp/src/isp_color.c @@ -43,6 +43,9 @@ esp_err_t esp_isp_color_configure(isp_proc_handle_t proc, const esp_isp_color_co isp_hal_color_config(&(proc->hal), NULL); } + bool valid = isp_ll_shadow_update_color(proc->hal.hw); + ESP_RETURN_ON_FALSE_ISR(valid, ESP_ERR_INVALID_STATE, TAG, "failed to update color shadow register"); + return ESP_OK; } diff --git a/components/esp_driver_isp/src/isp_core.c b/components/esp_driver_isp/src/isp_core.c index b1d1b45e14..2fb6510d09 100644 --- a/components/esp_driver_isp/src/isp_core.c +++ b/components/esp_driver_isp/src/isp_core.c @@ -178,6 +178,8 @@ esp_err_t esp_isp_new_processor(const esp_isp_processor_cfg_t *proc_config, isp_ isp_ll_set_byte_swap(proc->hal.hw, true); } + isp_ll_shadow_set_mode(proc->hal.hw, ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC); + proc->in_color_format = in_color_format; proc->out_color_format = out_color_format; proc->h_res = proc_config->h_res; diff --git a/components/esp_driver_isp/src/isp_sharpen.c b/components/esp_driver_isp/src/isp_sharpen.c index b8ac88abeb..c0dd2fc258 100644 --- a/components/esp_driver_isp/src/isp_sharpen.c +++ b/components/esp_driver_isp/src/isp_sharpen.c @@ -45,6 +45,9 @@ esp_err_t esp_isp_sharpen_configure(isp_proc_handle_t proc, const esp_isp_sharpe isp_hal_sharpen_config(&(proc->hal), NULL); } + bool valid = isp_ll_shadow_update_sharpen(proc->hal.hw); + ESP_RETURN_ON_FALSE_ISR(valid, ESP_ERR_INVALID_STATE, TAG, "failed to update sharp shadow register"); + return ESP_OK; } diff --git a/components/esp_driver_isp/src/isp_wbg.c b/components/esp_driver_isp/src/isp_wbg.c index e03d0eda52..96b809840c 100644 --- a/components/esp_driver_isp/src/isp_wbg.c +++ b/components/esp_driver_isp/src/isp_wbg.c @@ -61,6 +61,9 @@ esp_err_t esp_isp_wbg_set_wb_gain(isp_proc_handle_t isp_proc, isp_wbg_gain_t gai // Set WBG gain isp_ll_awb_set_wb_gain(isp_proc->hal.hw, gain); + bool valid = isp_ll_shadow_update_wbg(isp_proc->hal.hw); + ESP_RETURN_ON_FALSE_ISR(valid, ESP_ERR_INVALID_STATE, TAG, "failed to update wbg shadow register"); + return ESP_OK; } diff --git a/components/hal/esp32p4/include/hal/isp_ll.h b/components/hal/esp32p4/include/hal/isp_ll.h index 2fec895ab4..63f2da2ec9 100644 --- a/components/hal/esp32p4/include/hal/isp_ll.h +++ b/components/hal/esp32p4/include/hal/isp_ll.h @@ -197,6 +197,14 @@ typedef enum { ISP_LL_PIPELINE_CLK_CTRL_ALWAYS_ON, ///< Always on } isp_ll_pipeline_clk_ctrl_t; +/** + * @brief Shadow mode + */ +typedef enum { + ISP_SHADOW_MODE_DISABLE, + ISP_SHADOW_MODE_UPDATE_EVERY_VSYNC, + ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC, +} isp_ll_shadow_mode_t; /*--------------------------------------------------------------- Clock @@ -1852,6 +1860,224 @@ static inline void isp_ll_demosaic_set_padding_line_tail_valid_end_pixel(isp_dev HAL_FORCE_MODIFY_U32_REG_FIELD(hw->demosaic_matrix_ctrl, demosaic_tail_pixen_pulse_th, end_pixel); } +#if HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 300 +/*--------------------------------------------------------------- + Shadow +---------------------------------------------------------------*/ +/** + * @brief Shadow mode + * + * @param[in] hw Hardware instance address + * @param[in] mode 'isp_ll_shadow_mode_t` + */ +static inline void isp_ll_shadow_set_mode(isp_dev_t *hw, isp_ll_shadow_mode_t mode) +{ + hw->shadow_reg_ctrl.shadow_update_sel = mode; +} + +/** + * @brief Update BLC shadow register + * + * @param[in] hw Hardware instance address + * @return + * - True if update is successful, False otherwise + */ +static inline bool isp_ll_shadow_update_blc(isp_dev_t *hw) +{ + //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.blc_update == 1) { + return false; + } + + //self clear when ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC + hw->shadow_reg_ctrl.blc_update = 1; + + return true; +} + +/** + * @brief Update DPC shadow register + * + * @param[in] hw Hardware instance address + * @return + * - True if update is successful, False otherwise + */ +static inline bool isp_ll_shadow_update_dpc(isp_dev_t *hw) +{ + //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.dpc_update == 1) { + return false; + } + + //self clear when ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC + hw->shadow_reg_ctrl.dpc_update = 1; + + return true; +} + +/** + * @brief Update BF shadow register + * + * @param[in] hw Hardware instance address + * @return + * - True if update is successful, False otherwise + */ +static inline bool isp_ll_shadow_update_bf(isp_dev_t *hw) +{ + //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.bf_update == 1) { + return false; + } + + //self clear when ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC + hw->shadow_reg_ctrl.bf_update = 1; + + return true; +} + +/** + * @brief Update WBG shadow register + * + * @param[in] hw Hardware instance address + * @return + * - True if update is successful, False otherwise + */ +static inline bool isp_ll_shadow_update_wbg(isp_dev_t *hw) +{ + //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.wbg_update == 1) { + return false; + } + + //self clear when ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC + hw->shadow_reg_ctrl.wbg_update = 1; + + return true; +} + +/** + * @brief Update CCM shadow register + * + * @param[in] hw Hardware instance address + * @return + * - True if update is successful, False otherwise + */ +static inline bool isp_ll_shadow_update_ccm(isp_dev_t *hw) +{ + //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; + } + + //self clear when ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC + hw->shadow_reg_ctrl.ccm_update = 1; + + return true; +} + +/** + * @brief Update Sharpen shadow register + * + * @param[in] hw Hardware instance address + * @return + * - True if update is successful, False otherwise + */ +static inline bool isp_ll_shadow_update_sharpen(isp_dev_t *hw) +{ + //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.sharp_update == 1) { + return false; + } + + //self clear when ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC + hw->shadow_reg_ctrl.sharp_update = 1; + + return true; +} + +/** + * @brief Update Color shadow register + * + * @param[in] hw Hardware instance address + * @return + * - True if update is successful, False otherwise + */ +static inline bool isp_ll_shadow_update_color(isp_dev_t *hw) +{ + //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.color_update == 1) { + return false; + } + + //self clear when ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC + hw->shadow_reg_ctrl.color_update = 1; + + return true; +} + +#else +static inline void isp_ll_shadow_set_mode(isp_dev_t *hw, isp_ll_shadow_mode_t mode) +{ + //for compatibility +} + +static inline bool isp_ll_shadow_update_blc(isp_dev_t *hw) +{ + //for compatibility + return true; +} + +static inline bool isp_ll_shadow_update_dpc(isp_dev_t *hw) +{ + //for compatibility + return true; +} + +static inline bool isp_ll_shadow_update_bf(isp_dev_t *hw) +{ + //for compatibility + return true; +} + +static inline bool isp_ll_shadow_update_wbg(isp_dev_t *hw) +{ + //for compatibility + return true; +} + +static inline bool isp_ll_shadow_update_ccm(isp_dev_t *hw) +{ + //for compatibility + return true; +} + +static inline bool isp_ll_shadow_update_sharpen(isp_dev_t *hw) +{ + //for compatibility + return true; +} + +static inline bool isp_ll_shadow_update_color(isp_dev_t *hw) +{ + //for compatibility + return true; +} +#endif + /*--------------------------------------------------------------- Sharpen ---------------------------------------------------------------*/ diff --git a/docs/en/api-reference/peripherals/isp.rst b/docs/en/api-reference/peripherals/isp.rst index 41c8381c32..1408484bdf 100644 --- a/docs/en/api-reference/peripherals/isp.rst +++ b/docs/en/api-reference/peripherals/isp.rst @@ -724,7 +724,7 @@ Calling :cpp:func:`esp_isp_demosaic_configure` to configure Demosaic function, y ... }; - ESP_ERROR_CHECK(esp_isp_demosaic_configure(isp_proc, &sharpen_config)); + ESP_ERROR_CHECK(esp_isp_demosaic_configure(isp_proc, &demosaic_config)); ESP_ERROR_CHECK(esp_isp_demosaic_enable(isp_proc)); After calling :cpp:func:`esp_isp_demosaic_configure`, you need to enable the ISP Demosaic controller, by calling :cpp:func:`esp_isp_demosaic_enable`. This function: diff --git a/docs/zh_CN/api-reference/peripherals/isp.rst b/docs/zh_CN/api-reference/peripherals/isp.rst index 8bcaa3c1f0..92ac020914 100644 --- a/docs/zh_CN/api-reference/peripherals/isp.rst +++ b/docs/zh_CN/api-reference/peripherals/isp.rst @@ -724,7 +724,7 @@ ISP 去马赛克控制器 ... }; - ESP_ERROR_CHECK(esp_isp_demosaic_configure(isp_proc, &sharpen_config)); + ESP_ERROR_CHECK(esp_isp_demosaic_configure(isp_proc, &demosaic_config)); ESP_ERROR_CHECK(esp_isp_demosaic_enable(isp_proc)); 调用 :cpp:func:`esp_isp_demosaic_configure` 后,需要通过调用 :cpp:func:`esp_isp_demosaic_enable` 来启用 ISP 去马赛克控制器。此函数: