From c88ba68cb089e4ef8bea27674170c52fbaf519e7 Mon Sep 17 00:00:00 2001 From: gaoxu Date: Thu, 18 Jul 2024 20:11:07 +0800 Subject: [PATCH] feat(isp): ISP dispatched ISRs together --- .../esp_driver_isp/include/driver/isp_ae.h | 2 +- .../esp_driver_isp/include/driver/isp_af.h | 2 +- .../esp_driver_isp/include/driver/isp_core.h | 1 + .../include/esp_private/isp_private.h | 29 +++- components/esp_driver_isp/src/isp_ae.c | 49 ++----- components/esp_driver_isp/src/isp_af.c | 28 ++-- components/esp_driver_isp/src/isp_awb.c | 36 ++--- components/esp_driver_isp/src/isp_core.c | 138 +++++++++++++++++- .../test_apps/isp/main/test_isp_driver.c | 4 +- 9 files changed, 205 insertions(+), 84 deletions(-) diff --git a/components/esp_driver_isp/include/driver/isp_ae.h b/components/esp_driver_isp/include/driver/isp_ae.h index 66e31c9c8b..289aad7ada 100644 --- a/components/esp_driver_isp/include/driver/isp_ae.h +++ b/components/esp_driver_isp/include/driver/isp_ae.h @@ -21,7 +21,7 @@ extern "C" { typedef struct { isp_ae_sample_point_t sample_point; ///< The input data source, ISP_AE_SAMPLE_POINT_AFTER_DEMOSAIC: AE input data after demosaic, ISP_AE_SAMPLE_POINT_AFTER_GAMMA: AE input data after gamma isp_window_t window; ///< The sampling windows of AE - int intr_priority; ///< The interrupt priority, range 0~7, if set to 0, the driver will try to allocate an interrupt with a relative low priority (1,2,3) otherwise the larger the higher, 7 is NMI + int intr_priority; ///< The interrupt priority, range 0~3, if set to 0, the driver will try to allocate an interrupt with a relative low priority (1,2,3) } esp_isp_ae_config_t; /** diff --git a/components/esp_driver_isp/include/driver/isp_af.h b/components/esp_driver_isp/include/driver/isp_af.h index 1d079bf615..da1714d51b 100644 --- a/components/esp_driver_isp/include/driver/isp_af.h +++ b/components/esp_driver_isp/include/driver/isp_af.h @@ -21,7 +21,7 @@ extern "C" { typedef struct { isp_window_t window[ISP_AF_WINDOW_NUM]; ///< The sampling windows of AF int edge_thresh; ///< Edge threshold, definition higher than this value will be counted as a valid pixel for calculating AF result - int intr_priority; ///< The interrupt priority, range 0~7, if set to 0, the driver will try to allocate an interrupt with a relative low priority (1,2,3) otherwise the larger the higher, 7 is NMI + int intr_priority; ///< The interrupt priority, range 0~3, if set to 0, the driver will try to allocate an interrupt with a relative low priority (1,2,3) } esp_isp_af_config_t; /** diff --git a/components/esp_driver_isp/include/driver/isp_core.h b/components/esp_driver_isp/include/driver/isp_core.h index 8081e945fe..9f330aeaff 100644 --- a/components/esp_driver_isp/include/driver/isp_core.h +++ b/components/esp_driver_isp/include/driver/isp_core.h @@ -28,6 +28,7 @@ typedef struct { bool has_line_end_packet; ///< Enable line end packet uint32_t h_res; ///< Input horizontal resolution, i.e. the number of pixels in a line uint32_t v_res; ///< Input vertical resolution, i.e. the number of lines in a frame + int intr_priority; ///< The interrupt priority, range 0~3 } esp_isp_processor_cfg_t; /** diff --git a/components/esp_driver_isp/include/esp_private/isp_private.h b/components/esp_driver_isp/include/esp_private/isp_private.h index 2ee7c59127..b2f0d7c736 100644 --- a/components/esp_driver_isp/include/esp_private/isp_private.h +++ b/components/esp_driver_isp/include/esp_private/isp_private.h @@ -32,10 +32,10 @@ extern "C" { #endif #if CONFIG_ISP_ISR_IRAM_SAFE -#define ISP_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_IRAM) +#define ISP_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_IRAM) #define ISP_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT) #else -#define ISP_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_INTRDISABLED) +#define ISP_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_INTRDISABLED) #define ISP_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT #endif @@ -67,9 +67,34 @@ typedef struct isp_processor_t { isp_awb_ctlr_t awb_ctlr; isp_fsm_t bf_fsm; isp_ae_ctlr_t ae_ctlr; + /* ISR */ + intr_handle_t intr_hdl; + int intr_priority; + int isr_ref_counts; + struct { + uint32_t af_isr_added: 1; + uint32_t ae_isr_added: 1; + uint32_t awb_isr_added: 1; + } isr_users; + } isp_processor_t; #endif +typedef enum { + ISP_SUBMODULE_AF, + ISP_SUBMODULE_AE, + ISP_SUBMODULE_AWB, +} isp_submodule_t; + +/*--------------------------------------------------------------- + INTR +---------------------------------------------------------------*/ +esp_err_t esp_isp_register_isr(isp_proc_handle_t proc, isp_submodule_t submodule); +esp_err_t esp_isp_deregister_isr(isp_proc_handle_t proc, isp_submodule_t submodule); +bool esp_isp_af_isr(isp_proc_handle_t proc, uint32_t af_events); +bool esp_isp_ae_isr(isp_proc_handle_t proc, uint32_t ae_events); +bool esp_isp_awb_isr(isp_proc_handle_t proc, uint32_t awb_events); + #ifdef __cplusplus } #endif diff --git a/components/esp_driver_isp/src/isp_ae.c b/components/esp_driver_isp/src/isp_ae.c index 2d7d28bd04..89582be011 100644 --- a/components/esp_driver_isp/src/isp_ae.c +++ b/components/esp_driver_isp/src/isp_ae.c @@ -31,10 +31,6 @@ typedef struct isp_ae_controller_t { void *user_data; } isp_ae_controller_t; -extern portMUX_TYPE fsm_spinlock; - -static void s_isp_ae_default_isr(void *arg); - /*--------------------------------------------- AE ----------------------------------------------*/ @@ -69,10 +65,10 @@ static void s_isp_ae_free_controller(isp_ae_ctlr_t ae_ctlr) esp_intr_free(ae_ctlr->intr_handle); } if (ae_ctlr->evt_que) { - vQueueDelete(ae_ctlr->evt_que); + vQueueDeleteWithCaps(ae_ctlr->evt_que); } if (ae_ctlr->stat_lock) { - vSemaphoreDelete(ae_ctlr->stat_lock); + vSemaphoreDeleteWithCaps(ae_ctlr->stat_lock); } free(ae_ctlr); } @@ -105,10 +101,9 @@ esp_err_t esp_isp_new_ae_controller(isp_proc_handle_t isp_proc, const esp_isp_ae ESP_GOTO_ON_ERROR(s_isp_claim_ae_controller(isp_proc, ae_ctlr), err1, TAG, "no available controller"); // Register the AE ISR - uint32_t intr_st_reg_addr = isp_ll_get_intr_status_reg_addr(isp_proc->hal.hw); - int intr_priority = ae_config->intr_priority > 0 && ae_config->intr_priority <= 7 ? BIT(ae_config->intr_priority) : ESP_INTR_FLAG_LOWMED; - ESP_GOTO_ON_ERROR(esp_intr_alloc_intrstatus(isp_hw_info.instances[isp_proc->proc_id].irq, ISP_INTR_ALLOC_FLAGS | intr_priority, intr_st_reg_addr, ISP_LL_EVENT_AE_MASK, - s_isp_ae_default_isr, ae_ctlr, &ae_ctlr->intr_handle), err2, TAG, "allocate interrupt failed"); + int intr_priority = (ae_config->intr_priority > 0 && ae_config->intr_priority <= 3) ? BIT(ae_config->intr_priority) : ESP_INTR_FLAG_LOWMED; + ESP_GOTO_ON_ERROR(intr_priority != isp_proc->intr_priority, err2, TAG, "intr_priority error"); + ESP_GOTO_ON_ERROR(esp_isp_register_isr(ae_ctlr->isp_proc, ISP_SUBMODULE_AE), err2, TAG, "fail to register ISR"); isp_ll_ae_set_sample_point(isp_proc->hal.hw, ae_config->sample_point); isp_ll_ae_enable(isp_proc->hal.hw, false); @@ -132,8 +127,11 @@ esp_err_t esp_isp_del_ae_controller(isp_ae_ctlr_t ae_ctlr) ESP_RETURN_ON_FALSE(ae_ctlr && ae_ctlr->isp_proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); ESP_RETURN_ON_FALSE(ae_ctlr->isp_proc->ae_ctlr == ae_ctlr, ESP_ERR_INVALID_ARG, TAG, "controller isn't in use"); ESP_RETURN_ON_FALSE(ae_ctlr->fsm == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "controller isn't in init state"); - s_isp_declaim_ae_controller(ae_ctlr); + // Deregister the AE ISR + ESP_RETURN_ON_FALSE(esp_isp_deregister_isr(ae_ctlr->isp_proc, ISP_SUBMODULE_AE) == ESP_OK, ESP_FAIL, TAG, "fail to deregister ISR"); + + s_isp_declaim_ae_controller(ae_ctlr); s_isp_ae_free_controller(ae_ctlr); return ESP_OK; @@ -143,17 +141,14 @@ esp_err_t esp_isp_ae_controller_enable(isp_ae_ctlr_t ae_ctlr) { ESP_RETURN_ON_FALSE(ae_ctlr && ae_ctlr->isp_proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); ESP_RETURN_ON_FALSE(ae_ctlr->fsm == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "controller isn't in init state"); - esp_err_t ret = ESP_OK; - ESP_GOTO_ON_ERROR(esp_intr_enable(ae_ctlr->intr_handle), err, TAG, "failed to enable the AE interrupt"); + isp_ll_ae_clk_enable(ae_ctlr->isp_proc->hal.hw, true); isp_ll_enable_intr(ae_ctlr->isp_proc->hal.hw, ISP_LL_EVENT_AE_MASK, true); isp_ll_ae_enable(ae_ctlr->isp_proc->hal.hw, true); xSemaphoreGive(ae_ctlr->stat_lock); - return ret; -err: - ae_ctlr->fsm = ISP_FSM_INIT; - return ret; + ae_ctlr->fsm = ISP_FSM_ENABLE; + return ESP_OK; } esp_err_t esp_isp_ae_controller_disable(isp_ae_ctlr_t ae_ctlr) @@ -195,9 +190,7 @@ esp_err_t esp_isp_ae_controller_get_oneshot_statistics(isp_ae_ctlr_t ae_ctlr, in // Re-enable the env detector after manual statistics. isp_ll_ae_env_detector_set_thresh(ae_ctlr->isp_proc->hal.hw, ae_ctlr->low_thresh, ae_ctlr->high_thresh); - portENTER_CRITICAL(&fsm_spinlock); ae_ctlr->fsm = ISP_FSM_ENABLE; - portEXIT_CRITICAL(&fsm_spinlock); err: xSemaphoreGive(ae_ctlr->stat_lock); @@ -208,7 +201,6 @@ err: esp_err_t esp_isp_ae_controller_start_continuous_statistics(isp_ae_ctlr_t ae_ctlr) { ESP_RETURN_ON_FALSE_ISR(ae_ctlr, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); - ESP_RETURN_ON_FALSE_ISR(ae_ctlr->fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "controller isn't in enable state"); esp_err_t ret = ESP_OK; if (xSemaphoreTake(ae_ctlr->stat_lock, 0) == pdFALSE) { ESP_LOGW(TAG, "statistics lock is not acquired, controller is busy"); @@ -216,9 +208,7 @@ esp_err_t esp_isp_ae_controller_start_continuous_statistics(isp_ae_ctlr_t ae_ctl } ESP_GOTO_ON_FALSE(ae_ctlr->fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, err, TAG, "controller isn't in enable state"); - portENTER_CRITICAL(&fsm_spinlock); ae_ctlr->fsm = ISP_FSM_START; - portEXIT_CRITICAL(&fsm_spinlock); isp_ll_ae_manual_update(ae_ctlr->isp_proc->hal.hw); @@ -231,11 +221,8 @@ esp_err_t esp_isp_ae_controller_stop_continuous_statistics(isp_ae_ctlr_t ae_ctlr { ESP_RETURN_ON_FALSE_ISR(ae_ctlr, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); ESP_RETURN_ON_FALSE_ISR(ae_ctlr->fsm == ISP_FSM_START, ESP_ERR_INVALID_STATE, TAG, "controller isn't in continuous state"); - isp_ll_ae_env_detector_set_thresh(ae_ctlr->isp_proc->hal.hw, ae_ctlr->low_thresh, ae_ctlr->high_thresh); - portENTER_CRITICAL(&fsm_spinlock); ae_ctlr->fsm = ISP_FSM_ENABLE; - portEXIT_CRITICAL(&fsm_spinlock); xSemaphoreGive(ae_ctlr->stat_lock); return ESP_OK; @@ -297,12 +284,9 @@ esp_err_t esp_isp_ae_controller_set_env_detector_threshold(isp_ae_ctlr_t ae_ctlr /*--------------------------------------------------------------- INTR ---------------------------------------------------------------*/ -static void IRAM_ATTR s_isp_ae_default_isr(void *arg) +bool IRAM_ATTR esp_isp_ae_isr(isp_proc_handle_t proc, uint32_t ae_events) { - isp_ae_ctlr_t ae_ctlr = (isp_ae_ctlr_t)arg; - isp_proc_handle_t proc = ae_ctlr->isp_proc; - - uint32_t ae_events = isp_hal_check_clear_intr_event(&proc->hal, ISP_LL_EVENT_AE_MASK); + isp_ae_ctlr_t ae_ctlr = proc->ae_ctlr; bool need_yield = false; esp_isp_ae_env_detector_evt_data_t edata = {}; @@ -343,8 +327,5 @@ static void IRAM_ATTR s_isp_ae_default_isr(void *arg) need_yield |= ae_ctlr->cbs.on_env_change(ae_ctlr, &edata, ae_ctlr->user_data); } } - - if (need_yield) { - portYIELD_FROM_ISR(); - } + return need_yield; } diff --git a/components/esp_driver_isp/src/isp_af.c b/components/esp_driver_isp/src/isp_af.c index 516d2b22bf..9cef3208c1 100644 --- a/components/esp_driver_isp/src/isp_af.c +++ b/components/esp_driver_isp/src/isp_af.c @@ -28,8 +28,6 @@ typedef struct isp_af_controller_t { void *user_data; } isp_af_controller_t; -static void s_isp_af_default_isr(void *arg); - /*--------------------------------------------- AF ----------------------------------------------*/ @@ -72,7 +70,7 @@ static void s_isp_af_free_controller(isp_af_ctlr_t af_ctlr) esp_intr_free(af_ctlr->intr_handle); } if (af_ctlr->evt_que) { - vQueueDelete(af_ctlr->evt_que); + vQueueDeleteWithCaps(af_ctlr->evt_que); } free(af_ctlr); } @@ -114,10 +112,9 @@ esp_err_t esp_isp_new_af_controller(isp_proc_handle_t isp_proc, const esp_isp_af ESP_GOTO_ON_ERROR(s_isp_claim_af_controller(isp_proc, af_ctlr), err1, TAG, "no available controller"); // Register the AF ISR - uint32_t intr_st_reg_addr = isp_ll_get_intr_status_reg_addr(isp_proc->hal.hw); - int intr_priority = af_config->intr_priority > 0 && af_config->intr_priority <= 7 ? BIT(af_config->intr_priority) : ESP_INTR_FLAG_LOWMED; - ESP_GOTO_ON_ERROR(esp_intr_alloc_intrstatus(isp_hw_info.instances[isp_proc->proc_id].irq, ISP_INTR_ALLOC_FLAGS | intr_priority, intr_st_reg_addr, ISP_LL_EVENT_AF_MASK, - s_isp_af_default_isr, af_ctlr, &af_ctlr->intr_handle), err2, TAG, "allocate interrupt failed"); + int intr_priority = (af_config->intr_priority > 0 && af_config->intr_priority <= 3) ? BIT(af_config->intr_priority) : ESP_INTR_FLAG_LOWMED; + ESP_GOTO_ON_ERROR(intr_priority != isp_proc->intr_priority, err2, TAG, "intr_priority error"); + ESP_GOTO_ON_ERROR(esp_isp_register_isr(af_ctlr->isp_proc, ISP_SUBMODULE_AF), err2, TAG, "fail to register ISR"); isp_ll_af_enable_auto_update(isp_proc->hal.hw, false); isp_ll_af_enable(isp_proc->hal.hw, false); @@ -153,6 +150,10 @@ esp_err_t esp_isp_del_af_controller(isp_af_ctlr_t af_ctlr) } } ESP_RETURN_ON_FALSE(exist, ESP_ERR_INVALID_ARG, TAG, "controller isn't in use"); + + // Deregister the AF ISR + ESP_RETURN_ON_FALSE(esp_isp_deregister_isr(af_ctlr->isp_proc, ISP_SUBMODULE_AF) == ESP_OK, ESP_FAIL, TAG, "fail to deregister ISR"); + s_isp_declaim_af_controller(af_ctlr); s_isp_af_free_controller(af_ctlr); @@ -164,7 +165,6 @@ esp_err_t esp_isp_af_controller_enable(isp_af_ctlr_t af_ctlr) ESP_RETURN_ON_FALSE(af_ctlr && af_ctlr->isp_proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); ESP_RETURN_ON_FALSE(af_ctlr->fsm == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "controller isn't in init state"); - esp_intr_enable(af_ctlr->intr_handle); isp_ll_af_clk_enable(af_ctlr->isp_proc->hal.hw, true); isp_ll_enable_intr(af_ctlr->isp_proc->hal.hw, ISP_LL_EVENT_AF_MASK, true); isp_ll_af_enable(af_ctlr->isp_proc->hal.hw, true); @@ -284,12 +284,9 @@ esp_err_t esp_isp_af_controller_set_env_detector_threshold(isp_af_ctlr_t af_ctrl /*--------------------------------------------------------------- INTR ---------------------------------------------------------------*/ -static void IRAM_ATTR s_isp_af_default_isr(void *arg) +bool IRAM_ATTR esp_isp_af_isr(isp_proc_handle_t proc, uint32_t af_events) { - isp_af_ctlr_t af_ctrlr = (isp_af_ctlr_t)arg; - isp_proc_handle_t proc = af_ctrlr->isp_proc; - - uint32_t af_events = isp_hal_check_clear_intr_event(&proc->hal, ISP_LL_EVENT_AF_MASK); + isp_af_ctlr_t af_ctrlr = proc->af_ctlr[0]; bool need_yield = false; esp_isp_af_env_detector_evt_data_t edata = {}; @@ -323,8 +320,5 @@ static void IRAM_ATTR s_isp_af_default_isr(void *arg) need_yield |= af_ctrlr->cbs.on_env_change(af_ctrlr, &edata, af_ctrlr->user_data); } } - - if (need_yield) { - portYIELD_FROM_ISR(); - } + return need_yield; } diff --git a/components/esp_driver_isp/src/isp_awb.c b/components/esp_driver_isp/src/isp_awb.c index 435515a9a4..fbc22d959c 100644 --- a/components/esp_driver_isp/src/isp_awb.c +++ b/components/esp_driver_isp/src/isp_awb.c @@ -18,7 +18,6 @@ typedef struct isp_awb_controller_t { isp_fsm_t fsm; portMUX_TYPE spinlock; intr_handle_t intr_handle; - int intr_priority; isp_proc_handle_t isp_proc; QueueHandle_t evt_que; SemaphoreHandle_t stat_lock; @@ -28,8 +27,6 @@ typedef struct isp_awb_controller_t { static const char *TAG = "ISP_AWB"; -static void s_isp_awb_default_isr(void *arg); - /*--------------------------------------------- AWB ----------------------------------------------*/ @@ -64,10 +61,10 @@ static void s_isp_awb_free_controller(isp_awb_ctlr_t awb_ctlr) esp_intr_free(awb_ctlr->intr_handle); } if (awb_ctlr->evt_que) { - vQueueDelete(awb_ctlr->evt_que); + vQueueDeleteWithCaps(awb_ctlr->evt_que); } if (awb_ctlr->stat_lock) { - vSemaphoreDelete(awb_ctlr->stat_lock); + vSemaphoreDeleteWithCaps(awb_ctlr->stat_lock); } free(awb_ctlr); } @@ -109,11 +106,11 @@ esp_err_t esp_isp_new_awb_controller(isp_proc_handle_t isp_proc, const esp_isp_a // Claim an AWB controller ESP_GOTO_ON_ERROR(s_isp_claim_awb_controller(isp_proc, awb_ctlr), err1, TAG, "no available controller"); + // Register the AWB ISR - uint32_t intr_st_reg_addr = isp_ll_get_intr_status_reg_addr(isp_proc->hal.hw); - awb_ctlr->intr_priority = awb_cfg->intr_priority > 0 && awb_cfg->intr_priority <= 3 ? BIT(awb_cfg->intr_priority) : ESP_INTR_FLAG_LOWMED; - ESP_GOTO_ON_ERROR(esp_intr_alloc_intrstatus(isp_hw_info.instances[isp_proc->proc_id].irq, ISP_INTR_ALLOC_FLAGS | awb_ctlr->intr_priority, intr_st_reg_addr, ISP_LL_EVENT_AWB_MASK, - s_isp_awb_default_isr, awb_ctlr, &awb_ctlr->intr_handle), err2, TAG, "allocate interrupt failed"); + int intr_priority = (awb_cfg->intr_priority > 0 && awb_cfg->intr_priority <= 3) ? BIT(awb_cfg->intr_priority) : ESP_INTR_FLAG_LOWMED; + ESP_GOTO_ON_ERROR(intr_priority != isp_proc->intr_priority, err2, TAG, "intr_priority error"); + ESP_GOTO_ON_ERROR(esp_isp_register_isr(awb_ctlr->isp_proc, ISP_SUBMODULE_AWB), err2, TAG, "fail to register ISR"); // Configure the hardware isp_ll_awb_enable(isp_proc->hal.hw, false); @@ -137,6 +134,8 @@ esp_err_t esp_isp_del_awb_controller(isp_awb_ctlr_t awb_ctlr) ESP_RETURN_ON_FALSE(awb_ctlr && awb_ctlr->isp_proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); ESP_RETURN_ON_FALSE(awb_ctlr->isp_proc->awb_ctlr == awb_ctlr, ESP_ERR_INVALID_ARG, TAG, "controller isn't in use"); ESP_RETURN_ON_FALSE(awb_ctlr->fsm == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "controller isn't in init state"); + + ESP_RETURN_ON_FALSE(esp_isp_deregister_isr(awb_ctlr->isp_proc, ISP_SUBMODULE_AWB) == ESP_OK, ESP_FAIL, TAG, "fail to deregister ISR"); s_isp_declaim_awb_controller(awb_ctlr); isp_ll_awb_enable_algorithm_mode(awb_ctlr->isp_proc->hal.hw, false); @@ -148,9 +147,6 @@ esp_err_t esp_isp_del_awb_controller(isp_awb_ctlr_t awb_ctlr) esp_err_t esp_isp_awb_controller_reconfig(isp_awb_ctlr_t awb_ctlr, const esp_isp_awb_config_t *awb_cfg) { ESP_RETURN_ON_FALSE(awb_ctlr && awb_cfg, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); - int intr_priority = awb_cfg->intr_priority > 0 && awb_cfg->intr_priority <= 3 ? BIT(awb_cfg->intr_priority) : ESP_INTR_FLAG_LOWMED; - ESP_RETURN_ON_FALSE(intr_priority == awb_ctlr->intr_priority, ESP_ERR_INVALID_ARG, TAG, "can't change interrupt priority after initialized"); - return s_esp_isp_awb_config_hardware(awb_ctlr->isp_proc, awb_cfg); } @@ -161,14 +157,10 @@ esp_err_t esp_isp_awb_controller_enable(isp_awb_ctlr_t awb_ctlr) awb_ctlr->fsm = ISP_FSM_ENABLE; esp_err_t ret = ESP_OK; - ESP_GOTO_ON_ERROR(esp_intr_enable(awb_ctlr->intr_handle), err, TAG, "failed to enable the AWB interrupt"); isp_ll_awb_clk_enable(awb_ctlr->isp_proc->hal.hw, true); isp_ll_enable_intr(awb_ctlr->isp_proc->hal.hw, ISP_LL_EVENT_AWB_MASK, true); xSemaphoreGive(awb_ctlr->stat_lock); - return ret; -err: - awb_ctlr->fsm = ISP_FSM_INIT; return ret; } @@ -245,13 +237,8 @@ esp_err_t esp_isp_awb_controller_stop_continuous_statistics(isp_awb_ctlr_t awb_c /*--------------------------------------------------------------- INTR ---------------------------------------------------------------*/ -static void IRAM_ATTR s_isp_awb_default_isr(void *arg) +bool IRAM_ATTR esp_isp_awb_isr(isp_proc_handle_t proc, uint32_t awb_events) { - isp_awb_ctlr_t awb_ctlr = (isp_awb_ctlr_t)arg; - isp_proc_handle_t proc = awb_ctlr->isp_proc; - - uint32_t awb_events = isp_hal_check_clear_intr_event(&proc->hal, ISP_LL_EVENT_AWB_MASK); - bool need_yield = false; if (awb_events & ISP_LL_EVENT_AWB_FDONE) { @@ -279,10 +266,7 @@ static void IRAM_ATTR s_isp_awb_default_isr(void *arg) isp_ll_awb_enable(awb_ctlr->isp_proc->hal.hw, true); } } - - if (need_yield) { - portYIELD_FROM_ISR(); - } + return need_yield; } esp_err_t esp_isp_awb_register_event_callbacks(isp_awb_ctlr_t awb_ctlr, const esp_isp_awb_cbs_t *cbs, void *user_data) diff --git a/components/esp_driver_isp/src/isp_core.c b/components/esp_driver_isp/src/isp_core.c index 8fbf9e5f66..d9abcf7f1e 100644 --- a/components/esp_driver_isp/src/isp_core.c +++ b/components/esp_driver_isp/src/isp_core.c @@ -89,6 +89,8 @@ esp_err_t esp_isp_new_processor(const esp_isp_processor_cfg_t *proc_config, isp_ ESP_GOTO_ON_ERROR(esp_clk_tree_src_get_freq_hz(clk_src, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &clk_src_freq_hz), err, TAG, "clock source setting fail"); ESP_GOTO_ON_FALSE((proc_config->clk_hz > 0 && proc_config->clk_hz <= clk_src_freq_hz), ESP_ERR_INVALID_ARG, err, TAG, "clk hz not supported"); + proc->intr_priority = (proc_config->intr_priority > 0 && proc_config->intr_priority <= 3) ? BIT(proc_config->intr_priority) : ESP_INTR_FLAG_LOWMED; + uint32_t out_clk_freq_hz = 0; hal_utils_clk_div_t clk_div = {}; hal_utils_clk_info_t clk_info = { @@ -102,7 +104,7 @@ esp_err_t esp_isp_new_processor(const esp_isp_processor_cfg_t *proc_config, isp_ if (out_clk_freq_hz != proc_config->clk_hz) { ESP_LOGW(TAG, "precision loss, real output frequency: %"PRIu32"Hz", out_clk_freq_hz); } - + ; isp_hal_init(&proc->hal, proc->proc_id); PERIPH_RCC_ATOMIC() { isp_ll_select_clk_source(proc->hal.hw, clk_src); @@ -186,3 +188,137 @@ esp_err_t esp_isp_disable(isp_proc_handle_t proc) return ESP_OK; } + +/*--------------------------------------------------------------- + INTR +---------------------------------------------------------------*/ +static void IRAM_ATTR s_isp_isr_dispatcher(void *arg) +{ + isp_processor_t *proc = (isp_processor_t *)arg; + bool need_yield = false; + + //Check and clear hw events + uint32_t af_events = isp_hal_check_clear_intr_event(&proc->hal, ISP_LL_EVENT_AF_MASK); + uint32_t awb_events = isp_hal_check_clear_intr_event(&proc->hal, ISP_LL_EVENT_AWB_MASK); + uint32_t ae_events = isp_hal_check_clear_intr_event(&proc->hal, ISP_LL_EVENT_AE_MASK); + + bool do_dispatch = false; + //Deal with hw events + if (af_events) { + portENTER_CRITICAL_ISR(&proc->spinlock); + do_dispatch = proc->isr_users.af_isr_added; + portEXIT_CRITICAL_ISR(&proc->spinlock); + + if (do_dispatch) { + need_yield |= esp_isp_af_isr(proc, af_events); + } + do_dispatch = false; + } + if (awb_events) { + portENTER_CRITICAL_ISR(&proc->spinlock); + do_dispatch = proc->isr_users.awb_isr_added; + portEXIT_CRITICAL_ISR(&proc->spinlock); + + if (do_dispatch) { + need_yield |= esp_isp_awb_isr(proc, awb_events); + } + do_dispatch = false; + } + if (ae_events) { + portENTER_CRITICAL_ISR(&proc->spinlock); + do_dispatch = proc->isr_users.ae_isr_added; + portEXIT_CRITICAL_ISR(&proc->spinlock); + + if (do_dispatch) { + need_yield |= esp_isp_ae_isr(proc, ae_events); + } + do_dispatch = false; + } + if (need_yield) { + portYIELD_FROM_ISR(); + } +} + +esp_err_t esp_isp_register_isr(isp_proc_handle_t proc, isp_submodule_t submodule) +{ + esp_err_t ret = ESP_FAIL; + ESP_RETURN_ON_FALSE(proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); + + bool do_alloc = false; + portENTER_CRITICAL(&proc->spinlock); + proc->isr_ref_counts++; + if (proc->isr_ref_counts == 1) { + assert(!proc->intr_hdl); + do_alloc = true; + } + + switch (submodule) { + case ISP_SUBMODULE_AF: + proc->isr_users.af_isr_added = true; + break; + case ISP_SUBMODULE_AWB: + proc->isr_users.awb_isr_added = true; + break; + case ISP_SUBMODULE_AE: + proc->isr_users.ae_isr_added = true; + break; + default: + assert(false); + } + portEXIT_CRITICAL(&proc->spinlock); + + if (do_alloc) { + + uint32_t intr_st_reg_addr = isp_ll_get_intr_status_reg_addr(proc->hal.hw); + uint32_t intr_st_mask = ISP_LL_EVENT_AF_MASK | ISP_LL_EVENT_AE_MASK | ISP_LL_EVENT_AWB_MASK; + ret = esp_intr_alloc_intrstatus(isp_hw_info.instances[proc->proc_id].irq, ISP_INTR_ALLOC_FLAGS | proc->intr_priority, intr_st_reg_addr, intr_st_mask, + s_isp_isr_dispatcher, (void *)proc, &proc->intr_hdl); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "no intr source"); + return ret; + } + esp_intr_enable(proc->intr_hdl); + } + + return ESP_OK; +} + +esp_err_t esp_isp_deregister_isr(isp_proc_handle_t proc, isp_submodule_t submodule) +{ + esp_err_t ret = ESP_FAIL; + ESP_RETURN_ON_FALSE(proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); + + bool do_free = false; + portENTER_CRITICAL(&proc->spinlock); + proc->isr_ref_counts--; + assert(proc->isr_ref_counts >= 0); + if (proc->isr_ref_counts == 0) { + assert(proc->intr_hdl); + do_free = true; + } + + switch (submodule) { + case ISP_SUBMODULE_AF: + proc->isr_users.af_isr_added = false; + break; + case ISP_SUBMODULE_AWB: + proc->isr_users.awb_isr_added = false; + break; + case ISP_SUBMODULE_AE: + proc->isr_users.ae_isr_added = false; + break; + default: + assert(false); + } + portEXIT_CRITICAL(&proc->spinlock); + + if (do_free) { + esp_intr_disable(proc->intr_hdl); + ret = esp_intr_free(proc->intr_hdl); + if (ret != ESP_OK) { + return ret; + } + } + + return ESP_OK; +} 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 6bfef09784..5a583c13bc 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 @@ -187,7 +187,7 @@ TEST_CASE("ISP AE driver basic function", "[isp]") isp_ae_ctlr_t ae_ctlr = NULL; /* Default parameters from helper macro */ esp_isp_ae_config_t ae_config = { - .ae_sample_point = ISP_AE_SAMPLE_POINT_AFTER_DEMOSAIC, + .sample_point = ISP_AE_SAMPLE_POINT_AFTER_DEMOSAIC, }; isp_ae_result_t ae_res = {}; /* Create the ae controller */ @@ -230,7 +230,7 @@ TEST_CASE("ISP AE controller exhausted allocation", "[isp]") TEST_ESP_OK(esp_isp_new_processor(&isp_config, &isp_proc)); esp_isp_ae_config_t ae_config = { - .ae_sample_point = ISP_AE_SAMPLE_POINT_AFTER_DEMOSAIC, + .sample_point = ISP_AE_SAMPLE_POINT_AFTER_DEMOSAIC, }; isp_ae_ctlr_t ae_ctrlr[SOC_ISP_AE_CTLR_NUMS + 1] = {}; for (int i = 0; i < SOC_ISP_AE_CTLR_NUMS; i++) {