diff --git a/components/driver/test_apps/legacy_pcnt_driver/main/test_legacy_pcnt.c b/components/driver/test_apps/legacy_pcnt_driver/main/test_legacy_pcnt.c index af54d80722..9348f715be 100644 --- a/components/driver/test_apps/legacy_pcnt_driver/main/test_legacy_pcnt.c +++ b/components/driver/test_apps/legacy_pcnt_driver/main/test_legacy_pcnt.c @@ -11,7 +11,9 @@ #include "soc/soc_caps.h" #include "driver/gpio.h" #include "driver/pcnt.h" +#if SOC_LEDC_SUPPORTED #include "driver/ledc.h" +#endif #include "esp_attr.h" #include "esp_log.h" #include "soc/gpio_periph.h" @@ -30,6 +32,9 @@ #define PCNT_CTRL_HIGH_LEVEL 1 #define PCNT_CTRL_LOW_LEVEL 0 +// The following items only used in the cases that involve LEDC +#if SOC_LEDC_SUPPORTED + static QueueHandle_t pcnt_evt_queue = NULL; typedef struct { @@ -40,6 +45,69 @@ typedef struct { int l_threshold; int filter_time; } event_times; +#endif // SOC_LEDC_SUPPORTED + +// test PCNT basic configuration +TEST_CASE("PCNT_test_config", "[pcnt]") +{ + pcnt_config_t pcnt_config = { + .pulse_gpio_num = PCNT_INPUT_IO, + .ctrl_gpio_num = PCNT_CTRL_VCC_IO, + .channel = PCNT_CHANNEL_0, + .unit = PCNT_UNIT_0, + .pos_mode = PCNT_COUNT_INC, + .neg_mode = PCNT_COUNT_DIS, + .lctrl_mode = PCNT_MODE_REVERSE, + .hctrl_mode = PCNT_MODE_KEEP, + .counter_h_lim = 100, + .counter_l_lim = 0, + }; + // basic configuration + pcnt_config_t temp_pcnt_config = pcnt_config; + TEST_ESP_OK(pcnt_unit_config(&pcnt_config)); + + // test SOC_PCNT_UNITS_PER_GROUP units, from 0-(SOC_PCNT_UNITS_PER_GROUP-1) + pcnt_config = temp_pcnt_config; + pcnt_config.unit = SOC_PCNT_UNITS_PER_GROUP; + TEST_ASSERT_NOT_NULL((void *)pcnt_unit_config(&pcnt_config)); + for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) { + pcnt_config.unit = i; + TEST_ESP_OK(pcnt_unit_config(&pcnt_config)); + } + + // test channels + pcnt_config = temp_pcnt_config; + pcnt_config.channel = PCNT_CHANNEL_MAX; + TEST_ASSERT_NOT_NULL((void *)pcnt_unit_config(&pcnt_config)); + pcnt_config = temp_pcnt_config; + pcnt_config.pulse_gpio_num = -1; + TEST_ESP_OK(pcnt_unit_config(&pcnt_config)); + + pcnt_config = temp_pcnt_config; + pcnt_config.pulse_gpio_num = GPIO_NUM_MAX + 1; + TEST_ASSERT_NOT_NULL((void *)pcnt_unit_config(&pcnt_config)); + + // test pulse_gpio_num and ctrl_gpio_num is the same + pcnt_config = temp_pcnt_config; + pcnt_config.pulse_gpio_num = PCNT_INPUT_IO; + pcnt_config.ctrl_gpio_num = PCNT_INPUT_IO; + TEST_ASSERT_NOT_NULL((void *)pcnt_unit_config(&pcnt_config)); + + pcnt_config = temp_pcnt_config; + pcnt_config.pos_mode = PCNT_COUNT_MAX; + TEST_ASSERT_NOT_NULL((void *)pcnt_unit_config(&pcnt_config)); + + pcnt_config = temp_pcnt_config; + pcnt_config.hctrl_mode = PCNT_MODE_MAX; + TEST_ASSERT_NOT_NULL((void *)pcnt_unit_config(&pcnt_config)); + + pcnt_config = temp_pcnt_config; + pcnt_config.lctrl_mode = PCNT_MODE_MAX; + TEST_ASSERT_NOT_NULL((void *)pcnt_unit_config(&pcnt_config)); +} + +// The following test cases rely on the support of LEDC +#if SOC_LEDC_SUPPORTED static void pcnt_test_io_config(int ctrl_level) { @@ -304,65 +372,6 @@ static void count_mode_test(gpio_num_t ctl_io) TEST_ASSERT_INT16_WITHIN(1, test_counter, result[7]); } -// test PCNT basic configuration -TEST_CASE("PCNT_test_config", "[pcnt]") -{ - pcnt_config_t pcnt_config = { - .pulse_gpio_num = PCNT_INPUT_IO, - .ctrl_gpio_num = PCNT_CTRL_VCC_IO, - .channel = PCNT_CHANNEL_0, - .unit = PCNT_UNIT_0, - .pos_mode = PCNT_COUNT_INC, - .neg_mode = PCNT_COUNT_DIS, - .lctrl_mode = PCNT_MODE_REVERSE, - .hctrl_mode = PCNT_MODE_KEEP, - .counter_h_lim = 100, - .counter_l_lim = 0, - }; - // basic configuration - pcnt_config_t temp_pcnt_config = pcnt_config; - TEST_ESP_OK(pcnt_unit_config(&pcnt_config)); - - // test SOC_PCNT_UNITS_PER_GROUP units, from 0-(SOC_PCNT_UNITS_PER_GROUP-1) - pcnt_config = temp_pcnt_config; - pcnt_config.unit = SOC_PCNT_UNITS_PER_GROUP; - TEST_ASSERT_NOT_NULL((void *)pcnt_unit_config(&pcnt_config)); - for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) { - pcnt_config.unit = i; - TEST_ESP_OK(pcnt_unit_config(&pcnt_config)); - } - - // test channels - pcnt_config = temp_pcnt_config; - pcnt_config.channel = PCNT_CHANNEL_MAX; - TEST_ASSERT_NOT_NULL((void *)pcnt_unit_config(&pcnt_config)); - pcnt_config = temp_pcnt_config; - pcnt_config.pulse_gpio_num = -1; - TEST_ESP_OK(pcnt_unit_config(&pcnt_config)); - - pcnt_config = temp_pcnt_config; - pcnt_config.pulse_gpio_num = GPIO_NUM_MAX + 1; - TEST_ASSERT_NOT_NULL((void *)pcnt_unit_config(&pcnt_config)); - - // test pulse_gpio_num and ctrl_gpio_num is the same - pcnt_config = temp_pcnt_config; - pcnt_config.pulse_gpio_num = PCNT_INPUT_IO; - pcnt_config.ctrl_gpio_num = PCNT_INPUT_IO; - TEST_ASSERT_NOT_NULL((void *)pcnt_unit_config(&pcnt_config)); - - pcnt_config = temp_pcnt_config; - pcnt_config.pos_mode = PCNT_COUNT_MAX; - TEST_ASSERT_NOT_NULL((void *)pcnt_unit_config(&pcnt_config)); - - pcnt_config = temp_pcnt_config; - pcnt_config.hctrl_mode = PCNT_MODE_MAX; - TEST_ASSERT_NOT_NULL((void *)pcnt_unit_config(&pcnt_config)); - - pcnt_config = temp_pcnt_config; - pcnt_config.lctrl_mode = PCNT_MODE_MAX; - TEST_ASSERT_NOT_NULL((void *)pcnt_unit_config(&pcnt_config)); -} - /* PCNT basic property: * 1. pause counter * 2. resume counter @@ -666,3 +675,4 @@ TEST_CASE("PCNT_counting_mode_test", "[pcnt]") printf("PCNT mode test for negative count\n"); count_mode_test(PCNT_CTRL_GND_IO); } +#endif // SOC_LEDC_SUPPORTED diff --git a/components/driver/test_apps/legacy_pcnt_driver/pytest_legacy_pcnt.py b/components/driver/test_apps/legacy_pcnt_driver/pytest_legacy_pcnt.py index c2a1c98270..0f021e69e2 100644 --- a/components/driver/test_apps/legacy_pcnt_driver/pytest_legacy_pcnt.py +++ b/components/driver/test_apps/legacy_pcnt_driver/pytest_legacy_pcnt.py @@ -9,6 +9,7 @@ from pytest_embedded import Dut @pytest.mark.esp32s2 @pytest.mark.esp32s3 @pytest.mark.esp32c6 +# @pytest.mark.esp32h2 # TODO: IDF-6263, IDF-6235 @pytest.mark.generic @pytest.mark.parametrize( 'config', diff --git a/components/driver/test_apps/pulse_cnt/pytest_pulse_cnt.py b/components/driver/test_apps/pulse_cnt/pytest_pulse_cnt.py index b8d40cf4d1..a599c08073 100644 --- a/components/driver/test_apps/pulse_cnt/pytest_pulse_cnt.py +++ b/components/driver/test_apps/pulse_cnt/pytest_pulse_cnt.py @@ -9,6 +9,7 @@ from pytest_embedded import Dut @pytest.mark.esp32s2 @pytest.mark.esp32s3 @pytest.mark.esp32c6 +# @pytest.mark.esp32h2 # TODO: IDF-6263, IDF-6227 @pytest.mark.generic @pytest.mark.parametrize( 'config', diff --git a/components/hal/esp32h2/include/hal/clk_gate_ll.h b/components/hal/esp32h2/include/hal/clk_gate_ll.h index c82a998091..2022c9f861 100644 --- a/components/hal/esp32h2/include/hal/clk_gate_ll.h +++ b/components/hal/esp32h2/include/hal/clk_gate_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -23,6 +23,8 @@ static inline uint32_t periph_ll_get_clk_en_mask(periph_module_t periph) return PCR_SARADC_CLK_EN; case PERIPH_RMT_MODULE: return PCR_RMT_CLK_EN; + case PERIPH_PCNT_MODULE: + return PCR_PCNT_CLK_EN; case PERIPH_LEDC_MODULE: return PCR_LEDC_CLK_EN; case PERIPH_UART0_MODULE: @@ -88,6 +90,8 @@ static inline uint32_t periph_ll_get_rst_en_mask(periph_module_t periph, bool en return PCR_SARADC_RST_EN; case PERIPH_RMT_MODULE: return PCR_RMT_RST_EN; + case PERIPH_PCNT_MODULE: + return PCR_PCNT_RST_EN; case PERIPH_LEDC_MODULE: return PCR_LEDC_RST_EN; case PERIPH_UART0_MODULE: @@ -178,6 +182,8 @@ static uint32_t periph_ll_get_clk_en_reg(periph_module_t periph) return PCR_RMT_CONF_REG; case PERIPH_LEDC_MODULE: return PCR_LEDC_CONF_REG; + case PERIPH_PCNT_MODULE: + return PCR_PCNT_CONF_REG; case PERIPH_UART0_MODULE: return PCR_UART0_CONF_REG; case PERIPH_UART1_MODULE: @@ -227,6 +233,8 @@ static uint32_t periph_ll_get_rst_en_reg(periph_module_t periph) return PCR_SARADC_CONF_REG; case PERIPH_RMT_MODULE: return PCR_RMT_CONF_REG; + case PERIPH_PCNT_MODULE: + return PCR_PCNT_CONF_REG; case PERIPH_LEDC_MODULE: return PCR_LEDC_CONF_REG; case PERIPH_UART0_MODULE: diff --git a/components/hal/esp32h2/include/hal/pcnt_ll.h b/components/hal/esp32h2/include/hal/pcnt_ll.h new file mode 100644 index 0000000000..8c759ef093 --- /dev/null +++ b/components/hal/esp32h2/include/hal/pcnt_ll.h @@ -0,0 +1,426 @@ +/* + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/******************************************************************************* + * NOTICE + * The hal is not public api, don't use in application code. + * See readme.md in hal/include/hal/readme.md + ******************************************************************************/ + +// The LL layer for ESP32-H2 PCNT register operations + +#pragma once + +#include +#include +#include +#include "soc/pcnt_struct.h" +#include "hal/pcnt_types.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 = pos_act; + hw->conf_unit[unit].conf0.ch0_neg_mode = neg_act; + } else { + hw->conf_unit[unit].conf0.ch1_pos_mode = pos_act; + hw->conf_unit[unit].conf0.ch1_neg_mode = 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 = high_act; + hw->conf_unit[unit].conf0.ch0_lctrl_mode = low_act; + } else { + hw->conf_unit[unit].conf0.ch1_hctrl_mode = high_act; + hw->conf_unit[unit].conf0.ch1_lctrl_mode = 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 = hw->cnt_unit[unit]; + int16_t value = cnt_reg.pulse_cnt; + 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 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 = 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 = 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 = 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 = enable; + } else { + hw->conf_unit[unit].conf0.thr_thres1_en = 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 = hw->conf_unit[unit].conf2; + conf2_reg.cnt_h_lim = value; + hw->conf_unit[unit].conf2 = conf2_reg; +} + +/** + * @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 = hw->conf_unit[unit].conf2; + conf2_reg.cnt_l_lim = value; + hw->conf_unit[unit].conf2 = conf2_reg; +} + +/** + * @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 = hw->conf_unit[unit].conf1; + if (thres == 0) { + conf1_reg.cnt_thres0 = value; + } else { + conf1_reg.cnt_thres1 = value; + } + hw->conf_unit[unit].conf1 = conf1_reg; +} + +/** + * @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 = hw->conf_unit[unit].conf2; + int16_t value = conf2_reg.cnt_h_lim ; + 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 = hw->conf_unit[unit].conf2; + int16_t value = conf2_reg.cnt_l_lim ; + 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 = hw->conf_unit[unit].conf1; + if (thres == 0) { + value = conf1_reg.cnt_thres0 ; + } else { + value = conf1_reg.cnt_thres1 ; + } + 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 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 = 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 ; +} + +/** + * @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 = 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; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/soc/esp32h2/CMakeLists.txt b/components/soc/esp32h2/CMakeLists.txt index 8f5b821c67..25599a01ee 100644 --- a/components/soc/esp32h2/CMakeLists.txt +++ b/components/soc/esp32h2/CMakeLists.txt @@ -6,6 +6,7 @@ set(srcs "interrupts.c" "spi_periph.c" "ledc_periph.c" + "pcnt_periph.c" "rmt_periph.c" "sdm_periph.c" "i2s_periph.c" diff --git a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in index cb44cbebc1..0671b982d6 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -11,6 +11,10 @@ config SOC_ASYNC_MEMCPY_SUPPORTED bool default y +config SOC_PCNT_SUPPORTED + bool + default y + config SOC_GPTIMER_SUPPORTED bool default y diff --git a/components/soc/esp32h2/include/soc/periph_defs.h b/components/soc/esp32h2/include/soc/periph_defs.h index 464c16370d..df6eef2c74 100644 --- a/components/soc/esp32h2/include/soc/periph_defs.h +++ b/components/soc/esp32h2/include/soc/periph_defs.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -22,6 +22,7 @@ typedef enum { PERIPH_TIMG1_MODULE, PERIPH_UHCI0_MODULE, PERIPH_RMT_MODULE, + PERIPH_PCNT_MODULE, PERIPH_SPI_MODULE, //SPI1 PERIPH_SPI2_MODULE, //SPI2 PERIPH_TWAI0_MODULE, diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index baaa1f8385..150eeaaeeb 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -29,7 +29,7 @@ // #define SOC_DEDICATED_GPIO_SUPPORTED 1 // TODO: IDF-6241 #define SOC_GDMA_SUPPORTED 1 #define SOC_ASYNC_MEMCPY_SUPPORTED 1 -// #define SOC_PCNT_SUPPORTED 1 // TODO: IDF-6221 +#define SOC_PCNT_SUPPORTED 1 // #define SOC_MCPWM_SUPPORTED 1 // TODO: IDF-6237 // #define SOC_TWAI_SUPPORTED 1 // TODO: IDF-6217 // #define SOC_BT_SUPPORTED 1 // TODO: IDF-6416 @@ -212,7 +212,6 @@ #define SOC_MPU_REGION_RO_SUPPORTED 0 #define SOC_MPU_REGION_WO_SUPPORTED 0 -// TODO: IDF-6221 /*-------------------------- PCNT CAPS ---------------------------------------*/ #define SOC_PCNT_GROUPS 1U #define SOC_PCNT_UNITS_PER_GROUP 4 diff --git a/components/soc/esp32h2/pcnt_periph.c b/components/soc/esp32h2/pcnt_periph.c new file mode 100644 index 0000000000..83c3424a0f --- /dev/null +++ b/components/soc/esp32h2/pcnt_periph.c @@ -0,0 +1,67 @@ +/* + * SPDX-FileCopyrightText: 2020-2022 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] = { + .module = PERIPH_PCNT_MODULE, + .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 + } + } + }, + [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 + } + } + }, + [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 + } + } + }, + [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 + } + } + } + } + } + } +}; diff --git a/examples/peripherals/pcnt/rotary_encoder/pytest_rotary_encoder.py b/examples/peripherals/pcnt/rotary_encoder/pytest_rotary_encoder.py index 64514e56d7..9515db200b 100644 --- a/examples/peripherals/pcnt/rotary_encoder/pytest_rotary_encoder.py +++ b/examples/peripherals/pcnt/rotary_encoder/pytest_rotary_encoder.py @@ -9,6 +9,7 @@ from pytest_embedded.dut import Dut @pytest.mark.esp32s2 @pytest.mark.esp32s3 @pytest.mark.esp32c6 +# @pytest.mark.esp32h2 # TODO: IDF-6263, IDF-6227 @pytest.mark.generic def test_rotary_encoder(dut: Dut) -> None: dut.expect_exact('install pcnt unit')