From 3b376b03df517628833e911938b1264fc351283e Mon Sep 17 00:00:00 2001 From: morris Date: Wed, 15 May 2024 18:31:35 +0800 Subject: [PATCH] feat(pcnt): add driver support on esp32c5 --- components/hal/esp32c5/include/hal/pcnt_ll.h | 495 ++++++++++++++++++ components/soc/esp32/pcnt_periph.c | 1 - .../beta3/include/soc/Kconfig.soc_caps.in | 28 + .../esp32c5/beta3/include/soc/pcnt_struct.h | 4 +- .../soc/esp32c5/beta3/include/soc/soc_caps.h | 13 +- components/soc/esp32c5/beta3/pcnt_periph.c | 70 +++ .../mp/include/soc/Kconfig.soc_caps.in | 28 + .../soc/esp32c5/mp/include/soc/pcnt_struct.h | 94 +--- .../soc/esp32c5/mp/include/soc/soc_caps.h | 14 +- components/soc/esp32c5/mp/pcnt_periph.c | 70 +++ components/soc/esp32c6/pcnt_periph.c | 1 - components/soc/esp32h2/pcnt_periph.c | 1 - components/soc/esp32p4/pcnt_periph.c | 1 - components/soc/esp32s2/pcnt_periph.c | 1 - components/soc/esp32s3/pcnt_periph.c | 1 - components/soc/include/soc/pcnt_periph.h | 1 - docs/docs_not_updated/esp32c5.txt | 1 - 17 files changed, 724 insertions(+), 100 deletions(-) create mode 100644 components/hal/esp32c5/include/hal/pcnt_ll.h create mode 100644 components/soc/esp32c5/beta3/pcnt_periph.c create mode 100644 components/soc/esp32c5/mp/pcnt_periph.c diff --git a/components/hal/esp32c5/include/hal/pcnt_ll.h b/components/hal/esp32c5/include/hal/pcnt_ll.h new file mode 100644 index 0000000000..ddf151b677 --- /dev/null +++ b/components/hal/esp32c5/include/hal/pcnt_ll.h @@ -0,0 +1,495 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 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_LIN 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; + +#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 value PCNT step value + */ +static inline void pcnt_ll_set_step_value(pcnt_dev_t *hw, uint32_t unit, int value) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->change_conf_unit[3 - unit], cnt_step, value); +} + +/** + * @brief Set PCNT step limit value + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number + * @param value PCNT step limit value + */ +static inline void pcnt_ll_set_step_limit_value(pcnt_dev_t *hw, uint32_t unit, int value) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->change_conf_unit[3 - unit], cnt_step_lim, 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 + */ +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; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/soc/esp32/pcnt_periph.c b/components/soc/esp32/pcnt_periph.c index f11beee6c9..f413c0b0ab 100644 --- a/components/soc/esp32/pcnt_periph.c +++ b/components/soc/esp32/pcnt_periph.c @@ -11,7 +11,6 @@ const pcnt_signal_conn_t pcnt_periph_signals = { .groups = { [0] = { - .module = PERIPH_PCNT_MODULE, .irq = ETS_PCNT_INTR_SOURCE, .units = { [0] = { diff --git a/components/soc/esp32c5/beta3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c5/beta3/include/soc/Kconfig.soc_caps.in index 51f555389b..f73769d906 100644 --- a/components/soc/esp32c5/beta3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c5/beta3/include/soc/Kconfig.soc_caps.in @@ -19,6 +19,10 @@ config SOC_GPTIMER_SUPPORTED bool default y +config SOC_PCNT_SUPPORTED + bool + default y + config SOC_ASYNC_MEMCPY_SUPPORTED bool default y @@ -363,6 +367,30 @@ config SOC_MMU_DI_VADDR_SHARED bool default y +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_RMT_GROUPS int default 1 diff --git a/components/soc/esp32c5/beta3/include/soc/pcnt_struct.h b/components/soc/esp32c5/beta3/include/soc/pcnt_struct.h index ce929f709e..a724547e8e 100644 --- a/components/soc/esp32c5/beta3/include/soc/pcnt_struct.h +++ b/components/soc/esp32c5/beta3/include/soc/pcnt_struct.h @@ -419,12 +419,12 @@ typedef struct pcnt_dev_t { pcnt_un_conf1_reg_t conf1; pcnt_un_conf2_reg_t conf2; } conf_unit[4]; - volatile pcnt_un_cnt_reg_t un_cnt[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; volatile pcnt_un_change_conf_reg_t change_conf_unit[4]; // Note the unit order is 3210 uint32_t reserved_074[34]; diff --git a/components/soc/esp32c5/beta3/include/soc/soc_caps.h b/components/soc/esp32c5/beta3/include/soc/soc_caps.h index e418cc0936..03053b6e87 100644 --- a/components/soc/esp32c5/beta3/include/soc/soc_caps.h +++ b/components/soc/esp32c5/beta3/include/soc/soc_caps.h @@ -23,7 +23,7 @@ #define SOC_GDMA_SUPPORTED 1 #define SOC_AHB_GDMA_SUPPORTED 1 #define SOC_GPTIMER_SUPPORTED 1 -// #define SOC_PCNT_SUPPORTED 1 // TODO: [ESP32C5] IDF-8683 +#define SOC_PCNT_SUPPORTED 1 // #define SOC_MCPWM_SUPPORTED 1 // TODO: [ESP32C5] IDF-8709 // #define SOC_TWAI_SUPPORTED 1 // TODO: [ESP32C5] IDF-8691 // #define SOC_ETM_SUPPORTED 1 // TODO: [ESP32C5] IDF-8693 @@ -299,11 +299,12 @@ // #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 /*--------------------------- RMT CAPS ---------------------------------------*/ #define SOC_RMT_GROUPS 1U /*!< One RMT group */ diff --git a/components/soc/esp32c5/beta3/pcnt_periph.c b/components/soc/esp32c5/beta3/pcnt_periph.c new file mode 100644 index 0000000000..162db5aa27 --- /dev/null +++ b/components/soc/esp32c5/beta3/pcnt_periph.c @@ -0,0 +1,70 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "soc/pcnt_periph.h" +#include "soc/gpio_sig_map.h" + +const pcnt_signal_conn_t pcnt_periph_signals = { + .groups = { + [0] = { + .irq = ETS_PCNT_INTR_SOURCE, + .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/esp32c5/mp/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c5/mp/include/soc/Kconfig.soc_caps.in index f23e3e999d..06a1115eb8 100644 --- a/components/soc/esp32c5/mp/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c5/mp/include/soc/Kconfig.soc_caps.in @@ -19,6 +19,10 @@ config SOC_GPTIMER_SUPPORTED bool default y +config SOC_PCNT_SUPPORTED + bool + default y + config SOC_ASYNC_MEMCPY_SUPPORTED bool default y @@ -227,6 +231,30 @@ config SOC_MMU_DI_VADDR_SHARED bool default y +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_RMT_GROUPS int default 1 diff --git a/components/soc/esp32c5/mp/include/soc/pcnt_struct.h b/components/soc/esp32c5/mp/include/soc/pcnt_struct.h index b4d8ca6a39..1a8ec481e6 100644 --- a/components/soc/esp32c5/mp/include/soc/pcnt_struct.h +++ b/components/soc/esp32c5/mp/include/soc/pcnt_struct.h @@ -217,74 +217,22 @@ typedef union { uint32_t val; } pcnt_ctrl_reg_t; -/** Type of u3_change_conf register +/** Type of un_change_conf register * Configuration register for unit $n's step value. */ typedef union { struct { - /** cnt_step_u3 : R/W; bitpos: [15:0]; default: 0; - * Configures the step value for unit 3. + /** cnt_step : R/W; bitpos: [15:0]; default: 0; + * Configures the step value for unit n. */ - uint32_t cnt_step_u3:16; + uint32_t cnt_step:16; /** cnt_step_lim_u3 : R/W; bitpos: [31:16]; default: 0; - * Configures the step limit value for unit 3. + * Configures the step limit value for unit n. */ - uint32_t cnt_step_lim_u3:16; + uint32_t cnt_step_lim:16; }; uint32_t val; -} pcnt_u3_change_conf_reg_t; - -/** Type of u2_change_conf register - * Configuration register for unit $n's step value. - */ -typedef union { - struct { - /** cnt_step_u2 : R/W; bitpos: [15:0]; default: 0; - * Configures the step value for unit 2. - */ - uint32_t cnt_step_u2:16; - /** cnt_step_lim_u2 : R/W; bitpos: [31:16]; default: 0; - * Configures the step limit value for unit 2. - */ - uint32_t cnt_step_lim_u2:16; - }; - uint32_t val; -} pcnt_u2_change_conf_reg_t; - -/** Type of u1_change_conf register - * Configuration register for unit $n's step value. - */ -typedef union { - struct { - /** cnt_step_u1 : R/W; bitpos: [15:0]; default: 0; - * Configures the step value for unit 1. - */ - uint32_t cnt_step_u1:16; - /** cnt_step_lim_u1 : R/W; bitpos: [31:16]; default: 0; - * Configures the step limit value for unit 1. - */ - uint32_t cnt_step_lim_u1:16; - }; - uint32_t val; -} pcnt_u1_change_conf_reg_t; - -/** Type of u0_change_conf register - * Configuration register for unit $n's step value. - */ -typedef union { - struct { - /** cnt_step_u0 : R/W; bitpos: [15:0]; default: 0; - * Configures the step value for unit 0. - */ - uint32_t cnt_step_u0:16; - /** cnt_step_lim_u0 : R/W; bitpos: [31:16]; default: 0; - * Configures the step limit value for unit 0. - */ - uint32_t cnt_step_lim_u0:16; - }; - uint32_t val; -} pcnt_u0_change_conf_reg_t; - +} pcnt_un_change_conf_reg_t; /** Group: Status Register */ /** Type of un_cnt register @@ -488,30 +436,20 @@ 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_un_conf0_reg_t u1_conf0; - volatile pcnt_un_conf1_reg_t u1_conf1; - volatile pcnt_un_conf2_reg_t u1_conf2; - 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_un_conf0_reg_t u3_conf0; - volatile pcnt_un_conf1_reg_t u3_conf1; - volatile pcnt_un_conf2_reg_t u3_conf2; - 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; + } 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; - volatile pcnt_u3_change_conf_reg_t u3_change_conf; - volatile pcnt_u2_change_conf_reg_t u2_change_conf; - volatile pcnt_u1_change_conf_reg_t u1_change_conf; - volatile pcnt_u0_change_conf_reg_t u0_change_conf; + volatile pcnt_un_change_conf_reg_t change_conf_unit[4]; // Note the unit order is 3210 uint32_t reserved_074[34]; volatile pcnt_date_reg_t date; } pcnt_dev_t; diff --git a/components/soc/esp32c5/mp/include/soc/soc_caps.h b/components/soc/esp32c5/mp/include/soc/soc_caps.h index 8f7e8932d1..83eb765153 100644 --- a/components/soc/esp32c5/mp/include/soc/soc_caps.h +++ b/components/soc/esp32c5/mp/include/soc/soc_caps.h @@ -23,7 +23,7 @@ #define SOC_GDMA_SUPPORTED 1 #define SOC_AHB_GDMA_SUPPORTED 1 #define SOC_GPTIMER_SUPPORTED 1 -// #define SOC_PCNT_SUPPORTED 1 // TODO: [ESP32C5] IDF-8683 +#define SOC_PCNT_SUPPORTED 1 // #define SOC_MCPWM_SUPPORTED 1 // TODO: [ESP32C5] IDF-8709 // #define SOC_TWAI_SUPPORTED 1 // TODO: [ESP32C5] IDF-8691 // #define SOC_ETM_SUPPORTED 1 // TODO: [ESP32C5] IDF-8693 @@ -295,11 +295,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 // IDF-7984 /*--------------------------- RMT CAPS ---------------------------------------*/ #define SOC_RMT_GROUPS 1U /*!< One RMT group */ diff --git a/components/soc/esp32c5/mp/pcnt_periph.c b/components/soc/esp32c5/mp/pcnt_periph.c new file mode 100644 index 0000000000..162db5aa27 --- /dev/null +++ b/components/soc/esp32c5/mp/pcnt_periph.c @@ -0,0 +1,70 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "soc/pcnt_periph.h" +#include "soc/gpio_sig_map.h" + +const pcnt_signal_conn_t pcnt_periph_signals = { + .groups = { + [0] = { + .irq = ETS_PCNT_INTR_SOURCE, + .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/esp32c6/pcnt_periph.c b/components/soc/esp32c6/pcnt_periph.c index 83c3424a0f..b2b440245b 100644 --- a/components/soc/esp32c6/pcnt_periph.c +++ b/components/soc/esp32c6/pcnt_periph.c @@ -10,7 +10,6 @@ const pcnt_signal_conn_t pcnt_periph_signals = { .groups = { [0] = { - .module = PERIPH_PCNT_MODULE, .irq = ETS_PCNT_INTR_SOURCE, .units = { [0] = { diff --git a/components/soc/esp32h2/pcnt_periph.c b/components/soc/esp32h2/pcnt_periph.c index 83c3424a0f..b2b440245b 100644 --- a/components/soc/esp32h2/pcnt_periph.c +++ b/components/soc/esp32h2/pcnt_periph.c @@ -10,7 +10,6 @@ const pcnt_signal_conn_t pcnt_periph_signals = { .groups = { [0] = { - .module = PERIPH_PCNT_MODULE, .irq = ETS_PCNT_INTR_SOURCE, .units = { [0] = { diff --git a/components/soc/esp32p4/pcnt_periph.c b/components/soc/esp32p4/pcnt_periph.c index 8d1afb6ed2..ae7d32b2fe 100644 --- a/components/soc/esp32p4/pcnt_periph.c +++ b/components/soc/esp32p4/pcnt_periph.c @@ -10,7 +10,6 @@ const pcnt_signal_conn_t pcnt_periph_signals = { .groups = { [0] = { - .module = PERIPH_PCNT_MODULE, .irq = ETS_PCNT_INTR_SOURCE, .units = { [0] = { diff --git a/components/soc/esp32s2/pcnt_periph.c b/components/soc/esp32s2/pcnt_periph.c index 83c3424a0f..b2b440245b 100644 --- a/components/soc/esp32s2/pcnt_periph.c +++ b/components/soc/esp32s2/pcnt_periph.c @@ -10,7 +10,6 @@ const pcnt_signal_conn_t pcnt_periph_signals = { .groups = { [0] = { - .module = PERIPH_PCNT_MODULE, .irq = ETS_PCNT_INTR_SOURCE, .units = { [0] = { diff --git a/components/soc/esp32s3/pcnt_periph.c b/components/soc/esp32s3/pcnt_periph.c index 83c3424a0f..b2b440245b 100644 --- a/components/soc/esp32s3/pcnt_periph.c +++ b/components/soc/esp32s3/pcnt_periph.c @@ -10,7 +10,6 @@ const pcnt_signal_conn_t pcnt_periph_signals = { .groups = { [0] = { - .module = PERIPH_PCNT_MODULE, .irq = ETS_PCNT_INTR_SOURCE, .units = { [0] = { diff --git a/components/soc/include/soc/pcnt_periph.h b/components/soc/include/soc/pcnt_periph.h index 16ced33c43..e7d8818b09 100644 --- a/components/soc/include/soc/pcnt_periph.h +++ b/components/soc/include/soc/pcnt_periph.h @@ -26,7 +26,6 @@ typedef struct { const uint32_t clear_sig; } units[SOC_PCNT_UNITS_PER_GROUP]; const uint32_t irq; - const periph_module_t module; } groups[SOC_PCNT_GROUPS]; } pcnt_signal_conn_t; diff --git a/docs/docs_not_updated/esp32c5.txt b/docs/docs_not_updated/esp32c5.txt index a2ba119778..926c4f1b84 100644 --- a/docs/docs_not_updated/esp32c5.txt +++ b/docs/docs_not_updated/esp32c5.txt @@ -117,7 +117,6 @@ api-reference/peripherals/spi_slave.rst api-reference/peripherals/etm.rst api-reference/peripherals/i2s.rst api-reference/peripherals/gptimer.rst -api-reference/peripherals/pcnt.rst api-reference/peripherals/touch_element.rst api-reference/peripherals/lcd.rst api-reference/peripherals/mcpwm.rst