diff --git a/components/esp_driver_pcnt/src/pulse_cnt.c b/components/esp_driver_pcnt/src/pulse_cnt.c index f7b95fe215..f9cc421ff2 100644 --- a/components/esp_driver_pcnt/src/pulse_cnt.c +++ b/components/esp_driver_pcnt/src/pulse_cnt.c @@ -51,8 +51,6 @@ #define PCNT_ALLOW_INTR_PRIORITY_MASK ESP_INTR_FLAG_LOWMED -#define PCNT_PM_LOCK_NAME_LEN_MAX 16 - #if !SOC_RCC_IS_INDEPENDENT #define PCNT_RCC_ATOMIC() PERIPH_RCC_ATOMIC() #else @@ -85,6 +83,9 @@ struct pcnt_group_t { portMUX_TYPE spinlock; // to protect per-group register level concurrent access pcnt_hal_context_t hal; pcnt_unit_t *units[SOC_PCNT_UNITS_PER_GROUP]; // array of PCNT units +#if CONFIG_PM_ENABLE + esp_pm_lock_handle_t pm_lock; // power management lock +#endif }; typedef struct { @@ -119,10 +120,6 @@ struct pcnt_unit_t { pcnt_chan_t *channels[SOC_PCNT_CHANNELS_PER_UNIT]; // array of PCNT channels pcnt_watch_point_t watchers[PCNT_LL_WATCH_EVENT_MAX]; // array of PCNT watchers intr_handle_t intr; // interrupt handle - esp_pm_lock_handle_t pm_lock; // PM lock, for glitch filter, as that module can only be functional under APB -#if CONFIG_PM_ENABLE - char pm_lock_name[PCNT_PM_LOCK_NAME_LEN_MAX]; // pm lock name -#endif pcnt_unit_fsm_t fsm; // record PCNT unit's driver state pcnt_watch_cb_t on_reach; // user registered callback function void *user_data; // user data registered by user, which would be passed to the right callback function @@ -191,9 +188,6 @@ static void pcnt_unregister_from_group(pcnt_unit_t *unit) static esp_err_t pcnt_destroy(pcnt_unit_t *unit) { - if (unit->pm_lock) { - ESP_RETURN_ON_ERROR(esp_pm_lock_delete(unit->pm_lock), TAG, "delete pm lock failed"); - } if (unit->intr) { ESP_RETURN_ON_ERROR(esp_intr_free(unit->intr), TAG, "delete interrupt service failed"); } @@ -206,9 +200,6 @@ static esp_err_t pcnt_destroy(pcnt_unit_t *unit) esp_err_t pcnt_new_unit(const pcnt_unit_config_t *config, pcnt_unit_handle_t *ret_unit) { -#if CONFIG_PCNT_ENABLE_DEBUG_LOG - esp_log_level_set(TAG, ESP_LOG_DEBUG); -#endif esp_err_t ret = ESP_OK; pcnt_unit_t *unit = NULL; ESP_GOTO_ON_FALSE(config && ret_unit, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); @@ -263,14 +254,6 @@ esp_err_t pcnt_new_unit(const pcnt_unit_config_t *config, pcnt_unit_handle_t *re TAG, "install interrupt service failed"); } - // PCNT uses the APB as its function clock, - // and its filter module is sensitive to the clock frequency -#if CONFIG_PM_ENABLE - sprintf(unit->pm_lock_name, "pcnt_%d_%d", group_id, unit_id); // e.g. pcnt_0_0 - ESP_GOTO_ON_ERROR(esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, unit->pm_lock_name, &unit->pm_lock), err, TAG, "install pm lock failed"); - ESP_LOGD(TAG, "install APB_FREQ_MAX lock for unit (%d,%d)", group_id, unit_id); -#endif - // some events are enabled by default, disable them all pcnt_ll_disable_all_events(group->hal.dev, unit_id); // disable filter by default @@ -423,10 +406,12 @@ esp_err_t pcnt_unit_enable(pcnt_unit_handle_t unit) ESP_RETURN_ON_FALSE(unit, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); ESP_RETURN_ON_FALSE(unit->fsm == PCNT_UNIT_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "unit not in init state"); +#if CONFIG_PM_ENABLE // acquire power manager lock - if (unit->pm_lock) { - ESP_RETURN_ON_ERROR(esp_pm_lock_acquire(unit->pm_lock), TAG, "acquire pm_lock failed"); + if (unit->group->pm_lock) { + ESP_RETURN_ON_ERROR(esp_pm_lock_acquire(unit->group->pm_lock), TAG, "acquire pm_lock failed"); } +#endif // enable interrupt service if (unit->intr) { ESP_RETURN_ON_ERROR(esp_intr_enable(unit->intr), TAG, "enable interrupt service failed"); @@ -445,10 +430,12 @@ esp_err_t pcnt_unit_disable(pcnt_unit_handle_t unit) if (unit->intr) { ESP_RETURN_ON_ERROR(esp_intr_disable(unit->intr), TAG, "disable interrupt service failed"); } +#if CONFIG_PM_ENABLE // release power manager lock - if (unit->pm_lock) { - ESP_RETURN_ON_ERROR(esp_pm_lock_release(unit->pm_lock), TAG, "release APB_FREQ_MAX lock failed"); + if (unit->group->pm_lock) { + ESP_RETURN_ON_ERROR(esp_pm_lock_release(unit->group->pm_lock), TAG, "release APB_FREQ_MAX lock failed"); } +#endif unit->fsm = PCNT_UNIT_FSM_INIT; return ESP_OK; @@ -966,6 +953,14 @@ static pcnt_group_t *pcnt_acquire_group_handle(int group_id) _lock_release(&s_platform.mutex); if (new_group) { +#if CONFIG_PM_ENABLE + // PCNT uses the APB as its function clock, + // and its filter module is sensitive to the clock frequency + // thus we choose the APM_MAX lock to prevent the function clock from being changed + if (esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, pcnt_periph_signals.groups[group_id].module_name, &group->pm_lock) != ESP_OK) { + ESP_LOGW(TAG, "create pm lock failed"); + } +#endif ESP_LOGD(TAG, "new group (%d) at %p", group_id, group); } @@ -986,16 +981,21 @@ static void pcnt_release_group_handle(pcnt_group_t *group) PCNT_RCC_ATOMIC() { pcnt_ll_enable_bus_clock(group_id, false); } - } - _lock_release(&s_platform.mutex); - - if (do_deinitialize) { #if PCNT_USE_RETENTION_LINK const periph_retention_module_t module_id = pcnt_reg_retention_info[group_id].retention_module; if (sleep_retention_is_module_inited(module_id)) { sleep_retention_module_deinit(module_id); } #endif // PCNT_USE_RETENTION_LINK + } + _lock_release(&s_platform.mutex); + + if (do_deinitialize) { +#if CONFIG_PM_ENABLE + if (group->pm_lock) { + esp_pm_lock_delete(group->pm_lock); + } +#endif free(group); ESP_LOGD(TAG, "del group (%d)", group_id); } @@ -1122,3 +1122,11 @@ static esp_err_t pcnt_create_sleep_retention_link_cb(void *arg) return ESP_OK; } #endif // PCNT_USE_RETENTION_LINK + +#if CONFIG_PCNT_ENABLE_DEBUG_LOG +__attribute__((constructor)) +static void pcnt_override_default_log_level(void) +{ + esp_log_level_set(TAG, ESP_LOG_VERBOSE); +} +#endif diff --git a/components/soc/esp32/pcnt_periph.c b/components/soc/esp32/pcnt_periph.c index f413c0b0ab..9fbdce0113 100644 --- a/components/soc/esp32/pcnt_periph.c +++ b/components/soc/esp32/pcnt_periph.c @@ -12,6 +12,7 @@ const pcnt_signal_conn_t pcnt_periph_signals = { .groups = { [0] = { .irq = ETS_PCNT_INTR_SOURCE, + .module_name = "pcnt0", .units = { [0] = { .channels = { diff --git a/components/soc/esp32c5/pcnt_periph.c b/components/soc/esp32c5/pcnt_periph.c index 834053942f..ca8c899a69 100644 --- a/components/soc/esp32c5/pcnt_periph.c +++ b/components/soc/esp32c5/pcnt_periph.c @@ -12,6 +12,7 @@ const pcnt_signal_conn_t pcnt_periph_signals = { .groups = { [0] = { .irq = ETS_PCNT_INTR_SOURCE, + .module_name = "pcnt0", .units = { [0] = { .channels = { diff --git a/components/soc/esp32c6/pcnt_periph.c b/components/soc/esp32c6/pcnt_periph.c index 5fee4252ff..a7e8ccd5f2 100644 --- a/components/soc/esp32c6/pcnt_periph.c +++ b/components/soc/esp32c6/pcnt_periph.c @@ -12,6 +12,7 @@ const pcnt_signal_conn_t pcnt_periph_signals = { .groups = { [0] = { .irq = ETS_PCNT_INTR_SOURCE, + .module_name = "pcnt0", .units = { [0] = { .channels = { diff --git a/components/soc/esp32h2/pcnt_periph.c b/components/soc/esp32h2/pcnt_periph.c index 5fee4252ff..a7e8ccd5f2 100644 --- a/components/soc/esp32h2/pcnt_periph.c +++ b/components/soc/esp32h2/pcnt_periph.c @@ -12,6 +12,7 @@ const pcnt_signal_conn_t pcnt_periph_signals = { .groups = { [0] = { .irq = ETS_PCNT_INTR_SOURCE, + .module_name = "pcnt0", .units = { [0] = { .channels = { diff --git a/components/soc/esp32p4/pcnt_periph.c b/components/soc/esp32p4/pcnt_periph.c index d10e7974fa..7e159c7d32 100644 --- a/components/soc/esp32p4/pcnt_periph.c +++ b/components/soc/esp32p4/pcnt_periph.c @@ -12,6 +12,7 @@ const pcnt_signal_conn_t pcnt_periph_signals = { .groups = { [0] = { .irq = ETS_PCNT_INTR_SOURCE, + .module_name = "pcnt0", .units = { [0] = { .channels = { diff --git a/components/soc/esp32s2/pcnt_periph.c b/components/soc/esp32s2/pcnt_periph.c index b2b440245b..bff39a4713 100644 --- a/components/soc/esp32s2/pcnt_periph.c +++ b/components/soc/esp32s2/pcnt_periph.c @@ -11,6 +11,7 @@ const pcnt_signal_conn_t pcnt_periph_signals = { .groups = { [0] = { .irq = ETS_PCNT_INTR_SOURCE, + .module_name = "pcnt0", .units = { [0] = { .channels = { diff --git a/components/soc/esp32s3/pcnt_periph.c b/components/soc/esp32s3/pcnt_periph.c index b2b440245b..bff39a4713 100644 --- a/components/soc/esp32s3/pcnt_periph.c +++ b/components/soc/esp32s3/pcnt_periph.c @@ -11,6 +11,7 @@ const pcnt_signal_conn_t pcnt_periph_signals = { .groups = { [0] = { .irq = ETS_PCNT_INTR_SOURCE, + .module_name = "pcnt0", .units = { [0] = { .channels = { diff --git a/components/soc/include/soc/pcnt_periph.h b/components/soc/include/soc/pcnt_periph.h index a060af597f..59234607cd 100644 --- a/components/soc/include/soc/pcnt_periph.h +++ b/components/soc/include/soc/pcnt_periph.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -22,6 +22,7 @@ extern "C" { typedef struct { struct { + const char *module_name; struct { struct { const uint32_t pulse_sig;