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 { 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_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 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; } esp_isp_ae_config_t;
/** /**

View File

@@ -21,7 +21,7 @@ extern "C" {
typedef struct { typedef struct {
isp_window_t window[ISP_AF_WINDOW_NUM]; ///< The sampling windows of AF 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 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; } esp_isp_af_config_t;
/** /**

View File

@@ -28,6 +28,7 @@ typedef struct {
bool has_line_end_packet; ///< Enable line end packet 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 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 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; } esp_isp_processor_cfg_t;
/** /**

View File

@@ -32,10 +32,10 @@ extern "C" {
#endif #endif
#if CONFIG_ISP_ISR_IRAM_SAFE #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) #define ISP_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
#else #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 #define ISP_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT
#endif #endif
@@ -67,9 +67,34 @@ typedef struct isp_processor_t {
isp_awb_ctlr_t awb_ctlr; isp_awb_ctlr_t awb_ctlr;
isp_fsm_t bf_fsm; isp_fsm_t bf_fsm;
isp_ae_ctlr_t ae_ctlr; 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; } isp_processor_t;
#endif #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 #ifdef __cplusplus
} }
#endif #endif

View File

@@ -31,10 +31,6 @@ typedef struct isp_ae_controller_t {
void *user_data; void *user_data;
} isp_ae_controller_t; } isp_ae_controller_t;
extern portMUX_TYPE fsm_spinlock;
static void s_isp_ae_default_isr(void *arg);
/*--------------------------------------------- /*---------------------------------------------
AE 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); esp_intr_free(ae_ctlr->intr_handle);
} }
if (ae_ctlr->evt_que) { if (ae_ctlr->evt_que) {
vQueueDelete(ae_ctlr->evt_que); vQueueDeleteWithCaps(ae_ctlr->evt_que);
} }
if (ae_ctlr->stat_lock) { if (ae_ctlr->stat_lock) {
vSemaphoreDelete(ae_ctlr->stat_lock); vSemaphoreDeleteWithCaps(ae_ctlr->stat_lock);
} }
free(ae_ctlr); 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"); ESP_GOTO_ON_ERROR(s_isp_claim_ae_controller(isp_proc, ae_ctlr), err1, TAG, "no available controller");
// Register the AE ISR // 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 <= 3) ? BIT(ae_config->intr_priority) : ESP_INTR_FLAG_LOWMED;
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(intr_priority != isp_proc->intr_priority, err2, TAG, "intr_priority error");
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, ESP_GOTO_ON_ERROR(esp_isp_register_isr(ae_ctlr->isp_proc, ISP_SUBMODULE_AE), err2, TAG, "fail to register ISR");
s_isp_ae_default_isr, ae_ctlr, &ae_ctlr->intr_handle), err2, TAG, "allocate interrupt failed");
isp_ll_ae_set_sample_point(isp_proc->hal.hw, ae_config->sample_point); isp_ll_ae_set_sample_point(isp_proc->hal.hw, ae_config->sample_point);
isp_ll_ae_enable(isp_proc->hal.hw, false); 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 && 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->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"); 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); s_isp_ae_free_controller(ae_ctlr);
return ESP_OK; 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 && 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_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_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_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); isp_ll_ae_enable(ae_ctlr->isp_proc->hal.hw, true);
xSemaphoreGive(ae_ctlr->stat_lock); xSemaphoreGive(ae_ctlr->stat_lock);
return ret; ae_ctlr->fsm = ISP_FSM_ENABLE;
err: return ESP_OK;
ae_ctlr->fsm = ISP_FSM_INIT;
return ret;
} }
esp_err_t esp_isp_ae_controller_disable(isp_ae_ctlr_t ae_ctlr) 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. // 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); 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; ae_ctlr->fsm = ISP_FSM_ENABLE;
portEXIT_CRITICAL(&fsm_spinlock);
err: err:
xSemaphoreGive(ae_ctlr->stat_lock); 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_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, 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; esp_err_t ret = ESP_OK;
if (xSemaphoreTake(ae_ctlr->stat_lock, 0) == pdFALSE) { if (xSemaphoreTake(ae_ctlr->stat_lock, 0) == pdFALSE) {
ESP_LOGW(TAG, "statistics lock is not acquired, controller is busy"); 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"); 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; ae_ctlr->fsm = ISP_FSM_START;
portEXIT_CRITICAL(&fsm_spinlock);
isp_ll_ae_manual_update(ae_ctlr->isp_proc->hal.hw); 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, 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"); 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; ae_ctlr->fsm = ISP_FSM_ENABLE;
portEXIT_CRITICAL(&fsm_spinlock);
xSemaphoreGive(ae_ctlr->stat_lock); xSemaphoreGive(ae_ctlr->stat_lock);
return ESP_OK; 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 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_ae_ctlr_t ae_ctlr = proc->ae_ctlr;
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);
bool need_yield = false; bool need_yield = false;
esp_isp_ae_env_detector_evt_data_t edata = {}; 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); need_yield |= ae_ctlr->cbs.on_env_change(ae_ctlr, &edata, ae_ctlr->user_data);
} }
} }
return need_yield;
if (need_yield) {
portYIELD_FROM_ISR();
}
} }

View File

@@ -28,8 +28,6 @@ typedef struct isp_af_controller_t {
void *user_data; void *user_data;
} isp_af_controller_t; } isp_af_controller_t;
static void s_isp_af_default_isr(void *arg);
/*--------------------------------------------- /*---------------------------------------------
AF 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); esp_intr_free(af_ctlr->intr_handle);
} }
if (af_ctlr->evt_que) { if (af_ctlr->evt_que) {
vQueueDelete(af_ctlr->evt_que); vQueueDeleteWithCaps(af_ctlr->evt_que);
} }
free(af_ctlr); 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"); ESP_GOTO_ON_ERROR(s_isp_claim_af_controller(isp_proc, af_ctlr), err1, TAG, "no available controller");
// Register the AF ISR // 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 <= 3) ? BIT(af_config->intr_priority) : ESP_INTR_FLAG_LOWMED;
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(intr_priority != isp_proc->intr_priority, err2, TAG, "intr_priority error");
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, ESP_GOTO_ON_ERROR(esp_isp_register_isr(af_ctlr->isp_proc, ISP_SUBMODULE_AF), err2, TAG, "fail to register ISR");
s_isp_af_default_isr, af_ctlr, &af_ctlr->intr_handle), err2, TAG, "allocate interrupt failed");
isp_ll_af_enable_auto_update(isp_proc->hal.hw, false); isp_ll_af_enable_auto_update(isp_proc->hal.hw, false);
isp_ll_af_enable(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"); 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_declaim_af_controller(af_ctlr);
s_isp_af_free_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 && 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_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_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_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); 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 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_af_ctlr_t af_ctrlr = proc->af_ctlr[0];
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);
bool need_yield = false; bool need_yield = false;
esp_isp_af_env_detector_evt_data_t edata = {}; 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); need_yield |= af_ctrlr->cbs.on_env_change(af_ctrlr, &edata, af_ctrlr->user_data);
} }
} }
return need_yield;
if (need_yield) {
portYIELD_FROM_ISR();
}
} }

View File

@@ -18,7 +18,6 @@ typedef struct isp_awb_controller_t {
isp_fsm_t fsm; isp_fsm_t fsm;
portMUX_TYPE spinlock; portMUX_TYPE spinlock;
intr_handle_t intr_handle; intr_handle_t intr_handle;
int intr_priority;
isp_proc_handle_t isp_proc; isp_proc_handle_t isp_proc;
QueueHandle_t evt_que; QueueHandle_t evt_que;
SemaphoreHandle_t stat_lock; SemaphoreHandle_t stat_lock;
@@ -28,8 +27,6 @@ typedef struct isp_awb_controller_t {
static const char *TAG = "ISP_AWB"; static const char *TAG = "ISP_AWB";
static void s_isp_awb_default_isr(void *arg);
/*--------------------------------------------- /*---------------------------------------------
AWB 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); esp_intr_free(awb_ctlr->intr_handle);
} }
if (awb_ctlr->evt_que) { if (awb_ctlr->evt_que) {
vQueueDelete(awb_ctlr->evt_que); vQueueDeleteWithCaps(awb_ctlr->evt_que);
} }
if (awb_ctlr->stat_lock) { if (awb_ctlr->stat_lock) {
vSemaphoreDelete(awb_ctlr->stat_lock); vSemaphoreDeleteWithCaps(awb_ctlr->stat_lock);
} }
free(awb_ctlr); 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 // Claim an AWB controller
ESP_GOTO_ON_ERROR(s_isp_claim_awb_controller(isp_proc, awb_ctlr), err1, TAG, "no available controller"); ESP_GOTO_ON_ERROR(s_isp_claim_awb_controller(isp_proc, awb_ctlr), err1, TAG, "no available controller");
// Register the AWB ISR // Register the AWB ISR
uint32_t intr_st_reg_addr = isp_ll_get_intr_status_reg_addr(isp_proc->hal.hw); int intr_priority = (awb_cfg->intr_priority > 0 && awb_cfg->intr_priority <= 3) ? BIT(awb_cfg->intr_priority) : ESP_INTR_FLAG_LOWMED;
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(intr_priority != isp_proc->intr_priority, err2, TAG, "intr_priority error");
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, ESP_GOTO_ON_ERROR(esp_isp_register_isr(awb_ctlr->isp_proc, ISP_SUBMODULE_AWB), err2, TAG, "fail to register ISR");
s_isp_awb_default_isr, awb_ctlr, &awb_ctlr->intr_handle), err2, TAG, "allocate interrupt failed");
// Configure the hardware // Configure the hardware
isp_ll_awb_enable(isp_proc->hal.hw, false); 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 && 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->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(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); s_isp_declaim_awb_controller(awb_ctlr);
isp_ll_awb_enable_algorithm_mode(awb_ctlr->isp_proc->hal.hw, false); 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_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"); 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); 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; awb_ctlr->fsm = ISP_FSM_ENABLE;
esp_err_t ret = ESP_OK; 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_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); isp_ll_enable_intr(awb_ctlr->isp_proc->hal.hw, ISP_LL_EVENT_AWB_MASK, true);
xSemaphoreGive(awb_ctlr->stat_lock); xSemaphoreGive(awb_ctlr->stat_lock);
return ret;
err:
awb_ctlr->fsm = ISP_FSM_INIT;
return ret; return ret;
} }
@@ -245,13 +237,8 @@ esp_err_t esp_isp_awb_controller_stop_continuous_statistics(isp_awb_ctlr_t awb_c
/*--------------------------------------------------------------- /*---------------------------------------------------------------
INTR 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; bool need_yield = false;
if (awb_events & ISP_LL_EVENT_AWB_FDONE) { 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); isp_ll_awb_enable(awb_ctlr->isp_proc->hal.hw, true);
} }
} }
return need_yield;
if (need_yield) {
portYIELD_FROM_ISR();
}
} }
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) 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_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"); 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; uint32_t out_clk_freq_hz = 0;
hal_utils_clk_div_t clk_div = {}; hal_utils_clk_div_t clk_div = {};
hal_utils_clk_info_t clk_info = { 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) { if (out_clk_freq_hz != proc_config->clk_hz) {
ESP_LOGW(TAG, "precision loss, real output frequency: %"PRIu32"Hz", out_clk_freq_hz); ESP_LOGW(TAG, "precision loss, real output frequency: %"PRIu32"Hz", out_clk_freq_hz);
} }
;
isp_hal_init(&proc->hal, proc->proc_id); isp_hal_init(&proc->hal, proc->proc_id);
PERIPH_RCC_ATOMIC() { PERIPH_RCC_ATOMIC() {
isp_ll_select_clk_source(proc->hal.hw, clk_src); 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; 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; isp_ae_ctlr_t ae_ctlr = NULL;
/* Default parameters from helper macro */ /* Default parameters from helper macro */
esp_isp_ae_config_t ae_config = { 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 = {}; isp_ae_result_t ae_res = {};
/* Create the ae controller */ /* 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)); TEST_ESP_OK(esp_isp_new_processor(&isp_config, &isp_proc));
esp_isp_ae_config_t ae_config = { 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] = {}; isp_ae_ctlr_t ae_ctrlr[SOC_ISP_AE_CTLR_NUMS + 1] = {};
for (int i = 0; i < SOC_ISP_AE_CTLR_NUMS; i++) { for (int i = 0; i < SOC_ISP_AE_CTLR_NUMS; i++) {