feat(isp): ISP dispatched ISRs together

This commit is contained in:
gaoxu
2024-07-18 20:11:07 +08:00
parent cb6ecc470c
commit c88ba68cb0
9 changed files with 205 additions and 84 deletions

View File

@@ -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;
/**

View File

@@ -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;
/**

View File

@@ -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;
/**

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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++) {