mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-03 03:31:41 +03:00
feat(ana_cmpr): supported analog comparator on esp32p4
This commit is contained in:
@@ -35,6 +35,7 @@ struct ana_cmpr_t {
|
||||
bool is_enabled; /*!< Whether the Analog comparator unit is enabled */
|
||||
ana_cmpr_event_callbacks_t cbs; /*!< The callback group that set by user */
|
||||
intr_handle_t intr_handle; /*!< Interrupt handle */
|
||||
uint32_t intr_mask; /*!< Interrupt mask */
|
||||
void *user_data; /*!< User data that passed to the callbacks */
|
||||
uint32_t src_clk_freq_hz; /*!< Source clock frequency of the Analog Comparator unit */
|
||||
esp_pm_lock_handle_t pm_lock; /*!< The Power Management lock that used to avoid unexpected power down of the clock domain */
|
||||
@@ -76,7 +77,14 @@ static void IRAM_ATTR s_ana_cmpr_default_intr_handler(void *usr_data)
|
||||
analog_cmpr_ll_clear_intr(cmpr_handle->dev, status);
|
||||
|
||||
/* Call the user callback function if it is specified and the corresponding event triggers*/
|
||||
if (cmpr_handle->cbs.on_cross && (status & ANALOG_CMPR_LL_EVENT_CROSS)) {
|
||||
if (cmpr_handle->cbs.on_cross && (status & cmpr_handle->intr_mask)) {
|
||||
#if SOC_ANA_CMPR_SUPPORT_MULTI_INTR
|
||||
if (status & ANALOG_CMPR_LL_POS_CROSS_MASK(cmpr_handle->unit)) {
|
||||
evt_data.cross_type = ANA_CMPR_CROSS_POS;
|
||||
} else if (status & ANALOG_CMPR_LL_NEG_CROSS_MASK(cmpr_handle->unit)) {
|
||||
evt_data.cross_type = ANA_CMPR_CROSS_NEG;
|
||||
}
|
||||
#endif // SOC_ANA_CMPR_SUPPORT_MULTI_INTR
|
||||
need_yield = cmpr_handle->cbs.on_cross(cmpr_handle, &evt_data, cmpr_handle->user_data);
|
||||
}
|
||||
if (need_yield) {
|
||||
@@ -102,7 +110,7 @@ esp_err_t ana_cmpr_new_unit(const ana_cmpr_config_t *config, ana_cmpr_handle_t *
|
||||
ESP_RETURN_ON_FALSE(s_ana_cmpr[unit], ESP_ERR_NO_MEM, TAG, "no memory for analog comparator struct");
|
||||
|
||||
/* Assign analog comparator unit */
|
||||
s_ana_cmpr[unit]->dev = ANALOG_CMPR_LL_GET_HW();
|
||||
s_ana_cmpr[unit]->dev = ANALOG_CMPR_LL_GET_HW(unit);
|
||||
s_ana_cmpr[unit]->ref_src = config->ref_src;
|
||||
s_ana_cmpr[unit]->is_enabled = false;
|
||||
s_ana_cmpr[unit]->pm_lock = NULL;
|
||||
@@ -126,12 +134,15 @@ esp_err_t ana_cmpr_new_unit(const ana_cmpr_config_t *config, ana_cmpr_handle_t *
|
||||
/* Configure the register */
|
||||
portENTER_CRITICAL(&s_spinlock);
|
||||
analog_cmpr_ll_set_ref_source(s_ana_cmpr[unit]->dev, config->ref_src);
|
||||
#if !SOC_ANA_CMPR_SUPPORT_MULTI_INTR
|
||||
analog_cmpr_ll_set_cross_type(s_ana_cmpr[unit]->dev, config->cross_type);
|
||||
#endif // SOC_ANA_CMPR_SUPPORT_MULTI_INTR
|
||||
portEXIT_CRITICAL(&s_spinlock);
|
||||
|
||||
/* Allocate the interrupt, currently the interrupt source of Analog Comparator is shared with GPIO interrupt source */
|
||||
ESP_GOTO_ON_ERROR(esp_intr_alloc_intrstatus(ETS_GPIO_INTR_SOURCE, ANA_CMPR_INTR_FLAG, (uint32_t)analog_cmpr_ll_get_intr_status_reg(s_ana_cmpr[unit]->dev),
|
||||
ANALOG_CMPR_LL_EVENT_CROSS, s_ana_cmpr_default_intr_handler, s_ana_cmpr[unit], &s_ana_cmpr[unit]->intr_handle),
|
||||
s_ana_cmpr[unit]->intr_mask = analog_cmpr_ll_get_intr_mask_by_type(s_ana_cmpr[unit]->dev, config->cross_type);
|
||||
ESP_GOTO_ON_ERROR(esp_intr_alloc_intrstatus(ana_cmpr_io_map[unit].intr_src, ANA_CMPR_INTR_FLAG, (uint32_t)analog_cmpr_ll_get_intr_status_reg(s_ana_cmpr[unit]->dev),
|
||||
s_ana_cmpr[unit]->intr_mask, s_ana_cmpr_default_intr_handler, s_ana_cmpr[unit], &s_ana_cmpr[unit]->intr_handle),
|
||||
err, TAG, "allocate interrupt failed");
|
||||
|
||||
if (config->ref_src == ANA_CMPR_REF_SRC_INTERNAL) {
|
||||
@@ -224,7 +235,10 @@ esp_err_t ana_cmpr_set_cross_type(ana_cmpr_handle_t cmpr, ana_cmpr_cross_type_t
|
||||
ESP_ERR_INVALID_ARG, TAG, "invalid cross type");
|
||||
|
||||
portENTER_CRITICAL_SAFE(&s_spinlock);
|
||||
#if !SOC_ANA_CMPR_SUPPORT_MULTI_INTR
|
||||
analog_cmpr_ll_set_cross_type(cmpr->dev, cross_type);
|
||||
#endif
|
||||
cmpr->intr_mask = analog_cmpr_ll_get_intr_mask_by_type(cmpr->dev, cross_type);
|
||||
portEXIT_CRITICAL_SAFE(&s_spinlock);
|
||||
|
||||
ESP_EARLY_LOGD(TAG, "unit %d cross type updated to %d", (int)cmpr->unit, cross_type);
|
||||
@@ -273,7 +287,7 @@ esp_err_t ana_cmpr_enable(ana_cmpr_handle_t cmpr)
|
||||
|
||||
/* Enable the Analog Comparator */
|
||||
portENTER_CRITICAL(&s_spinlock);
|
||||
analog_cmpr_ll_enable_intr(cmpr->dev, ANALOG_CMPR_LL_EVENT_CROSS, !!(cmpr->cbs.on_cross));
|
||||
analog_cmpr_ll_enable_intr(cmpr->dev, cmpr->intr_mask, true);
|
||||
analog_cmpr_ll_enable(cmpr->dev, true);
|
||||
portEXIT_CRITICAL(&s_spinlock);
|
||||
|
||||
@@ -289,7 +303,7 @@ esp_err_t ana_cmpr_disable(ana_cmpr_handle_t cmpr)
|
||||
"the analog comparator not enabled yet");
|
||||
/* Disable the Analog Comparator */
|
||||
portENTER_CRITICAL(&s_spinlock);
|
||||
analog_cmpr_ll_enable_intr(cmpr->dev, ANALOG_CMPR_LL_EVENT_CROSS, false);
|
||||
analog_cmpr_ll_enable_intr(cmpr->dev, cmpr->intr_mask, false);
|
||||
analog_cmpr_ll_enable(cmpr->dev, false);
|
||||
portEXIT_CRITICAL(&s_spinlock);
|
||||
|
||||
|
||||
@@ -90,7 +90,10 @@ typedef int ana_cmpr_clk_src_t;
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
// No data for now
|
||||
#if SOC_ANA_CMPR_SUPPORT_MULTI_INTR
|
||||
ana_cmpr_cross_type_t cross_type; /*!< The cross type of the target signal to the reference signal.
|
||||
* Will either be ANA_CMPR_CROSS_POS or ANA_CMPR_CROSS_NEG */
|
||||
#endif
|
||||
} ana_cmpr_cross_event_data_t;
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user