From 587583cc5f3b16891365c06d1704919db5f3dda2 Mon Sep 17 00:00:00 2001 From: Chen Jichang Date: Tue, 29 Jul 2025 17:38:19 +0800 Subject: [PATCH 1/2] remove(pcnt): remove unused retention reg --- components/esp_driver_pcnt/src/pulse_cnt.c | 41 +++---------------- .../pulse_cnt/main/test_pulse_cnt_sleep.c | 4 +- .../esp_hw_support/sleep_system_peripheral.c | 4 -- .../esp32c5/include/soc/Kconfig.soc_caps.in | 4 -- .../include/soc/retention_periph_defs.h | 4 +- components/soc/esp32c5/include/soc/soc_caps.h | 1 - components/soc/esp32c5/pcnt_periph.c | 32 +-------------- .../esp32c6/include/soc/Kconfig.soc_caps.in | 4 -- .../include/soc/retention_periph_defs.h | 4 +- components/soc/esp32c6/include/soc/soc_caps.h | 1 - components/soc/esp32c6/pcnt_periph.c | 31 +------------- .../esp32h2/include/soc/Kconfig.soc_caps.in | 4 -- .../include/soc/retention_periph_defs.h | 4 +- components/soc/esp32h2/include/soc/soc_caps.h | 1 - components/soc/esp32h2/pcnt_periph.c | 31 +------------- .../include/soc/retention_periph_defs.h | 4 +- .../include/soc/retention_periph_defs.h | 4 +- .../esp32p4/include/soc/Kconfig.soc_caps.in | 4 -- .../include/soc/retention_periph_defs.h | 2 - components/soc/esp32p4/include/soc/soc_caps.h | 1 - components/soc/esp32p4/pcnt_periph.c | 34 +-------------- components/soc/include/soc/pcnt_periph.h | 14 ------- components/soc/include/soc/regdma.h | 4 +- .../api-reference/system/power_management.rst | 10 ----- .../api-reference/system/power_management.rst | 10 ----- 25 files changed, 18 insertions(+), 239 deletions(-) diff --git a/components/esp_driver_pcnt/src/pulse_cnt.c b/components/esp_driver_pcnt/src/pulse_cnt.c index 6cd472e6a6..30a65f7dc6 100644 --- a/components/esp_driver_pcnt/src/pulse_cnt.c +++ b/components/esp_driver_pcnt/src/pulse_cnt.c @@ -62,12 +62,9 @@ typedef struct pcnt_group_t pcnt_group_t; typedef struct pcnt_unit_t pcnt_unit_t; typedef struct pcnt_chan_t pcnt_chan_t; -// Use retention link only when the target supports sleep retention -#define PCNT_USE_RETENTION_LINK (SOC_PCNT_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP) - -#if PCNT_USE_RETENTION_LINK -static esp_err_t pcnt_create_sleep_retention_link_cb(void *arg); -#endif +// The count register is read only and can't be restored after power down +// Use retention link to prevent power down +#define PCNT_USE_RETENTION_LINK CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP struct pcnt_platform_t { _lock_t mutex; // platform level mutex lock @@ -915,18 +912,7 @@ static pcnt_group_t *pcnt_acquire_group_handle(int group_id) pcnt_ll_reset_register(group_id); } #if PCNT_USE_RETENTION_LINK - sleep_retention_module_t module_id = pcnt_reg_retention_info[group_id].retention_module; - sleep_retention_module_init_param_t init_param = { - .cbs = { - .create = { - .handle = pcnt_create_sleep_retention_link_cb, - .arg = group, - }, - }, - .depends = RETENTION_MODULE_BITMAP_INIT(CLOCK_SYSTEM) - }; - // we only do retention init here. Allocate retention module in the unit initialization - if (sleep_retention_module_init(module_id, &init_param) != ESP_OK) { + if (sleep_retention_power_lock_acquire() != ESP_OK) { // even though the sleep retention module init failed, PCNT driver should still work, so just warning here ESP_LOGW(TAG, "init sleep retention failed %d, power domain may be turned off during sleep", group_id); } @@ -973,10 +959,7 @@ static void pcnt_release_group_handle(pcnt_group_t *group) pcnt_ll_enable_bus_clock(group_id, false); } #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); - } + sleep_retention_power_lock_release(); #endif // PCNT_USE_RETENTION_LINK } _lock_release(&s_platform.mutex); @@ -1101,20 +1084,6 @@ IRAM_ATTR static void pcnt_default_isr(void *args) } } -#if PCNT_USE_RETENTION_LINK -static esp_err_t pcnt_create_sleep_retention_link_cb(void *arg) -{ - pcnt_group_t *group = (pcnt_group_t *)arg; - int group_id = group->group_id; - sleep_retention_module_t module_id = pcnt_reg_retention_info[group_id].retention_module; - esp_err_t err = sleep_retention_entries_create(pcnt_reg_retention_info[group_id].regdma_entry_array, - pcnt_reg_retention_info[group_id].array_size, - REGDMA_LINK_PRI_PCNT, module_id); - ESP_RETURN_ON_ERROR(err, TAG, "create retention link failed"); - return ESP_OK; -} -#endif // PCNT_USE_RETENTION_LINK - #if CONFIG_PCNT_ENABLE_DEBUG_LOG __attribute__((constructor)) static void pcnt_override_default_log_level(void) diff --git a/components/esp_driver_pcnt/test_apps/pulse_cnt/main/test_pulse_cnt_sleep.c b/components/esp_driver_pcnt/test_apps/pulse_cnt/main/test_pulse_cnt_sleep.c index 2ac2dc4062..e6347a1cb8 100644 --- a/components/esp_driver_pcnt/test_apps/pulse_cnt/main/test_pulse_cnt_sleep.c +++ b/components/esp_driver_pcnt/test_apps/pulse_cnt/main/test_pulse_cnt_sleep.c @@ -98,10 +98,12 @@ static void test_pcnt_sleep_retention(void) printf("check if the sleep happened as expected\r\n"); TEST_ASSERT_EQUAL(0, sleep_ctx.sleep_request_result); -#if SOC_PCNT_SUPPORT_SLEEP_RETENTION + +#if SOC_PMU_SUPPORTED && !SOC_PM_TOP_PD_NOT_ALLOWED // check if the power domain also is powered down TEST_ASSERT_EQUAL(0, (sleep_ctx.sleep_flags) & PMU_SLEEP_PD_TOP); #endif + esp_sleep_set_sleep_context(NULL); gpio_hold_dis(TEST_PCNT_GPIO_A); diff --git a/components/esp_hw_support/sleep_system_peripheral.c b/components/esp_hw_support/sleep_system_peripheral.c index a5fe904443..9c1a62a48b 100644 --- a/components/esp_hw_support/sleep_system_peripheral.c +++ b/components/esp_hw_support/sleep_system_peripheral.c @@ -287,10 +287,6 @@ bool peripheral_domain_pd_allowed(void) mask.bitmap[SLEEP_RETENTION_MODULE_LEDC >> 5] |= BIT(SLEEP_RETENTION_MODULE_LEDC % 32); #endif -#if SOC_PCNT_SUPPORT_SLEEP_RETENTION - mask.bitmap[SLEEP_RETENTION_MODULE_PCNT0 >> 5] |= BIT(SLEEP_RETENTION_MODULE_PCNT0 % 32); -#endif - #if SOC_MCPWM_SUPPORT_SLEEP_RETENTION mask.bitmap[SLEEP_RETENTION_MODULE_MCPWM0 >> 5] |= BIT(SLEEP_RETENTION_MODULE_MCPWM0 % 32); #endif diff --git a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in index cb35db3a83..b6999af8f3 100644 --- a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in @@ -871,10 +871,6 @@ config SOC_PCNT_SUPPORT_STEP_NOTIFY bool default y -config SOC_PCNT_SUPPORT_SLEEP_RETENTION - bool - default y - config SOC_RMT_GROUPS int default 1 diff --git a/components/soc/esp32c5/include/soc/retention_periph_defs.h b/components/soc/esp32c5/include/soc/retention_periph_defs.h index 0f021d3a91..a9cda6140e 100644 --- a/components/soc/esp32c5/include/soc/retention_periph_defs.h +++ b/components/soc/esp32c5/include/soc/retention_periph_defs.h @@ -43,8 +43,7 @@ typedef enum periph_retention_module { SLEEP_RETENTION_MODULE_PARLIO0 = 19, SLEEP_RETENTION_MODULE_GPSPI2 = 20, SLEEP_RETENTION_MODULE_LEDC = 21, - SLEEP_RETENTION_MODULE_PCNT0 = 22, - SLEEP_RETENTION_MODULE_MCPWM0 = 23, + SLEEP_RETENTION_MODULE_MCPWM0 = 22, /* modem module, which includes WiFi, BLE and 802.15.4 */ SLEEP_RETENTION_MODULE_WIFI_MAC = 26, @@ -80,7 +79,6 @@ typedef enum periph_retention_module { : ((m) == SLEEP_RETENTION_MODULE_PARLIO0) ? true \ : ((m) == SLEEP_RETENTION_MODULE_GPSPI2) ? true \ : ((m) == SLEEP_RETENTION_MODULE_LEDC) ? true \ - : ((m) == SLEEP_RETENTION_MODULE_PCNT0) ? true \ : ((m) == SLEEP_RETENTION_MODULE_MCPWM0) ? true \ : false) diff --git a/components/soc/esp32c5/include/soc/soc_caps.h b/components/soc/esp32c5/include/soc/soc_caps.h index 92731060be..0960e2cc47 100644 --- a/components/soc/esp32c5/include/soc/soc_caps.h +++ b/components/soc/esp32c5/include/soc/soc_caps.h @@ -348,7 +348,6 @@ #define SOC_PCNT_SUPPORT_RUNTIME_THRES_UPDATE 1 #define SOC_PCNT_SUPPORT_CLEAR_SIGNAL 1 #define SOC_PCNT_SUPPORT_STEP_NOTIFY 1 -#define SOC_PCNT_SUPPORT_SLEEP_RETENTION 1 /*!< The sleep retention feature can help back up PCNT registers before sleep */ /*--------------------------- RMT CAPS ---------------------------------------*/ #define SOC_RMT_GROUPS 1U /*!< One RMT group */ diff --git a/components/soc/esp32c5/pcnt_periph.c b/components/soc/esp32c5/pcnt_periph.c index ca8c899a69..56767409ef 100644 --- a/components/soc/esp32c5/pcnt_periph.c +++ b/components/soc/esp32c5/pcnt_periph.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -70,33 +70,3 @@ const pcnt_signal_conn_t pcnt_periph_signals = { } } }; - -/** - * PCNT Registers to be saved during sleep retention - * - Configuration registers, e.g.: PCNT_CTRL_REG, PCNT_U0_CONF0_REG, PCNT_U0_CONF1_REG, PCNT_U0_CONF2_REG, PCNT_U1_CONF0_REG... - * - Step Configuration registers, e.g.: PCNT_U0_CHANGE_CONF_REG, PCNT_U1_CHANGE_CONF_REG, PCNT_U2_CHANGE_CONF_REG, PCNT_U3_CHANGE_CONF_REG - * - Interrupt enable registers, e.g.: PCNT_INT_ENA_REG -*/ -#define PCNT_RETENTION_REGS_CNT 18 -#define PCNT_RETENTION_REGS_BASE (DR_REG_PCNT_BASE + 0x0) -static const uint32_t pcnt_regs_map[4] = {0x1f040fff, 0x0, 0x0, 0x0}; -static const regdma_entries_config_t pcnt_regs_retention[] = { - // backup stage: save configuration registers - // restore stage: restore the configuration registers - [0] = { - .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_PCNT_LINK(0x00), \ - PCNT_RETENTION_REGS_BASE, PCNT_RETENTION_REGS_BASE, \ - PCNT_RETENTION_REGS_CNT, 0, 0, \ - pcnt_regs_map[0], pcnt_regs_map[1], \ - pcnt_regs_map[2], pcnt_regs_map[3]), \ - .owner = ENTRY(0) | ENTRY(2) - }, \ -}; - -const pcnt_reg_retention_info_t pcnt_reg_retention_info[SOC_PCNT_GROUPS] = { - [0] = { - .regdma_entry_array = pcnt_regs_retention, - .array_size = ARRAY_SIZE(pcnt_regs_retention), - .retention_module = SLEEP_RETENTION_MODULE_PCNT0 - }, -}; diff --git a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in index 399e48e196..213c005085 100644 --- a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in @@ -803,10 +803,6 @@ config SOC_PCNT_SUPPORT_RUNTIME_THRES_UPDATE bool default y -config SOC_PCNT_SUPPORT_SLEEP_RETENTION - bool - default y - config SOC_RMT_GROUPS int default 1 diff --git a/components/soc/esp32c6/include/soc/retention_periph_defs.h b/components/soc/esp32c6/include/soc/retention_periph_defs.h index 1b30218bbb..d944f62397 100644 --- a/components/soc/esp32c6/include/soc/retention_periph_defs.h +++ b/components/soc/esp32c6/include/soc/retention_periph_defs.h @@ -45,8 +45,7 @@ typedef enum periph_retention_module { SLEEP_RETENTION_MODULE_PARLIO0 = 21, SLEEP_RETENTION_MODULE_GPSPI2 = 22, SLEEP_RETENTION_MODULE_LEDC = 23, - SLEEP_RETENTION_MODULE_PCNT0 = 24, - SLEEP_RETENTION_MODULE_MCPWM0 = 25, + SLEEP_RETENTION_MODULE_MCPWM0 = 24, /* Modem module, which includes WiFi, BLE and 802.15.4 */ SLEEP_RETENTION_MODULE_WIFI_MAC = 26, @@ -82,7 +81,6 @@ typedef enum periph_retention_module { : ((m) == SLEEP_RETENTION_MODULE_PARLIO0) ? true \ : ((m) == SLEEP_RETENTION_MODULE_GPSPI2) ? true \ : ((m) == SLEEP_RETENTION_MODULE_LEDC) ? true \ - : ((m) == SLEEP_RETENTION_MODULE_PCNT0) ? true \ : ((m) == SLEEP_RETENTION_MODULE_MCPWM0) ? true \ : false) diff --git a/components/soc/esp32c6/include/soc/soc_caps.h b/components/soc/esp32c6/include/soc/soc_caps.h index 38218f04f4..668ca7d05b 100644 --- a/components/soc/esp32c6/include/soc/soc_caps.h +++ b/components/soc/esp32c6/include/soc/soc_caps.h @@ -320,7 +320,6 @@ #define SOC_PCNT_CHANNELS_PER_UNIT 2 #define SOC_PCNT_THRES_POINT_PER_UNIT 2 #define SOC_PCNT_SUPPORT_RUNTIME_THRES_UPDATE 1 -#define SOC_PCNT_SUPPORT_SLEEP_RETENTION 1 /*!< The sleep retention feature can help back up PCNT registers before sleep */ /*--------------------------- RMT CAPS ---------------------------------------*/ #define SOC_RMT_GROUPS 1U /*!< One RMT group */ diff --git a/components/soc/esp32c6/pcnt_periph.c b/components/soc/esp32c6/pcnt_periph.c index a7e8ccd5f2..920a5001a9 100644 --- a/components/soc/esp32c6/pcnt_periph.c +++ b/components/soc/esp32c6/pcnt_periph.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -66,32 +66,3 @@ const pcnt_signal_conn_t pcnt_periph_signals = { } } }; - -/** - * PCNT Registers to be saved during sleep retention - * - Configuration registers, e.g.: PCNT_CTRL_REG, PCNT_U0_CONF0_REG, PCNT_U0_CONF1_REG, PCNT_U0_CONF2_REG, PCNT_U1_CONF0_REG... - * - Interrupt enable registers, e.g.: PCNT_INT_ENA_REG -*/ -#define PCNT_RETENTION_REGS_CNT 14 -#define PCNT_RETENTION_REGS_BASE (DR_REG_PCNT_BASE + 0x0) -static const uint32_t pcnt_regs_map[4] = {0x1040fff, 0x0, 0x0, 0x0}; -static const regdma_entries_config_t pcnt_regs_retention[] = { - // backup stage: save configuration registers - // restore stage: restore the configuration registers - [0] = { - .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_PCNT_LINK(0x00), \ - PCNT_RETENTION_REGS_BASE, PCNT_RETENTION_REGS_BASE, \ - PCNT_RETENTION_REGS_CNT, 0, 0, \ - pcnt_regs_map[0], pcnt_regs_map[1], \ - pcnt_regs_map[2], pcnt_regs_map[3]), \ - .owner = ENTRY(0) | ENTRY(2) - }, \ -}; - -const pcnt_reg_retention_info_t pcnt_reg_retention_info[SOC_PCNT_GROUPS] = { - [0] = { - .regdma_entry_array = pcnt_regs_retention, - .array_size = ARRAY_SIZE(pcnt_regs_retention), - .retention_module = SLEEP_RETENTION_MODULE_PCNT0 - }, -}; diff --git a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in index 5519a4f074..1c58c53324 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -799,10 +799,6 @@ config SOC_PCNT_SUPPORT_STEP_NOTIFY bool default y -config SOC_PCNT_SUPPORT_SLEEP_RETENTION - bool - default y - config SOC_RMT_GROUPS int default 1 diff --git a/components/soc/esp32h2/include/soc/retention_periph_defs.h b/components/soc/esp32h2/include/soc/retention_periph_defs.h index cb32eff66c..e4ef9608dd 100644 --- a/components/soc/esp32h2/include/soc/retention_periph_defs.h +++ b/components/soc/esp32h2/include/soc/retention_periph_defs.h @@ -45,8 +45,7 @@ typedef enum periph_retention_module { SLEEP_RETENTION_MODULE_PARLIO0 = 21, SLEEP_RETENTION_MODULE_GPSPI2 = 22, SLEEP_RETENTION_MODULE_LEDC = 23, - SLEEP_RETENTION_MODULE_PCNT0 = 24, - SLEEP_RETENTION_MODULE_MCPWM0 = 25, + SLEEP_RETENTION_MODULE_MCPWM0 = 24, /* Modem module, which includes BLE and 802.15.4 */ SLEEP_RETENTION_MODULE_BLE_MAC = 28, @@ -80,7 +79,6 @@ typedef enum periph_retention_module { : ((m) == SLEEP_RETENTION_MODULE_PARLIO0) ? true \ : ((m) == SLEEP_RETENTION_MODULE_GPSPI2) ? true \ : ((m) == SLEEP_RETENTION_MODULE_LEDC) ? true \ - : ((m) == SLEEP_RETENTION_MODULE_PCNT0) ? true \ : ((m) == SLEEP_RETENTION_MODULE_MCPWM0) ? true \ : false) diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index 987072daa6..203f450bf1 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -334,7 +334,6 @@ #define SOC_PCNT_THRES_POINT_PER_UNIT 2 #define SOC_PCNT_SUPPORT_RUNTIME_THRES_UPDATE 1 #define SOC_PCNT_SUPPORT_STEP_NOTIFY 1 /*!< Only avliable in chip version above 1.2*/ -#define SOC_PCNT_SUPPORT_SLEEP_RETENTION 1 /*!< The sleep retention feature can help back up PCNT registers before sleep */ /*--------------------------- RMT CAPS ---------------------------------------*/ #define SOC_RMT_GROUPS 1U /*!< One RMT group */ diff --git a/components/soc/esp32h2/pcnt_periph.c b/components/soc/esp32h2/pcnt_periph.c index a7e8ccd5f2..920a5001a9 100644 --- a/components/soc/esp32h2/pcnt_periph.c +++ b/components/soc/esp32h2/pcnt_periph.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -66,32 +66,3 @@ const pcnt_signal_conn_t pcnt_periph_signals = { } } }; - -/** - * PCNT Registers to be saved during sleep retention - * - Configuration registers, e.g.: PCNT_CTRL_REG, PCNT_U0_CONF0_REG, PCNT_U0_CONF1_REG, PCNT_U0_CONF2_REG, PCNT_U1_CONF0_REG... - * - Interrupt enable registers, e.g.: PCNT_INT_ENA_REG -*/ -#define PCNT_RETENTION_REGS_CNT 14 -#define PCNT_RETENTION_REGS_BASE (DR_REG_PCNT_BASE + 0x0) -static const uint32_t pcnt_regs_map[4] = {0x1040fff, 0x0, 0x0, 0x0}; -static const regdma_entries_config_t pcnt_regs_retention[] = { - // backup stage: save configuration registers - // restore stage: restore the configuration registers - [0] = { - .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_PCNT_LINK(0x00), \ - PCNT_RETENTION_REGS_BASE, PCNT_RETENTION_REGS_BASE, \ - PCNT_RETENTION_REGS_CNT, 0, 0, \ - pcnt_regs_map[0], pcnt_regs_map[1], \ - pcnt_regs_map[2], pcnt_regs_map[3]), \ - .owner = ENTRY(0) | ENTRY(2) - }, \ -}; - -const pcnt_reg_retention_info_t pcnt_reg_retention_info[SOC_PCNT_GROUPS] = { - [0] = { - .regdma_entry_array = pcnt_regs_retention, - .array_size = ARRAY_SIZE(pcnt_regs_retention), - .retention_module = SLEEP_RETENTION_MODULE_PCNT0 - }, -}; diff --git a/components/soc/esp32h21/include/soc/retention_periph_defs.h b/components/soc/esp32h21/include/soc/retention_periph_defs.h index 44a487382f..99cf5abccc 100644 --- a/components/soc/esp32h21/include/soc/retention_periph_defs.h +++ b/components/soc/esp32h21/include/soc/retention_periph_defs.h @@ -45,8 +45,7 @@ typedef enum periph_retention_module { SLEEP_RETENTION_MODULE_PARLIO0 = 21, SLEEP_RETENTION_MODULE_GPSPI2 = 22, SLEEP_RETENTION_MODULE_LEDC = 23, - SLEEP_RETENTION_MODULE_PCNT0 = 24, - SLEEP_RETENTION_MODULE_MCPWM0 = 25, + SLEEP_RETENTION_MODULE_MCPWM0 = 24, /* Modem module, which includes BLE and 802.15.4 */ SLEEP_RETENTION_MODULE_BLE_MAC = 28, @@ -80,7 +79,6 @@ typedef enum periph_retention_module { : ((m) == SLEEP_RETENTION_MODULE_PARLIO0) ? true \ : ((m) == SLEEP_RETENTION_MODULE_GPSPI2) ? true \ : ((m) == SLEEP_RETENTION_MODULE_LEDC) ? true \ - : ((m) == SLEEP_RETENTION_MODULE_PCNT0) ? true \ : ((m) == SLEEP_RETENTION_MODULE_MCPWM0) ? true \ : false) diff --git a/components/soc/esp32h4/include/soc/retention_periph_defs.h b/components/soc/esp32h4/include/soc/retention_periph_defs.h index 2f316495d7..9306653f66 100644 --- a/components/soc/esp32h4/include/soc/retention_periph_defs.h +++ b/components/soc/esp32h4/include/soc/retention_periph_defs.h @@ -48,8 +48,7 @@ typedef enum periph_retention_module { SLEEP_RETENTION_MODULE_GPSPI2 = 24, SLEEP_RETENTION_MODULE_GPSPI3 = 25, SLEEP_RETENTION_MODULE_LEDC = 26, - SLEEP_RETENTION_MODULE_PCNT0 = 27, - SLEEP_RETENTION_MODULE_MCPWM0 = 28, + SLEEP_RETENTION_MODULE_MCPWM0 = 27, /* Modem module, which includes BLE and 802.15.4 */ SLEEP_RETENTION_MODULE_BLE_MAC = 29, @@ -86,7 +85,6 @@ typedef enum periph_retention_module { : ((m) == SLEEP_RETENTION_MODULE_GPSPI2) ? true \ : ((m) == SLEEP_RETENTION_MODULE_GPSPI3) ? true \ : ((m) == SLEEP_RETENTION_MODULE_LEDC) ? true \ - : ((m) == SLEEP_RETENTION_MODULE_PCNT0) ? true \ : ((m) == SLEEP_RETENTION_MODULE_MCPWM0) ? true \ : false) diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index 0d1ad891d1..d8e70fe2bb 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -1175,10 +1175,6 @@ config SOC_PCNT_SUPPORT_CLEAR_SIGNAL bool default y -config SOC_PCNT_SUPPORT_SLEEP_RETENTION - bool - default y - config SOC_RMT_GROUPS int default 1 diff --git a/components/soc/esp32p4/include/soc/retention_periph_defs.h b/components/soc/esp32p4/include/soc/retention_periph_defs.h index 17cf61998f..d68770ef3a 100644 --- a/components/soc/esp32p4/include/soc/retention_periph_defs.h +++ b/components/soc/esp32p4/include/soc/retention_periph_defs.h @@ -59,7 +59,6 @@ typedef enum periph_retention_module { SLEEP_RETENTION_MODULE_LEDC = 33, SLEEP_RETENTION_MODULE_MCPWM0 = 34, SLEEP_RETENTION_MODULE_MCPWM1 = 35, - SLEEP_RETENTION_MODULE_PCNT0 = 36, SLEEP_RETENTION_MODULE_MAX = SOC_PM_RETENTION_MODULE_NUM - 1 } periph_retention_module_t; @@ -101,7 +100,6 @@ typedef enum periph_retention_module { : ((m) == SLEEP_RETENTION_MODULE_LEDC) ? true \ : ((m) == SLEEP_RETENTION_MODULE_MCPWM0) ? true \ : ((m) == SLEEP_RETENTION_MODULE_MCPWM1) ? true \ - : ((m) == SLEEP_RETENTION_MODULE_PCNT0) ? true \ : false) #ifdef __cplusplus diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index d789b1f1be..1261317bbf 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -427,7 +427,6 @@ #define SOC_PCNT_THRES_POINT_PER_UNIT 2 #define SOC_PCNT_SUPPORT_RUNTIME_THRES_UPDATE 1 #define SOC_PCNT_SUPPORT_CLEAR_SIGNAL 1 /*!< Support clear signal input */ -#define SOC_PCNT_SUPPORT_SLEEP_RETENTION 1 /*!< The sleep retention feature can help back up PCNT registers before sleep */ /*--------------------------- RMT CAPS ---------------------------------------*/ #define SOC_RMT_GROUPS 1U /*!< One RMT group */ diff --git a/components/soc/esp32p4/pcnt_periph.c b/components/soc/esp32p4/pcnt_periph.c index 7e159c7d32..9acf3713ad 100644 --- a/components/soc/esp32p4/pcnt_periph.c +++ b/components/soc/esp32p4/pcnt_periph.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -70,35 +70,3 @@ const pcnt_signal_conn_t pcnt_periph_signals = { } } }; - -#if SOC_PCNT_SUPPORT_SLEEP_RETENTION -/** - * PCNT Registers to be saved during sleep retention - * - Configuration registers, e.g.: PCNT_CTRL_REG, PCNT_U0_CONF0_REG, PCNT_U0_CONF1_REG, PCNT_U0_CONF2_REG, PCNT_U1_CONF0_REG... - * - Step Configuration registers, e.g.: PCNT_U0_CHANGE_CONF_REG, PCNT_U1_CHANGE_CONF_REG, PCNT_U2_CHANGE_CONF_REG, PCNT_U3_CHANGE_CONF_REG - * - Interrupt enable registers, e.g.: PCNT_INT_ENA_REG -*/ -#define PCNT_RETENTION_REGS_CNT 18 -#define PCNT_RETENTION_REGS_BASE (DR_REG_PCNT_BASE + 0x0) -static const uint32_t pcnt_regs_map[4] = {0x1f040fff, 0x0, 0x0, 0x0}; -static const regdma_entries_config_t pcnt_regs_retention[] = { - // backup stage: save configuration registers - // restore stage: restore the configuration registers - [0] = { - .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_PCNT_LINK(0x00), \ - PCNT_RETENTION_REGS_BASE, PCNT_RETENTION_REGS_BASE, \ - PCNT_RETENTION_REGS_CNT, 0, 0, \ - pcnt_regs_map[0], pcnt_regs_map[1], \ - pcnt_regs_map[2], pcnt_regs_map[3]), \ - .owner = ENTRY(0) - }, \ -}; - -const pcnt_reg_retention_info_t pcnt_reg_retention_info[SOC_PCNT_GROUPS] = { - [0] = { - .regdma_entry_array = pcnt_regs_retention, - .array_size = ARRAY_SIZE(pcnt_regs_retention), - .retention_module = SLEEP_RETENTION_MODULE_PCNT0 - }, -}; -#endif // SOC_PCNT_SUPPORT_SLEEP_RETENTION diff --git a/components/soc/include/soc/pcnt_periph.h b/components/soc/include/soc/pcnt_periph.h index 59234607cd..18edab8b42 100644 --- a/components/soc/include/soc/pcnt_periph.h +++ b/components/soc/include/soc/pcnt_periph.h @@ -9,10 +9,6 @@ #include #include "soc/soc_caps.h" #include "soc/periph_defs.h" -#include "soc/regdma.h" -#if SOC_PCNT_SUPPORT_SLEEP_RETENTION -#include "soc/retention_periph_defs.h" -#endif #ifdef __cplusplus extern "C" { @@ -36,16 +32,6 @@ typedef struct { extern const pcnt_signal_conn_t pcnt_periph_signals; -#if SOC_PCNT_SUPPORT_SLEEP_RETENTION -typedef struct { - const periph_retention_module_t retention_module; - const regdma_entries_config_t *regdma_entry_array; - uint32_t array_size; -} pcnt_reg_retention_info_t; - -extern const pcnt_reg_retention_info_t pcnt_reg_retention_info[SOC_PCNT_GROUPS]; -#endif // SOC_PCNT_SUPPORT_SLEEP_RETENTION - #endif // SOC_PCNT_SUPPORTED #ifdef __cplusplus diff --git a/components/soc/include/soc/regdma.h b/components/soc/include/soc/regdma.h index 07885ae002..67b5c1d7fb 100644 --- a/components/soc/include/soc/regdma.h +++ b/components/soc/include/soc/regdma.h @@ -63,8 +63,7 @@ extern "C" { #define REGDMA_PARLIO_LINK(_pri) ((0x22 << 8) | _pri) #define REGDMA_GPSPI_LINK(_pri) ((0x23 << 8) | _pri) #define REGDMA_LEDC_LINK(_pri) ((0x24 << 8) | _pri) -#define REGDMA_PCNT_LINK(_pri) ((0x25 << 8) | _pri) -#define REGDMA_MCPWM_LINK(_pri) ((0x26 << 8) | _pri) +#define REGDMA_MCPWM_LINK(_pri) ((0x25 << 8) | _pri) #define REGDMA_MODEM_FE_LINK(_pri) ((0xFF << 8) | _pri) @@ -85,7 +84,6 @@ extern "C" { #define REGDMA_LINK_PRI_I2C REGDMA_LINK_PRI_GENERAL_PERIPH #define REGDMA_LINK_PRI_I2S REGDMA_LINK_PRI_GENERAL_PERIPH #define REGDMA_LINK_PRI_PARLIO REGDMA_LINK_PRI_GENERAL_PERIPH -#define REGDMA_LINK_PRI_PCNT REGDMA_LINK_PRI_GENERAL_PERIPH #define REGDMA_LINK_PRI_UART REGDMA_LINK_PRI_GENERAL_PERIPH #define REGDMA_LINK_PRI_TEMPERATURE_SENSOR REGDMA_LINK_PRI_GENERAL_PERIPH #define REGDMA_LINK_PRI_TWAI REGDMA_LINK_PRI_GENERAL_PERIPH diff --git a/docs/en/api-reference/system/power_management.rst b/docs/en/api-reference/system/power_management.rst index c21ecde468..da5eae6cd1 100644 --- a/docs/en/api-reference/system/power_management.rst +++ b/docs/en/api-reference/system/power_management.rst @@ -122,16 +122,6 @@ The following drivers hold the ``ESP_PM_APB_FREQ_MAX`` lock while the driver is :SOC_SDM_SUPPORTED: - **Sigma-delta**: between calls to :cpp:func:`sdm_channel_enable` and :cpp:func:`sdm_channel_disable`. :SOC_MCPWM_SUPPORTED: - **MCPWM**: between calls to :cpp:func:`mcpwm_timer_enable` and :cpp:func:`mcpwm_timer_disable`, as well as :cpp:func:`mcpwm_capture_timer_enable` and :cpp:func:`mcpwm_capture_timer_disable`. -The following peripheral drivers are not aware of DFS yet. Applications need to acquire/release locks themselves, when necessary: - -.. list:: - - :SOC_PCNT_SUPPORTED: - The legacy PCNT driver - :SOC_SDM_SUPPORTED: - The legacy Sigma-delta driver - - The legacy timer group driver - :SOC_MCPWM_SUPPORTED: - The legacy MCPWM driver - - .. only:: SOC_PM_SUPPORT_TOP_PD Light-sleep Peripheral Power Down diff --git a/docs/zh_CN/api-reference/system/power_management.rst b/docs/zh_CN/api-reference/system/power_management.rst index 1853b547a5..0dd473471e 100644 --- a/docs/zh_CN/api-reference/system/power_management.rst +++ b/docs/zh_CN/api-reference/system/power_management.rst @@ -122,16 +122,6 @@ ESP-IDF 中集成的电源管理算法可以根据应用程序组件的需求, :SOC_SDM_SUPPORTED: - **Sigma-delta**:从调用 :cpp:func:`sdm_channel_enable` 至 :cpp:func:`sdm_channel_disable` 期间。 :SOC_MCPWM_SUPPORTED: - **MCPWM**: 从调用 :cpp:func:`mcpwm_timer_enable` 至 :cpp:func:`mcpwm_timer_disable` 期间,以及调用 :cpp:func:`mcpwm_capture_timer_enable` 至 :cpp:func:`mcpwm_capture_timer_disable` 期间。 -以下外设驱动程序无法感知动态调频,应用程序需自己获取/释放管理锁: - -.. list:: - - :SOC_PCNT_SUPPORTED: - 旧版 PCNT 驱动 - :SOC_SDM_SUPPORTED: - 旧版 Sigma-delta 驱动 - - 旧版定时器驱动 (Timer Group) - :SOC_MCPWM_SUPPORTED: - 旧版 MCPWM 驱动 - - .. only:: SOC_PM_SUPPORT_TOP_PD Light-sleep 外设下电 From e6f5a9ab5a8e9b1d3e131d331f760fc45528df7e Mon Sep 17 00:00:00 2001 From: Chen Jichang Date: Wed, 30 Jul 2025 14:48:22 +0800 Subject: [PATCH 2/2] feat(pcnt): support pcnt on esp32h21 --- .../test_apps/pulse_cnt/README.md | 4 +- components/hal/esp32h21/include/hal/pcnt_ll.h | 504 ++++++++++++++++++ .../esp32h21/include/soc/Kconfig.soc_caps.in | 32 ++ .../soc/esp32h21/include/soc/soc_caps.h | 14 +- components/soc/esp32h21/pcnt_periph.c | 72 +++ .../soc/esp32h21/register/soc/pcnt_struct.h | 87 +-- docs/docs_not_updated/esp32h21.txt | 1 - .../peripherals/pcnt/rotary_encoder/README.md | 4 +- 8 files changed, 633 insertions(+), 85 deletions(-) create mode 100644 components/hal/esp32h21/include/hal/pcnt_ll.h create mode 100644 components/soc/esp32h21/pcnt_periph.c diff --git a/components/esp_driver_pcnt/test_apps/pulse_cnt/README.md b/components/esp_driver_pcnt/test_apps/pulse_cnt/README.md index 7abac169b5..c0916a10f2 100644 --- a/components/esp_driver_pcnt/test_apps/pulse_cnt/README.md +++ b/components/esp_driver_pcnt/test_apps/pulse_cnt/README.md @@ -1,2 +1,2 @@ -| Supported Targets | ESP32 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-H21 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | diff --git a/components/hal/esp32h21/include/hal/pcnt_ll.h b/components/hal/esp32h21/include/hal/pcnt_ll.h new file mode 100644 index 0000000000..c104fbe23a --- /dev/null +++ b/components/hal/esp32h21/include/hal/pcnt_ll.h @@ -0,0 +1,504 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include +#include "soc/pcnt_struct.h" +#include "hal/pcnt_types.h" +#include "hal/misc.h" +#include "soc/pcr_struct.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define PCNT_LL_GET_HW(num) (((num) == 0) ? (&PCNT) : NULL) +#define PCNT_LL_MAX_GLITCH_WIDTH 1023 +#define PCNT_LL_MAX_LIM SHRT_MAX +#define PCNT_LL_MIN_LIM SHRT_MIN + +typedef enum { + PCNT_LL_WATCH_EVENT_INVALID = -1, + PCNT_LL_WATCH_EVENT_THRES1, + PCNT_LL_WATCH_EVENT_THRES0, + PCNT_LL_WATCH_EVENT_LOW_LIMIT, + PCNT_LL_WATCH_EVENT_HIGH_LIMIT, + PCNT_LL_WATCH_EVENT_ZERO_CROSS, + PCNT_LL_WATCH_EVENT_MAX +} pcnt_ll_watch_event_id_t; + +typedef enum { + PCNT_LL_STEP_EVENT_REACH_INTERVAL_FORWARD = PCNT_LL_WATCH_EVENT_MAX, + PCNT_LL_STEP_EVENT_REACH_INTERVAL_BACKWARD, +} pcnt_ll_step_event_id_t; + +#define PCNT_LL_WATCH_EVENT_MASK ((1 << PCNT_LL_WATCH_EVENT_MAX) - 1) +#define PCNT_LL_UNIT_WATCH_EVENT(unit_id) (1 << (unit_id)) + +/** + * @brief Set PCNT channel edge action + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number + * @param channel PCNT channel number + * @param pos_act Counter action when detecting positive edge + * @param neg_act Counter action when detecting negative edge + */ +static inline void pcnt_ll_set_edge_action(pcnt_dev_t *hw, uint32_t unit, uint32_t channel, pcnt_channel_edge_action_t pos_act, pcnt_channel_edge_action_t neg_act) +{ + if (channel == 0) { + hw->conf_unit[unit].conf0.ch0_pos_mode_un = pos_act; + hw->conf_unit[unit].conf0.ch0_neg_mode_un = neg_act; + } else { + hw->conf_unit[unit].conf0.ch1_pos_mode_un = pos_act; + hw->conf_unit[unit].conf0.ch1_neg_mode_un = neg_act; + } +} + +/** + * @brief Set PCNT channel level action + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number + * @param channel PCNT channel number + * @param high_act Counter action when control signal is high level + * @param low_act Counter action when control signal is low level + */ +static inline void pcnt_ll_set_level_action(pcnt_dev_t *hw, uint32_t unit, uint32_t channel, pcnt_channel_level_action_t high_act, pcnt_channel_level_action_t low_act) +{ + if (channel == 0) { + hw->conf_unit[unit].conf0.ch0_hctrl_mode_un = high_act; + hw->conf_unit[unit].conf0.ch0_lctrl_mode_un = low_act; + } else { + hw->conf_unit[unit].conf0.ch1_hctrl_mode_un = high_act; + hw->conf_unit[unit].conf0.ch1_lctrl_mode_un = low_act; + } +} + +/** + * @brief Get pulse counter value + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit Pulse Counter unit number + * @return PCNT count value (a signed integer) + */ +__attribute__((always_inline)) +static inline int pcnt_ll_get_count(pcnt_dev_t *hw, uint32_t unit) +{ + pcnt_un_cnt_reg_t cnt_reg; + cnt_reg.val = hw->cnt_unit[unit].val; + + int16_t value = cnt_reg.pulse_cnt_un; + return value; +} + +/** + * @brief Pause PCNT counter of PCNT unit + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number + */ +__attribute__((always_inline)) +static inline void pcnt_ll_stop_count(pcnt_dev_t *hw, uint32_t unit) +{ + hw->ctrl.val |= 1 << (2 * unit + 1); +} + +/** + * @brief Resume counting for PCNT counter + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number, select from uint32_t + */ +__attribute__((always_inline)) +static inline void pcnt_ll_start_count(pcnt_dev_t *hw, uint32_t unit) +{ + hw->ctrl.val &= ~(1 << (2 * unit + 1)); +} + +/** + * @brief Clear PCNT counter value to zero + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number, select from uint32_t + */ +__attribute__((always_inline)) +static inline void pcnt_ll_clear_count(pcnt_dev_t *hw, uint32_t unit) +{ + hw->ctrl.val |= 1 << (2 * unit); + hw->ctrl.val &= ~(1 << (2 * unit)); +} + +/** + * @brief Enable PCNT step comparator event + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number + * @param enable true to enable, false to disable + */ +static inline void pcnt_ll_enable_step_notify(pcnt_dev_t *hw, uint32_t unit, bool enable) +{ + if (enable) { + hw->ctrl.val |= 1 << (8 + unit); + } else { + hw->ctrl.val &= ~(1 << (8 + unit)); + } +} + +/** + * @brief Set PCNT step value + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number + * @param direction PCNT step direction + * @param value PCNT step value + */ +static inline void pcnt_ll_set_step_value(pcnt_dev_t *hw, uint32_t unit, pcnt_step_direction_t direction, uint16_t value) +{ + if (direction == PCNT_STEP_FORWARD) { + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->conf_unit[unit].conf3, cnt_h_step_un, value); + } else { + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->conf_unit[unit].conf3, cnt_l_step_un, value); + } +} + +/** + * @brief Enable PCNT interrupt for PCNT unit + * @note Each PCNT unit has five watch point events that share the same interrupt bit. + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit_mask PCNT units mask + * @param enable True to enable interrupt, False to disable interrupt + */ +static inline void pcnt_ll_enable_intr(pcnt_dev_t *hw, uint32_t unit_mask, bool enable) +{ + if (enable) { + hw->int_ena.val |= unit_mask; + } else { + hw->int_ena.val &= ~unit_mask; + } +} + +/** + * @brief Get PCNT interrupt status + * + * @param hw Peripheral PCNT hardware instance address. + * @return Interrupt status word + */ +__attribute__((always_inline)) +static inline uint32_t pcnt_ll_get_intr_status(pcnt_dev_t *hw) +{ + return hw->int_st.val; +} + +/** + * @brief Clear PCNT interrupt status + * + * @param hw Peripheral PCNT hardware instance address. + * @param status value to clear interrupt status + */ +__attribute__((always_inline)) +static inline void pcnt_ll_clear_intr_status(pcnt_dev_t *hw, uint32_t status) +{ + hw->int_clr.val = status; +} + +/** + * @brief Enable PCNT high limit event + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number + * @param enable true to enable, false to disable + */ +static inline void pcnt_ll_enable_high_limit_event(pcnt_dev_t *hw, uint32_t unit, bool enable) +{ + hw->conf_unit[unit].conf0.thr_h_lim_en_un = enable; +} + +/** + * @brief Enable PCNT low limit event + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number + * @param enable true to enable, false to disable + */ +static inline void pcnt_ll_enable_low_limit_event(pcnt_dev_t *hw, uint32_t unit, bool enable) +{ + hw->conf_unit[unit].conf0.thr_l_lim_en_un = enable; +} + +/** + * @brief Enable PCNT zero cross event + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number + * @param enable true to enable, false to disable + */ +static inline void pcnt_ll_enable_zero_cross_event(pcnt_dev_t *hw, uint32_t unit, bool enable) +{ + hw->conf_unit[unit].conf0.thr_zero_en_un = enable; +} + +/** + * @brief Enable PCNT threshold event + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number + * @param thres Threshold ID + * @param enable true to enable, false to disable + */ +static inline void pcnt_ll_enable_thres_event(pcnt_dev_t *hw, uint32_t unit, uint32_t thres, bool enable) +{ + if (thres == 0) { + hw->conf_unit[unit].conf0.thr_thres0_en_un = enable; + } else { + hw->conf_unit[unit].conf0.thr_thres1_en_un = enable; + } +} + +/** + * @brief Disable all PCNT threshold events + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit unit number + */ +static inline void pcnt_ll_disable_all_events(pcnt_dev_t *hw, uint32_t unit) +{ + hw->conf_unit[unit].conf0.val &= ~(PCNT_LL_WATCH_EVENT_MASK << 11); +} + +/** + * @brief Set PCNT high limit value + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number + * @param value PCNT high limit value + */ +static inline void pcnt_ll_set_high_limit_value(pcnt_dev_t *hw, uint32_t unit, int value) +{ + pcnt_un_conf2_reg_t conf2_reg; + conf2_reg.val = hw->conf_unit[unit].conf2.val; + + conf2_reg.cnt_h_lim_un = value; + hw->conf_unit[unit].conf2.val = conf2_reg.val; +} + +/** + * @brief Set PCNT low limit value + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number + * @param value PCNT low limit value + */ +static inline void pcnt_ll_set_low_limit_value(pcnt_dev_t *hw, uint32_t unit, int value) +{ + pcnt_un_conf2_reg_t conf2_reg; + conf2_reg.val = hw->conf_unit[unit].conf2.val; + + conf2_reg.cnt_l_lim_un = value; + hw->conf_unit[unit].conf2.val = conf2_reg.val; +} + +/** + * @brief Set PCNT threshold value + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number + * @param thres Threshold ID + * @param value PCNT threshold value + */ +static inline void pcnt_ll_set_thres_value(pcnt_dev_t *hw, uint32_t unit, uint32_t thres, int value) +{ + pcnt_un_conf1_reg_t conf1_reg; + conf1_reg.val = hw->conf_unit[unit].conf1.val; + + if (thres == 0) { + conf1_reg.cnt_thres0_un = value; + } else { + conf1_reg.cnt_thres1_un = value; + } + hw->conf_unit[unit].conf1.val = conf1_reg.val; +} + +/** + * @brief Get PCNT high limit value + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number + * @return PCNT high limit value + */ +static inline int pcnt_ll_get_high_limit_value(pcnt_dev_t *hw, uint32_t unit) +{ + pcnt_un_conf2_reg_t conf2_reg; + conf2_reg.val = hw->conf_unit[unit].conf2.val; + + int16_t value = conf2_reg.cnt_h_lim_un; + return value; +} + +/** + * @brief Get PCNT low limit value + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number + * @return PCNT high limit value + */ +static inline int pcnt_ll_get_low_limit_value(pcnt_dev_t *hw, uint32_t unit) +{ + pcnt_un_conf2_reg_t conf2_reg; + conf2_reg.val = hw->conf_unit[unit].conf2.val; + + int16_t value = conf2_reg.cnt_l_lim_un ; + return value; +} + +/** + * @brief Get PCNT threshold value + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number + * @param thres Threshold ID + * @return PCNT threshold value + */ +__attribute__((always_inline)) +static inline int pcnt_ll_get_thres_value(pcnt_dev_t *hw, uint32_t unit, uint32_t thres) +{ + int16_t value; + pcnt_un_conf1_reg_t conf1_reg; + conf1_reg.val = hw->conf_unit[unit].conf1.val; + + if (thres == 0) { + value = conf1_reg.cnt_thres0_un ; + } else { + value = conf1_reg.cnt_thres1_un ; + } + return value; +} + +/** + * @brief Get PCNT unit runtime status + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number + * @return PCNT unit runtime status + */ +static inline uint32_t pcnt_ll_get_unit_status(pcnt_dev_t *hw, uint32_t unit) +{ + return hw->status_unit[unit].val; +} + +/** + * @brief Get PCNT zero cross mode + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number + * @return Zero cross mode + */ +__attribute__((always_inline)) +static inline pcnt_unit_zero_cross_mode_t pcnt_ll_get_zero_cross_mode(pcnt_dev_t *hw, uint32_t unit) +{ + return (pcnt_unit_zero_cross_mode_t)(hw->status_unit[unit].val & 0x03); +} + +/** + * @brief Get PCNT event status + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number + * @return Event status word + */ +__attribute__((always_inline)) +static inline uint32_t pcnt_ll_get_event_status(pcnt_dev_t *hw, uint32_t unit) +{ + return hw->status_unit[unit].val >> 2; +} + +/** + * @brief Set PCNT glitch filter threshold + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number + * @param filter_val PCNT signal filter value, counter in APB_CLK cycles. + * Any pulses lasting shorter than this will be ignored when the filter is enabled. + */ +static inline void pcnt_ll_set_glitch_filter_thres(pcnt_dev_t *hw, uint32_t unit, uint32_t filter_val) +{ + hw->conf_unit[unit].conf0.filter_thres_un = filter_val; +} + +/** + * @brief Get PCNT glitch filter threshold + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number + * @return glitch filter threshold + */ +static inline uint32_t pcnt_ll_get_glitch_filter_thres(pcnt_dev_t *hw, uint32_t unit) +{ + return hw->conf_unit[unit].conf0.filter_thres_un; +} + +/** + * @brief Enable PCNT glitch filter + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number + * @param enable True to enable the filter, False to disable the filter + */ +static inline void pcnt_ll_enable_glitch_filter(pcnt_dev_t *hw, uint32_t unit, bool enable) +{ + hw->conf_unit[unit].conf0.filter_en_un = enable; +} + +/** + * @brief Get interrupt status register address. + * + * @param hw Beginning address of the peripheral registers. + * + * @return Interrupt status register address + */ +static inline volatile void *pcnt_ll_get_intr_status_reg(pcnt_dev_t *hw) +{ + return &hw->int_st.val; +} + +/** + * @brief Enable or disable the bus clock for the PCNT module + * + * @param set_bit True to set bit, false to clear bit + */ +static inline void pcnt_ll_enable_bus_clock(int group_id, bool enable) +{ + (void)group_id; + PCR.pcnt_conf.pcnt_clk_en = enable; +} + +/** + * @brief Reset the PCNT module + */ +static inline void pcnt_ll_reset_register(int group_id) +{ + (void)group_id; + PCR.pcnt_conf.pcnt_rst_en = 1; + PCR.pcnt_conf.pcnt_rst_en = 0; +} + +/** + * @brief Check if the step notify is supported + */ +static inline bool pcnt_ll_is_step_notify_supported(int group_id) +{ + (void)group_id; + return true; +} + + +#ifdef __cplusplus +} +#endif diff --git a/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in index 2c7520c1be..191165ce27 100644 --- a/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in @@ -115,6 +115,10 @@ config SOC_REG_I2C_SUPPORTED bool default y +config SOC_PCNT_SUPPORTED + bool + default y + config SOC_TWAI_SUPPORTED bool default y @@ -467,6 +471,34 @@ config SOC_LEDC_CHANNEL_NUM int default 6 +config SOC_PCNT_GROUPS + int + default 1 + +config SOC_PCNT_UNITS_PER_GROUP + int + default 4 + +config SOC_PCNT_CHANNELS_PER_UNIT + int + default 2 + +config SOC_PCNT_THRES_POINT_PER_UNIT + int + default 2 + +config SOC_PCNT_SUPPORT_RUNTIME_THRES_UPDATE + bool + default y + +config SOC_PCNT_SUPPORT_CLEAR_SIGNAL + bool + default y + +config SOC_PCNT_SUPPORT_STEP_NOTIFY + bool + default y + config SOC_RMT_GROUPS int default 1 diff --git a/components/soc/esp32h21/include/soc/soc_caps.h b/components/soc/esp32h21/include/soc/soc_caps.h index 007d767c0e..5ad8faaa89 100644 --- a/components/soc/esp32h21/include/soc/soc_caps.h +++ b/components/soc/esp32h21/include/soc/soc_caps.h @@ -72,7 +72,7 @@ #define SOC_MODEM_CLOCK_SUPPORTED 1 #define SOC_REG_I2C_SUPPORTED 1 // #define SOC_PHY_SUPPORTED 1 -// #define SOC_PCNT_SUPPORTED 1 //TODO: [ESP32H21] IDF-11566 +#define SOC_PCNT_SUPPORTED 1 // #define SOC_MCPWM_SUPPORTED 1 //TODO: [ESP32H21] IDF-11601 #define SOC_TWAI_SUPPORTED 1 // #define SOC_ETM_SUPPORTED 1 //TODO: [ESP32H21] IDF-11576 @@ -303,11 +303,13 @@ // #define SOC_MPU_REGION_WO_SUPPORTED 0 /*-------------------------- PCNT CAPS ---------------------------------------*/ -// #define SOC_PCNT_GROUPS 1U -// #define SOC_PCNT_UNITS_PER_GROUP 4 -// #define SOC_PCNT_CHANNELS_PER_UNIT 2 -// #define SOC_PCNT_THRES_POINT_PER_UNIT 2 -// #define SOC_PCNT_SUPPORT_RUNTIME_THRES_UPDATE 1 +#define SOC_PCNT_GROUPS 1U +#define SOC_PCNT_UNITS_PER_GROUP 4 +#define SOC_PCNT_CHANNELS_PER_UNIT 2 +#define SOC_PCNT_THRES_POINT_PER_UNIT 2 +#define SOC_PCNT_SUPPORT_RUNTIME_THRES_UPDATE 1 +#define SOC_PCNT_SUPPORT_CLEAR_SIGNAL 1 +#define SOC_PCNT_SUPPORT_STEP_NOTIFY 1 /*--------------------------- RMT CAPS ---------------------------------------*/ #define SOC_RMT_GROUPS 1U /*!< One RMT group */ diff --git a/components/soc/esp32h21/pcnt_periph.c b/components/soc/esp32h21/pcnt_periph.c new file mode 100644 index 0000000000..8d1ddfc062 --- /dev/null +++ b/components/soc/esp32h21/pcnt_periph.c @@ -0,0 +1,72 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "soc/pcnt_periph.h" +#include "soc/gpio_sig_map.h" +#include "soc/pcnt_reg.h" + +const pcnt_signal_conn_t pcnt_periph_signals = { + .groups = { + [0] = { + .irq = ETS_PCNT_INTR_SOURCE, + .module_name = "pcnt0", + .units = { + [0] = { + .channels = { + [0] = { + .control_sig = PCNT_CTRL_CH0_IN0_IDX, + .pulse_sig = PCNT_SIG_CH0_IN0_IDX + }, + [1] = { + .control_sig = PCNT_CTRL_CH1_IN0_IDX, + .pulse_sig = PCNT_SIG_CH1_IN0_IDX + } + }, + .clear_sig = PCNT_RST_IN0_IDX + }, + [1] = { + .channels = { + [0] = { + .control_sig = PCNT_CTRL_CH0_IN1_IDX, + .pulse_sig = PCNT_SIG_CH0_IN1_IDX, + }, + [1] = { + .control_sig = PCNT_CTRL_CH1_IN1_IDX, + .pulse_sig = PCNT_SIG_CH1_IN1_IDX + } + }, + .clear_sig = PCNT_RST_IN1_IDX + }, + [2] = { + .channels = { + [0] = { + .control_sig = PCNT_CTRL_CH0_IN2_IDX, + .pulse_sig = PCNT_SIG_CH0_IN2_IDX, + }, + [1] = { + .control_sig = PCNT_CTRL_CH1_IN2_IDX, + .pulse_sig = PCNT_SIG_CH1_IN2_IDX + } + }, + .clear_sig = PCNT_RST_IN2_IDX + }, + [3] = { + .channels = { + [0] = { + .control_sig = PCNT_CTRL_CH0_IN3_IDX, + .pulse_sig = PCNT_SIG_CH0_IN3_IDX, + }, + [1] = { + .control_sig = PCNT_CTRL_CH1_IN3_IDX, + .pulse_sig = PCNT_SIG_CH1_IN3_IDX + } + }, + .clear_sig = PCNT_RST_IN3_IDX + } + } + } + } +}; diff --git a/components/soc/esp32h21/register/soc/pcnt_struct.h b/components/soc/esp32h21/register/soc/pcnt_struct.h index 83e2b656b7..e79d035663 100644 --- a/components/soc/esp32h21/register/soc/pcnt_struct.h +++ b/components/soc/esp32h21/register/soc/pcnt_struct.h @@ -1,5 +1,5 @@ /** - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -156,65 +156,14 @@ typedef union { /** cnt_h_step_u0 : R/W; bitpos: [15:0]; default: 0; * Configures the forward rotation step value for unit 0. */ - uint32_t cnt_h_step_u0:16; + uint32_t cnt_h_step_un:16; /** cnt_l_step_u0 : R/W; bitpos: [31:16]; default: 0; * Configures the reverse rotation step value for unit 0. */ - uint32_t cnt_l_step_u0:16; + uint32_t cnt_l_step_un:16; }; uint32_t val; -} pcnt_u0_conf3_reg_t; - -/** Type of u1_conf3 register - * Configuration register for unit $n's step value. - */ -typedef union { - struct { - /** cnt_h_step_u1 : R/W; bitpos: [15:0]; default: 0; - * Configures the forward rotation step value for unit 1. - */ - uint32_t cnt_h_step_u1:16; - /** cnt_l_step_u1 : R/W; bitpos: [31:16]; default: 0; - * Configures the reverse rotation step value for unit 1. - */ - uint32_t cnt_l_step_u1:16; - }; - uint32_t val; -} pcnt_u1_conf3_reg_t; - -/** Type of u2_conf3 register - * Configuration register for unit $n's step value. - */ -typedef union { - struct { - /** cnt_h_step_u2 : R/W; bitpos: [15:0]; default: 0; - * Configures the forward rotation step value for unit 2. - */ - uint32_t cnt_h_step_u2:16; - /** cnt_l_step_u2 : R/W; bitpos: [31:16]; default: 0; - * Configures the reverse rotation step value for unit 2. - */ - uint32_t cnt_l_step_u2:16; - }; - uint32_t val; -} pcnt_u2_conf3_reg_t; - -/** Type of u3_conf3 register - * Configuration register for unit $n's step value. - */ -typedef union { - struct { - /** cnt_h_step_u3 : R/W; bitpos: [15:0]; default: 0; - * Configures the forward rotation step value for unit 3. - */ - uint32_t cnt_h_step_u3:16; - /** cnt_l_step_u3 : R/W; bitpos: [31:16]; default: 0; - * Configures the reverse rotation step value for unit 3. - */ - uint32_t cnt_l_step_u3:16; - }; - uint32_t val; -} pcnt_u3_conf3_reg_t; +} pcnt_un_conf3_reg_t; /** Type of ctrl register * Control register for all counters @@ -484,29 +433,19 @@ typedef union { } pcnt_date_reg_t; -typedef struct { - volatile pcnt_un_conf0_reg_t u0_conf0; - volatile pcnt_un_conf1_reg_t u0_conf1; - volatile pcnt_un_conf2_reg_t u0_conf2; - volatile pcnt_u0_conf3_reg_t u0_conf3; - volatile pcnt_un_conf0_reg_t u1_conf0; - volatile pcnt_un_conf1_reg_t u1_conf1; - volatile pcnt_un_conf2_reg_t u1_conf2; - volatile pcnt_u1_conf3_reg_t u1_conf3; - volatile pcnt_un_conf0_reg_t u2_conf0; - volatile pcnt_un_conf1_reg_t u2_conf1; - volatile pcnt_un_conf2_reg_t u2_conf2; - volatile pcnt_u2_conf3_reg_t u2_conf3; - volatile pcnt_un_conf0_reg_t u3_conf0; - volatile pcnt_un_conf1_reg_t u3_conf1; - volatile pcnt_un_conf2_reg_t u3_conf2; - volatile pcnt_u3_conf3_reg_t u3_conf3; - volatile pcnt_un_cnt_reg_t un_cnt[4]; +typedef struct pcnt_dev_t { + volatile struct { + pcnt_un_conf0_reg_t conf0; + pcnt_un_conf1_reg_t conf1; + pcnt_un_conf2_reg_t conf2; + pcnt_un_conf3_reg_t conf3; + } conf_unit[4]; + volatile pcnt_un_cnt_reg_t cnt_unit[4]; volatile pcnt_int_raw_reg_t int_raw; volatile pcnt_int_st_reg_t int_st; volatile pcnt_int_ena_reg_t int_ena; volatile pcnt_int_clr_reg_t int_clr; - volatile pcnt_un_status_reg_t un_status[4]; + volatile pcnt_un_status_reg_t status_unit[4]; volatile pcnt_ctrl_reg_t ctrl; uint32_t reserved_074[34]; volatile pcnt_date_reg_t date; diff --git a/docs/docs_not_updated/esp32h21.txt b/docs/docs_not_updated/esp32h21.txt index 097084c644..19ee3537b6 100644 --- a/docs/docs_not_updated/esp32h21.txt +++ b/docs/docs_not_updated/esp32h21.txt @@ -177,7 +177,6 @@ api-reference/peripherals/lcd/i2c_lcd.rst api-reference/peripherals/lcd/spi_lcd.rst api-reference/peripherals/lcd/rgb_lcd.rst api-reference/peripherals/lcd/parl_lcd.rst -api-reference/peripherals/pcnt.rst api-reference/peripherals/spi_features.rst api-reference/peripherals/ppa.rst api-reference/peripherals/ledc.rst diff --git a/examples/peripherals/pcnt/rotary_encoder/README.md b/examples/peripherals/pcnt/rotary_encoder/README.md index f38ea2dc13..fe0f5079d0 100644 --- a/examples/peripherals/pcnt/rotary_encoder/README.md +++ b/examples/peripherals/pcnt/rotary_encoder/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-H21 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # Rotary Encoder Example