From 62f1cbca2c1d19c285f55ce6887fd71d6317837c Mon Sep 17 00:00:00 2001 From: morris Date: Tue, 11 Oct 2022 18:04:54 +0800 Subject: [PATCH] gpio: support glitch filter --- components/driver/CMakeLists.txt | 9 ++ components/driver/gpio/glitch_filter_priv.h | 40 +++++ .../driver/gpio/gpio_flex_glitch_filter.c | 142 ++++++++++++++++ .../driver/gpio/gpio_glitch_filter_ops.c | 30 ++++ .../driver/gpio/gpio_pin_glitch_filter.c | 69 ++++++++ .../driver/include/driver/gpio_filter.h | 112 +++++++++++++ .../driver/test_apps/gpio/main/CMakeLists.txt | 4 + .../test_apps/gpio/main/test_gpio_filter.c | 151 ++++++++++++++++++ components/hal/esp32c2/include/hal/gpio_ll.h | 24 ++- components/hal/esp32c3/include/hal/gpio_ll.h | 24 ++- .../include/hal/gpio_glitch_filter_ll.h | 66 ++++++++ components/hal/esp32c6/include/hal/gpio_ll.h | 22 +++ .../hal/esp32h4/include/rev1/hal/gpio_ll.h | 22 +++ .../hal/esp32h4/include/rev2/hal/gpio_ll.h | 26 ++- components/hal/esp32s2/include/hal/gpio_ll.h | 24 ++- components/hal/esp32s3/include/hal/gpio_ll.h | 24 ++- .../esp32c2/include/soc/Kconfig.soc_caps.in | 4 + .../soc/esp32c2/include/soc/io_mux_reg.h | 23 ++- components/soc/esp32c2/include/soc/soc_caps.h | 5 +- .../esp32c3/include/soc/Kconfig.soc_caps.in | 4 + .../soc/esp32c3/include/soc/io_mux_reg.h | 23 ++- components/soc/esp32c3/include/soc/soc_caps.h | 5 +- .../esp32c6/include/soc/Kconfig.soc_caps.in | 8 + .../soc/esp32c6/include/soc/gpio_ext_struct.h | 16 +- .../soc/esp32c6/include/soc/io_mux_reg.h | 7 + components/soc/esp32c6/include/soc/soc_caps.h | 6 +- .../soc/esp32h4/include/rev1/soc/io_mux_reg.h | 23 ++- .../soc/esp32h4/include/rev2/soc/io_mux_reg.h | 23 ++- .../esp32h4/include/soc/Kconfig.soc_caps.in | 4 + components/soc/esp32h4/include/soc/soc_caps.h | 4 +- .../esp32s2/include/soc/Kconfig.soc_caps.in | 4 + .../soc/esp32s2/include/soc/io_mux_reg.h | 43 ++--- components/soc/esp32s2/include/soc/soc_caps.h | 5 +- .../esp32s3/include/soc/Kconfig.soc_caps.in | 4 + .../soc/esp32s3/include/soc/io_mux_reg.h | 23 ++- components/soc/esp32s3/include/soc/soc_caps.h | 5 +- 36 files changed, 945 insertions(+), 83 deletions(-) create mode 100644 components/driver/gpio/glitch_filter_priv.h create mode 100644 components/driver/gpio/gpio_flex_glitch_filter.c create mode 100644 components/driver/gpio/gpio_glitch_filter_ops.c create mode 100644 components/driver/gpio/gpio_pin_glitch_filter.c create mode 100644 components/driver/include/driver/gpio_filter.h create mode 100644 components/driver/test_apps/gpio/main/test_gpio_filter.c create mode 100644 components/hal/esp32c6/include/hal/gpio_glitch_filter_ll.h diff --git a/components/driver/CMakeLists.txt b/components/driver/CMakeLists.txt index 07282a70fb..aa1b5dcd2a 100644 --- a/components/driver/CMakeLists.txt +++ b/components/driver/CMakeLists.txt @@ -3,6 +3,7 @@ idf_build_get_property(target IDF_TARGET) set(srcs "gpio/gpio.c" "gpio/rtc_io.c" + "gpio/gpio_glitch_filter_ops.c" "gptimer/gptimer.c" "sdspi_crc.c" "sdspi_host.c" @@ -57,6 +58,14 @@ if(CONFIG_SOC_DEDICATED_GPIO_SUPPORTED) list(APPEND srcs "gpio/dedic_gpio.c") endif() +if(CONFIG_SOC_GPIO_SUPPORT_PIN_GLITCH_FILTER) + list(APPEND srcs "gpio/gpio_pin_glitch_filter.c") +endif() + +if(CONFIG_SOC_GPIO_FLEX_GLITCH_FILTER_NUM GREATER 0) + list(APPEND srcs "gpio/gpio_flex_glitch_filter.c") +endif() + if(CONFIG_SOC_SDM_SUPPORTED) list(APPEND srcs "sdm.c" "deprecated/sigma_delta_legacy.c") endif() diff --git a/components/driver/gpio/glitch_filter_priv.h b/components/driver/gpio/glitch_filter_priv.h new file mode 100644 index 0000000000..5d05244e44 --- /dev/null +++ b/components/driver/gpio/glitch_filter_priv.h @@ -0,0 +1,40 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "esp_err.h" +#include "driver/gpio_filter.h" +#include "esp_heap_caps.h" + +#define FILTER_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct gpio_glitch_filter_t gpio_glitch_filter_t; + +typedef enum { + GLITCH_FILTER_FSM_INIT, + GLITCH_FILTER_FSM_ENABLE, +} glitch_filter_fsm_t; + +/** + * @brief Glitch Filter base class + */ +struct gpio_glitch_filter_t { + glitch_filter_fsm_t fsm; + gpio_num_t gpio_num; + esp_err_t (*enable)(gpio_glitch_filter_t *filter); + esp_err_t (*disable)(gpio_glitch_filter_t *filter); + esp_err_t (*del)(gpio_glitch_filter_t *filter); +}; + +#ifdef __cplusplus +} +#endif diff --git a/components/driver/gpio/gpio_flex_glitch_filter.c b/components/driver/gpio/gpio_flex_glitch_filter.c new file mode 100644 index 0000000000..a7105805df --- /dev/null +++ b/components/driver/gpio/gpio_flex_glitch_filter.c @@ -0,0 +1,142 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "freertos/FreeRTOS.h" +#include "esp_check.h" +#include "glitch_filter_priv.h" +#include "esp_private/esp_clk.h" +#include "soc/soc_caps.h" +#include "hal/gpio_glitch_filter_ll.h" + +static const char *TAG = "gpio-filter"; + +typedef struct gpio_flex_glitch_filter_t gpio_flex_glitch_filter_t; + +typedef struct gpio_flex_glitch_filter_group_t { + gpio_glitch_filter_dev_t *hw; + gpio_flex_glitch_filter_t *filters[SOC_GPIO_FLEX_GLITCH_FILTER_NUM]; + portMUX_TYPE spinlock; +} gpio_flex_glitch_filter_group_t; + +struct gpio_flex_glitch_filter_t { + gpio_glitch_filter_t base; + gpio_flex_glitch_filter_group_t *group; + uint32_t filter_id; +}; + +static gpio_flex_glitch_filter_group_t s_gpio_glitch_filter_group = { + .hw = &GLITCH_FILTER, + .spinlock = portMUX_INITIALIZER_UNLOCKED, +}; + +static esp_err_t gpio_filter_register_to_group(gpio_flex_glitch_filter_t *filter) +{ + gpio_flex_glitch_filter_group_t *group = &s_gpio_glitch_filter_group; + int filter_id = -1; + // loop to search free one in the group + portENTER_CRITICAL(&group->spinlock); + for (int j = 0; j < SOC_GPIO_FLEX_GLITCH_FILTER_NUM; j++) { + if (!group->filters[j]) { + filter_id = j; + group->filters[j] = filter; + break; + } + } + portEXIT_CRITICAL(&group->spinlock); + + ESP_RETURN_ON_FALSE(filter_id != -1, ESP_ERR_NOT_FOUND, TAG, "no free gpio glitch filter"); + filter->filter_id = filter_id; + filter->group = group; + return ESP_OK; +} + +static esp_err_t gpio_filter_destroy(gpio_flex_glitch_filter_t *filter) +{ + gpio_flex_glitch_filter_group_t *group = &s_gpio_glitch_filter_group; + int filter_id = filter->filter_id; + + // unregister the filter from the group + if (filter->group) { + portENTER_CRITICAL(&group->spinlock); + group->filters[filter_id] = NULL; + portEXIT_CRITICAL(&group->spinlock); + } + + free(filter); + return ESP_OK; +} + +static esp_err_t gpio_flex_glitch_filter_del(gpio_glitch_filter_t *filter) +{ + ESP_RETURN_ON_FALSE(filter->fsm == GLITCH_FILTER_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "filter not in init state"); + gpio_flex_glitch_filter_t *flex_filter = __containerof(filter, gpio_flex_glitch_filter_t, base); + return gpio_filter_destroy(flex_filter); +} + +static esp_err_t gpio_flex_glitch_filter_enable(gpio_glitch_filter_t *filter) +{ + ESP_RETURN_ON_FALSE(filter->fsm == GLITCH_FILTER_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "filter not in init state"); + gpio_flex_glitch_filter_t *flex_filter = __containerof(filter, gpio_flex_glitch_filter_t, base); + + int filter_id = flex_filter->filter_id; + gpio_ll_glitch_filter_enable(s_gpio_glitch_filter_group.hw, filter_id, true); + filter->fsm = GLITCH_FILTER_FSM_ENABLE; + return ESP_OK; +} + +static esp_err_t gpio_flex_glitch_filter_disable(gpio_glitch_filter_t *filter) +{ + ESP_RETURN_ON_FALSE(filter->fsm == GLITCH_FILTER_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "filter not in enable state"); + gpio_flex_glitch_filter_t *flex_filter = __containerof(filter, gpio_flex_glitch_filter_t, base); + + int filter_id = flex_filter->filter_id; + gpio_ll_glitch_filter_enable(s_gpio_glitch_filter_group.hw, filter_id, false); + filter->fsm = GLITCH_FILTER_FSM_INIT; + return ESP_OK; +} + +esp_err_t gpio_new_flex_glitch_filter(const gpio_flex_glitch_filter_config_t *config, gpio_glitch_filter_handle_t *ret_filter) +{ + esp_err_t ret = ESP_OK; + gpio_flex_glitch_filter_t *filter = NULL; + ESP_GOTO_ON_FALSE(config && ret_filter, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); + ESP_GOTO_ON_FALSE(GPIO_IS_VALID_GPIO(config->gpio_num), ESP_ERR_INVALID_ARG, err, TAG, "invalid gpio number"); + // Glitch filter's clock source is same to the IOMUX clock + // TODO: IDF-6345 task will make the IOMUX clock source configurable, and we should opt the glitch filter clock source accordingly + uint32_t clk_freq_mhz = esp_clk_xtal_freq() / 1000000; + uint32_t window_thres_ticks = clk_freq_mhz * config->window_thres_ns / 1000; + uint32_t window_width_ticks = clk_freq_mhz * config->window_width_ns / 1000; + ESP_GOTO_ON_FALSE(window_thres_ticks && window_thres_ticks <= window_width_ticks && window_width_ticks <= GPIO_LL_GLITCH_FILTER_MAX_WINDOW, + ESP_ERR_INVALID_ARG, err, TAG, "invalid or out of range window width/threshold"); + + filter = heap_caps_calloc(1, sizeof(gpio_flex_glitch_filter_t), FILTER_MEM_ALLOC_CAPS); + ESP_GOTO_ON_FALSE(filter, ESP_ERR_NO_MEM, err, TAG, "no memory for flex glitch filter"); + // register the filter to the group + ESP_GOTO_ON_ERROR(gpio_filter_register_to_group(filter), err, TAG, "register filter to group failed"); + int filter_id = filter->filter_id; + + // make sure the filter is disabled + gpio_ll_glitch_filter_enable(s_gpio_glitch_filter_group.hw, filter_id, false); + // apply the filter to the GPIO + gpio_ll_glitch_filter_set_gpio(s_gpio_glitch_filter_group.hw, filter_id, config->gpio_num); + // set filter coefficient + gpio_ll_glitch_filter_set_window_coeff(s_gpio_glitch_filter_group.hw, filter_id, window_width_ticks, window_thres_ticks); + + filter->base.gpio_num = config->gpio_num; + filter->base.fsm = GLITCH_FILTER_FSM_INIT; + filter->base.del = gpio_flex_glitch_filter_del; + filter->base.enable = gpio_flex_glitch_filter_enable; + filter->base.disable = gpio_flex_glitch_filter_disable; + + *ret_filter = &(filter->base); + return ESP_OK; +err: + if (filter) { + gpio_filter_destroy(filter); + } + return ret; +} diff --git a/components/driver/gpio/gpio_glitch_filter_ops.c b/components/driver/gpio/gpio_glitch_filter_ops.c new file mode 100644 index 0000000000..841d095326 --- /dev/null +++ b/components/driver/gpio/gpio_glitch_filter_ops.c @@ -0,0 +1,30 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp_check.h" +#include "glitch_filter_priv.h" + +static const char *TAG = "gpio-filter"; + +/////////// Public abstract functions /////////// + +esp_err_t gpio_del_glitch_filter(gpio_glitch_filter_handle_t filter) +{ + ESP_RETURN_ON_FALSE(filter, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + return filter->del(filter); +} + +esp_err_t gpio_glitch_filter_enable(gpio_glitch_filter_handle_t filter) +{ + ESP_RETURN_ON_FALSE(filter, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + return filter->enable(filter); +} + +esp_err_t gpio_glitch_filter_disable(gpio_glitch_filter_handle_t filter) +{ + ESP_RETURN_ON_FALSE(filter, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + return filter->disable(filter); +} diff --git a/components/driver/gpio/gpio_pin_glitch_filter.c b/components/driver/gpio/gpio_pin_glitch_filter.c new file mode 100644 index 0000000000..e2068ba74d --- /dev/null +++ b/components/driver/gpio/gpio_pin_glitch_filter.c @@ -0,0 +1,69 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "freertos/FreeRTOS.h" +#include "esp_check.h" +#include "glitch_filter_priv.h" +#include "hal/gpio_ll.h" + +static const char *TAG = "gpio-filter"; + +/** + * @brief Type of GPIO pin glitch filter + */ +typedef struct gpio_pin_glitch_filter_t { + gpio_glitch_filter_t base; +} gpio_pin_glitch_filter_t; + +static esp_err_t gpio_pin_glitch_filter_del(gpio_glitch_filter_t *filter) +{ + ESP_RETURN_ON_FALSE(filter->fsm == GLITCH_FILTER_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "filter not in init state"); + gpio_pin_glitch_filter_t *pin_filter = __containerof(filter, gpio_pin_glitch_filter_t, base); + free(pin_filter); + return ESP_OK; +} + +static esp_err_t gpio_pin_glitch_filter_enable(gpio_glitch_filter_t *filter) +{ + ESP_RETURN_ON_FALSE(filter->fsm == GLITCH_FILTER_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "filter not in init state"); + gpio_ll_pin_filter_enable(NULL, filter->gpio_num); + filter->fsm = GLITCH_FILTER_FSM_ENABLE; + return ESP_OK; +} + +static esp_err_t gpio_pin_glitch_filter_disable(gpio_glitch_filter_t *filter) +{ + ESP_RETURN_ON_FALSE(filter->fsm == GLITCH_FILTER_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "filter not in enable state"); + gpio_ll_pin_filter_disable(NULL, filter->gpio_num); + filter->fsm = GLITCH_FILTER_FSM_INIT; + return ESP_OK; +} + +esp_err_t gpio_new_pin_glitch_filter(const gpio_pin_glitch_filter_config_t *config, gpio_glitch_filter_handle_t *ret_filter) +{ + esp_err_t ret = ESP_OK; + gpio_pin_glitch_filter_t *filter = NULL; + ESP_GOTO_ON_FALSE(config && ret_filter, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); + ESP_GOTO_ON_FALSE(GPIO_IS_VALID_GPIO(config->gpio_num), ESP_ERR_INVALID_ARG, err, TAG, "invalid gpio number"); + + filter = heap_caps_calloc(1, sizeof(gpio_pin_glitch_filter_t), FILTER_MEM_ALLOC_CAPS); + ESP_GOTO_ON_FALSE(filter, ESP_ERR_NO_MEM, err, TAG, "no memory for pin glitch filter"); + + filter->base.gpio_num = config->gpio_num; + filter->base.fsm = GLITCH_FILTER_FSM_INIT; + filter->base.del = gpio_pin_glitch_filter_del; + filter->base.enable = gpio_pin_glitch_filter_enable; + filter->base.disable = gpio_pin_glitch_filter_disable; + + *ret_filter = &(filter->base); + return ESP_OK; +err: + if (filter) { + free(filter); + } + return ret; +} diff --git a/components/driver/include/driver/gpio_filter.h b/components/driver/include/driver/gpio_filter.h new file mode 100644 index 0000000000..7ee33432ba --- /dev/null +++ b/components/driver/include/driver/gpio_filter.h @@ -0,0 +1,112 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include "esp_err.h" +#include "driver/gpio.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Typedef of GPIO glitch filter handle + */ +typedef struct gpio_glitch_filter_t *gpio_glitch_filter_handle_t; + +/** + * @brief Configuration of GPIO pin glitch filter + */ +typedef struct { + gpio_num_t gpio_num; /*!< GPIO number */ +} gpio_pin_glitch_filter_config_t; + +/** + * @brief Create a pin glitch filter + * + * @note Pin glitch filter parameters are fixed, pulses shorter than two sample clocks (IO-MUX's source clock) will be filtered out. + * It's independent with "flex" glitch filter. See also `gpio_new_flex_glitch_filter`. + * @note The created filter handle can later be deleted by `gpio_del_glitch_filter`. + * + * @param[in] config Glitch filter configuration + * @param[out] ret_filter Returned glitch filter handle + * @return + * - ESP_OK: Create a pin glitch filter successfully + * - ESP_ERR_INVALID_ARG: Create a pin glitch filter failed because of invalid arguments (e.g. wrong GPIO number) + * - ESP_ERR_NO_MEM: Create a pin glitch filter failed because of out of memory + * - ESP_FAIL: Create a pin glitch filter failed because of other error + */ +esp_err_t gpio_new_pin_glitch_filter(const gpio_pin_glitch_filter_config_t *config, gpio_glitch_filter_handle_t *ret_filter); + +/** + * @brief Configuration of GPIO flex glitch filter + */ +typedef struct { + gpio_num_t gpio_num; /*!< GPIO number */ + uint32_t window_width_ns; /*!< Sample window width (in ns) */ + uint32_t window_thres_ns; /*!< Sample window threshold (in ns), during the `window_width_ns` sample window, any pulse whose width < window_thres_ns will be discarded. */ +} gpio_flex_glitch_filter_config_t; + +/** + * @brief Allocate a flex glitch filter + * + * @note "flex" means the filter parameters (window, threshold) are adjustable. It's independent with pin glitch filter. + * See also `gpio_new_pin_glitch_filter`. + * @note The created filter handle can later be deleted by `gpio_del_glitch_filter`. + * + * @param[in] config Glitch filter configuration + * @param[out] ret_filter Returned glitch filter handle + * @return + * - ESP_OK: Allocate a flex glitch filter successfully + * - ESP_ERR_INVALID_ARG: Allocate a flex glitch filter failed because of invalid arguments (e.g. wrong GPIO number, filter parameters out of range) + * - ESP_ERR_NO_MEM: Allocate a flex glitch filter failed because of out of memory + * - ESP_ERR_NOT_FOUND: Allocate a flex glitch filter failed because the underlying hardware resources are used up + * - ESP_FAIL: Allocate a flex glitch filter failed because of other error + */ +esp_err_t gpio_new_flex_glitch_filter(const gpio_flex_glitch_filter_config_t *config, gpio_glitch_filter_handle_t *ret_filter); + +/** + * @brief Delete a glitch filter + * + * @param[in] filter Glitch filter handle returned from `gpio_new_flex_glitch_filter` or `gpio_new_pin_glitch_filter` + * @return + * - ESP_OK: Delete glitch filter successfully + * - ESP_ERR_INVALID_ARG: Delete glitch filter failed because of invalid arguments + * - ESP_ERR_INVALID_STATE: Delete glitch filter failed because the glitch filter is still in working + * - ESP_FAIL: Delete glitch filter failed because of other error + */ +esp_err_t gpio_del_glitch_filter(gpio_glitch_filter_handle_t filter); + +/** + * @brief Enable a glitch filter + * + * @param[in] filter Glitch filter handle returned from `gpio_new_flex_glitch_filter` or `gpio_new_pin_glitch_filter` + * @return + * - ESP_OK: Enable glitch filter successfully + * - ESP_ERR_INVALID_ARG: Enable glitch filter failed because of invalid arguments + * - ESP_ERR_INVALID_STATE: Enable glitch filter failed because the glitch filter is already enabled + * - ESP_FAIL: Enable glitch filter failed because of other error + */ +esp_err_t gpio_glitch_filter_enable(gpio_glitch_filter_handle_t filter); + +/** + * @brief Disable a glitch filter + * + * @param[in] filter Glitch filter handle returned from `gpio_new_flex_glitch_filter` or `gpio_new_pin_glitch_filter` + * @return + * - ESP_OK: Disable glitch filter successfully + * - ESP_ERR_INVALID_ARG: Disable glitch filter failed because of invalid arguments + * - ESP_ERR_INVALID_STATE: Disable glitch filter failed because the glitch filter is not enabled yet + * - ESP_FAIL: Disable glitch filter failed because of other error + */ +esp_err_t gpio_glitch_filter_disable(gpio_glitch_filter_handle_t filter); + +#ifdef __cplusplus +} +#endif diff --git a/components/driver/test_apps/gpio/main/CMakeLists.txt b/components/driver/test_apps/gpio/main/CMakeLists.txt index 60cb6effa6..09dabd06a5 100644 --- a/components/driver/test_apps/gpio/main/CMakeLists.txt +++ b/components/driver/test_apps/gpio/main/CMakeLists.txt @@ -1,6 +1,10 @@ set(srcs "test_app_main.c" "test_gpio.c") +if(CONFIG_SOC_GPIO_SUPPORT_PIN_GLITCH_FILTER OR (CONFIG_SOC_GPIO_FLEX_GLITCH_FILTER_NUM GREATER 0)) + list(APPEND srcs "test_gpio_filter.c") +endif() + if(CONFIG_SOC_DEDICATED_GPIO_SUPPORTED) list(APPEND srcs "test_dedicated_gpio.c") endif() diff --git a/components/driver/test_apps/gpio/main/test_gpio_filter.c b/components/driver/test_apps/gpio/main/test_gpio_filter.c new file mode 100644 index 0000000000..345ef6600b --- /dev/null +++ b/components/driver/test_apps/gpio/main/test_gpio_filter.c @@ -0,0 +1,151 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "sdkconfig.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "unity.h" +#include "driver/gpio_filter.h" +#include "driver/dedic_gpio.h" +#include "soc/soc_caps.h" + +#if SOC_GPIO_SUPPORT_PIN_GLITCH_FILTER + +TEST_CASE("GPIO pin glitch filter life cycle", "[gpio_filter]") +{ + gpio_glitch_filter_handle_t filter = NULL; + gpio_pin_glitch_filter_config_t config = {}; + TEST_ESP_OK(gpio_new_pin_glitch_filter(&config, &filter)); + + TEST_ESP_OK(gpio_glitch_filter_enable(filter)); + // can't delete filter if it's not disabled + TEST_ESP_ERR(ESP_ERR_INVALID_STATE, gpio_del_glitch_filter(filter)); + + TEST_ESP_OK(gpio_glitch_filter_disable(filter)); + + TEST_ESP_OK(gpio_del_glitch_filter(filter)); +} + +#endif // SOC_GPIO_SUPPORT_PIN_GLITCH_FILTER + +#if SOC_GPIO_FLEX_GLITCH_FILTER_NUM > 0 + +TEST_CASE("GPIO flex glitch filter life cycle", "[gpio_filter]") +{ + gpio_glitch_filter_handle_t filters[SOC_GPIO_FLEX_GLITCH_FILTER_NUM]; + gpio_flex_glitch_filter_config_t config = {}; + + // install filter with wrong parameters + TEST_ESP_ERR(ESP_ERR_INVALID_ARG, gpio_new_flex_glitch_filter(&config, &filters[0])); + + config.window_thres_ns = 75; + config.window_width_ns = 100; + for (int i = 0; i < SOC_GPIO_FLEX_GLITCH_FILTER_NUM; i++) { + TEST_ESP_OK((gpio_new_flex_glitch_filter(&config, &filters[i]))); + } + // no more hardware resource + TEST_ESP_ERR(ESP_ERR_NOT_FOUND, gpio_new_flex_glitch_filter(&config, &filters[0])); + + TEST_ESP_OK(gpio_glitch_filter_enable(filters[0])); + // can't delete filter if it's not disabled + TEST_ESP_ERR(ESP_ERR_INVALID_STATE, gpio_del_glitch_filter(filters[0])); + TEST_ESP_OK(gpio_glitch_filter_disable(filters[0])); + + for (int i = 0; i < SOC_GPIO_FLEX_GLITCH_FILTER_NUM; i++) { + TEST_ESP_OK(gpio_del_glitch_filter(filters[i])); + } +} + +/** + * @brief In order to generate the short glitch pulse, we use CPU CSR register to control the GPIO level, + * which is also called the Fast GPIO or Dedicated GPIO. + * @note Because the CPU instruction / CSR register is not compatible in all ESP chips, + * at the moment, this test only works for Espressif's RISC-V core (e.g. ESP32C6) + */ +#if SOC_DEDICATED_GPIO_SUPPORTED + +#include "hal/dedic_gpio_cpu_ll.h" + +static void test_gpio_intr_callback(void *args) +{ + SemaphoreHandle_t sem = (SemaphoreHandle_t)args; + BaseType_t high_task_wakeup = pdFALSE; + esp_rom_printf("event fired\r\n"); + xSemaphoreGiveFromISR(sem, &high_task_wakeup); + if (high_task_wakeup) { + esp_rom_printf("high priority task wake up\r\n"); + } +} + +TEST_CASE("GPIO flex glitch filter enable/disable", "[gpio_filter]") +{ + const gpio_num_t test_gpio = 0; + + printf("initialize GPIO for input and out\r\n"); + gpio_config_t gpio_cfg = { + .mode = GPIO_MODE_INPUT_OUTPUT, + .pin_bit_mask = BIT64(test_gpio), + .intr_type = GPIO_INTR_POSEDGE, + .pull_down_en = GPIO_PULLDOWN_ENABLE, + }; + TEST_ESP_OK(gpio_config(&gpio_cfg)); + + printf("install fast gpio to generate the glitch signal\r\n"); + dedic_gpio_bundle_handle_t bundle = NULL; + dedic_gpio_bundle_config_t bundle_cfg = { + .gpio_array = (int[]){test_gpio}, + .array_size = 1, + .flags.out_en = true, + }; + TEST_ESP_OK(dedic_gpio_new_bundle(&bundle_cfg, &bundle)); + // initial output value to zero + asm volatile("csrrci zero, %0, 0x1" :: "i"(CSR_GPIO_OUT_USER)); + + printf("apply glitch filter to the GPIO\r\n"); + gpio_glitch_filter_handle_t filter; + gpio_flex_glitch_filter_config_t filter_cfg = { + .gpio_num = test_gpio, + .window_thres_ns = 1500, // pulse whose width is shorter than 1500 will be filtered out + .window_width_ns = 1500, + }; + TEST_ESP_OK((gpio_new_flex_glitch_filter(&filter_cfg, &filter))); + TEST_ESP_OK(gpio_glitch_filter_enable(filter)); + + printf("install gpio interrupt\r\n"); + gpio_install_isr_service(0); + SemaphoreHandle_t sem = xSemaphoreCreateBinary(); + TEST_ESP_OK(gpio_isr_handler_add(test_gpio, test_gpio_intr_callback, sem)); + + printf("generate rising edge glitch signal\r\n"); + asm volatile("csrrsi zero, %0, 0x1" :: "i"(CSR_GPIO_OUT_USER)); + asm volatile("csrrci zero, %0, 0x1" :: "i"(CSR_GPIO_OUT_USER)); + + // should timeout, because the glitch is filtered out + TEST_ASSERT_EQUAL(pdFALSE, xSemaphoreTake(sem, pdMS_TO_TICKS(1000))); + + printf("disable the glitch filter\r\n"); + TEST_ESP_OK(gpio_glitch_filter_disable(filter)); + + printf("generate rising edge glitch signal again\r\n"); + asm volatile("csrrsi zero, %0, 0x1" :: "i"(CSR_GPIO_OUT_USER)); + asm volatile("csrrci zero, %0, 0x1" :: "i"(CSR_GPIO_OUT_USER)); + + // this time we should see the GPIO interrupt fired up + TEST_ASSERT_EQUAL(pdTRUE, xSemaphoreTake(sem, pdMS_TO_TICKS(1000))); + + TEST_ESP_OK(gpio_isr_handler_remove(test_gpio)); + gpio_uninstall_isr_service(); + + printf("disable gpio glitch filter\r\n"); + TEST_ESP_OK(gpio_del_glitch_filter(filter)); + TEST_ESP_OK(dedic_gpio_del_bundle(bundle)); + vSemaphoreDelete(sem); +} + +#endif // SOC_DEDICATED_GPIO_SUPPORTED +#endif // SOC_GPIO_FLEX_GLITCH_FILTER_NUM > 0 diff --git a/components/hal/esp32c2/include/hal/gpio_ll.h b/components/hal/esp32c2/include/hal/gpio_ll.h index 1d4c93cf90..fe6a2f4e9e 100644 --- a/components/hal/esp32c2/include/hal/gpio_ll.h +++ b/components/hal/esp32c2/include/hal/gpio_ll.h @@ -185,7 +185,29 @@ static inline void gpio_ll_input_disable(gpio_dev_t *hw, uint32_t gpio_num) */ static inline void gpio_ll_input_enable(gpio_dev_t *hw, uint32_t gpio_num) { - PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[gpio_num]); + PIN_INPUT_ENABLE(IO_MUX_GPIO0_REG + (gpio_num * 4)); +} + +/** + * @brief Enable GPIO pin filter + * + * @param hw Peripheral GPIO hardware instance address. + * @param gpio_num GPIO number of the pad. + */ +static inline void gpio_ll_pin_filter_enable(gpio_dev_t *hw, uint32_t gpio_num) +{ + PIN_FILTER_EN(IO_MUX_GPIO0_REG + (gpio_num * 4)); +} + +/** + * @brief Disable GPIO pin filter + * + * @param hw Peripheral GPIO hardware instance address. + * @param gpio_num GPIO number of the pad. + */ +static inline void gpio_ll_pin_filter_disable(gpio_dev_t *hw, uint32_t gpio_num) +{ + PIN_FILTER_DIS(IO_MUX_GPIO0_REG + (gpio_num * 4)); } /** diff --git a/components/hal/esp32c3/include/hal/gpio_ll.h b/components/hal/esp32c3/include/hal/gpio_ll.h index e5d1ad1841..d3b5bd7ea9 100644 --- a/components/hal/esp32c3/include/hal/gpio_ll.h +++ b/components/hal/esp32c3/include/hal/gpio_ll.h @@ -193,7 +193,29 @@ static inline void gpio_ll_input_disable(gpio_dev_t *hw, uint32_t gpio_num) */ static inline void gpio_ll_input_enable(gpio_dev_t *hw, uint32_t gpio_num) { - PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[gpio_num]); + PIN_INPUT_ENABLE(IO_MUX_GPIO0_REG + (gpio_num * 4)); +} + +/** + * @brief Enable GPIO pin filter + * + * @param hw Peripheral GPIO hardware instance address. + * @param gpio_num GPIO number of the pad. + */ +static inline void gpio_ll_pin_filter_enable(gpio_dev_t *hw, uint32_t gpio_num) +{ + PIN_FILTER_EN(IO_MUX_GPIO0_REG + (gpio_num * 4)); +} + +/** + * @brief Disable GPIO pin filter + * + * @param hw Peripheral GPIO hardware instance address. + * @param gpio_num GPIO number of the pad. + */ +static inline void gpio_ll_pin_filter_disable(gpio_dev_t *hw, uint32_t gpio_num) +{ + PIN_FILTER_DIS(IO_MUX_GPIO0_REG + (gpio_num * 4)); } /** diff --git a/components/hal/esp32c6/include/hal/gpio_glitch_filter_ll.h b/components/hal/esp32c6/include/hal/gpio_glitch_filter_ll.h new file mode 100644 index 0000000000..7823060765 --- /dev/null +++ b/components/hal/esp32c6/include/hal/gpio_glitch_filter_ll.h @@ -0,0 +1,66 @@ +/* + * SPDX-FileCopyrightText: 2022 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 + ******************************************************************************/ + +#pragma once + +#include +#include "hal/assert.h" +#include "soc/gpio_ext_struct.h" + +#define GPIO_LL_GLITCH_FILTER_MAX_WINDOW 64 + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Enable GPIO glitch filter + * + * @param hw Glitch filter register base address + * @param filter_idx Glitch filter index + * @param enable True to enable, false to disable + */ +static inline void gpio_ll_glitch_filter_enable(gpio_glitch_filter_dev_t *hw, uint32_t filter_idx, bool enable) +{ + hw->glitch_filter_chn[filter_idx].filter_chn_en = enable; +} + +/** + * @brief Set the input GPIO for the glitch filter + * + * @param hw Glitch filter register base address + * @param filter_idx Glitch filter index + * @param gpio_num GPIO number + */ +static inline void gpio_ll_glitch_filter_set_gpio(gpio_glitch_filter_dev_t *hw, uint32_t filter_idx, uint32_t gpio_num) +{ + hw->glitch_filter_chn[filter_idx].filter_chn_input_io_num = gpio_num; +} + +/** + * @brief Set the coefficient of the glitch filter window + * + * @param hw Glitch filter register base address + * @param filter_idx Glitch filter index + * @param window_width Window width, in IOMUX clock ticks + * @param window_threshold Window threshold, in IOMUX clock ticks + */ +static inline void gpio_ll_glitch_filter_set_window_coeff(gpio_glitch_filter_dev_t *hw, uint32_t filter_idx, uint32_t window_width, uint32_t window_thres) +{ + HAL_ASSERT(window_thres <= window_width); + hw->glitch_filter_chn[filter_idx].filter_chn_window_width = window_width - 1; + hw->glitch_filter_chn[filter_idx].filter_chn_window_thres = window_thres - 1; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32c6/include/hal/gpio_ll.h b/components/hal/esp32c6/include/hal/gpio_ll.h index ea085f2315..05b7b9445b 100644 --- a/components/hal/esp32c6/include/hal/gpio_ll.h +++ b/components/hal/esp32c6/include/hal/gpio_ll.h @@ -201,6 +201,28 @@ static inline void gpio_ll_input_enable(gpio_dev_t *hw, uint32_t gpio_num) PIN_INPUT_ENABLE(IO_MUX_GPIO0_REG + (gpio_num * 4)); } +/** + * @brief Enable GPIO pin filter + * + * @param hw Peripheral GPIO hardware instance address. + * @param gpio_num GPIO number of the pad. + */ +static inline void gpio_ll_pin_filter_enable(gpio_dev_t *hw, uint32_t gpio_num) +{ + PIN_FILTER_EN(IO_MUX_GPIO0_REG + (gpio_num * 4)); +} + +/** + * @brief Disable GPIO pin filter + * + * @param hw Peripheral GPIO hardware instance address. + * @param gpio_num GPIO number of the pad. + */ +static inline void gpio_ll_pin_filter_disable(gpio_dev_t *hw, uint32_t gpio_num) +{ + PIN_FILTER_DIS(IO_MUX_GPIO0_REG + (gpio_num * 4)); +} + /** * @brief Disable output mode on GPIO. * diff --git a/components/hal/esp32h4/include/rev1/hal/gpio_ll.h b/components/hal/esp32h4/include/rev1/hal/gpio_ll.h index b19fcd778a..26bbfdc13e 100644 --- a/components/hal/esp32h4/include/rev1/hal/gpio_ll.h +++ b/components/hal/esp32h4/include/rev1/hal/gpio_ll.h @@ -193,6 +193,28 @@ static inline void gpio_ll_input_enable(gpio_dev_t *hw, uint32_t gpio_num) PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[gpio_num]); } +/** + * @brief Enable GPIO pin filter + * + * @param hw Peripheral GPIO hardware instance address. + * @param gpio_num GPIO number of the pad. + */ +static inline void gpio_ll_pin_filter_enable(gpio_dev_t *hw, uint32_t gpio_num) +{ + PIN_FILTER_EN(GPIO_PIN_MUX_REG[gpio_num]); +} + +/** + * @brief Disable GPIO pin filter + * + * @param hw Peripheral GPIO hardware instance address. + * @param gpio_num GPIO number of the pad. + */ +static inline void gpio_ll_pin_filter_disable(gpio_dev_t *hw, uint32_t gpio_num) +{ + PIN_FILTER_DIS(GPIO_PIN_MUX_REG[gpio_num]); +} + /** * @brief Disable output mode on GPIO. * diff --git a/components/hal/esp32h4/include/rev2/hal/gpio_ll.h b/components/hal/esp32h4/include/rev2/hal/gpio_ll.h index dde3843f7a..8ff1a3fc1a 100644 --- a/components/hal/esp32h4/include/rev2/hal/gpio_ll.h +++ b/components/hal/esp32h4/include/rev2/hal/gpio_ll.h @@ -193,6 +193,28 @@ static inline void gpio_ll_input_enable(gpio_dev_t *hw, uint32_t gpio_num) PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[gpio_num]); } +/** + * @brief Enable GPIO pin filter + * + * @param hw Peripheral GPIO hardware instance address. + * @param gpio_num GPIO number of the pad. + */ +static inline void gpio_ll_pin_filter_enable(gpio_dev_t *hw, uint32_t gpio_num) +{ + PIN_FILTER_EN(GPIO_PIN_MUX_REG[gpio_num]); +} + +/** + * @brief Disable GPIO pin filter + * + * @param hw Peripheral GPIO hardware instance address. + * @param gpio_num GPIO number of the pad. + */ +static inline void gpio_ll_pin_filter_disable(gpio_dev_t *hw, uint32_t gpio_num) +{ + PIN_FILTER_DIS(GPIO_PIN_MUX_REG[gpio_num]); +} + /** * @brief Disable output mode on GPIO. * @@ -558,7 +580,7 @@ static inline void gpio_ll_sleep_output_enable(gpio_dev_t *hw, uint32_t gpio_num static inline void gpio_ll_deepsleep_wakeup_enable(gpio_dev_t *hw, uint32_t gpio_num, gpio_int_type_t intr_type) { HAL_ASSERT((gpio_num >= GPIO_NUM_7 && gpio_num <= GPIO_NUM_12) && - "only gpio7~12 support deep sleep wake-up function"); + "only gpio7~12 support deep sleep wake-up function"); REG_SET_BIT(RTC_CNTL_GPIO_WAKEUP_REG, RTC_CNTL_GPIO_PIN_CLK_GATE); REG_SET_BIT(RTC_CNTL_EXT_WAKEUP_CONF_REG, RTC_CNTL_GPIO_WAKEUP_FILTER); @@ -578,7 +600,7 @@ static inline void gpio_ll_deepsleep_wakeup_enable(gpio_dev_t *hw, uint32_t gpio static inline void gpio_ll_deepsleep_wakeup_disable(gpio_dev_t *hw, uint32_t gpio_num) { HAL_ASSERT((gpio_num >= GPIO_NUM_7 && gpio_num <= GPIO_NUM_12) && - "only gpio7~12 support deep sleep wake-up function"); + "only gpio7~12 support deep sleep wake-up function"); CLEAR_PERI_REG_MASK(RTC_CNTL_GPIO_WAKEUP_REG, 1 << (RTC_CNTL_GPIO_PIN0_WAKEUP_ENABLE_S - (gpio_num - 7))); CLEAR_PERI_REG_MASK(RTC_CNTL_GPIO_WAKEUP_REG, RTC_CNTL_GPIO_PIN0_INT_TYPE_S - (gpio_num - 7) * 3); diff --git a/components/hal/esp32s2/include/hal/gpio_ll.h b/components/hal/esp32s2/include/hal/gpio_ll.h index 75b7c4b0b4..d70b8baf50 100644 --- a/components/hal/esp32s2/include/hal/gpio_ll.h +++ b/components/hal/esp32s2/include/hal/gpio_ll.h @@ -187,7 +187,29 @@ static inline void gpio_ll_input_disable(gpio_dev_t *hw, uint32_t gpio_num) */ static inline void gpio_ll_input_enable(gpio_dev_t *hw, uint32_t gpio_num) { - PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[gpio_num]); + PIN_INPUT_ENABLE(IO_MUX_GPIO0_REG + (gpio_num * 4)); +} + +/** + * @brief Enable GPIO pin filter + * + * @param hw Peripheral GPIO hardware instance address. + * @param gpio_num GPIO number of the pad. + */ +static inline void gpio_ll_pin_filter_enable(gpio_dev_t *hw, uint32_t gpio_num) +{ + PIN_FILTER_EN(IO_MUX_GPIO0_REG + (gpio_num * 4)); +} + +/** + * @brief Disable GPIO pin filter + * + * @param hw Peripheral GPIO hardware instance address. + * @param gpio_num GPIO number of the pad. + */ +static inline void gpio_ll_pin_filter_disable(gpio_dev_t *hw, uint32_t gpio_num) +{ + PIN_FILTER_DIS(IO_MUX_GPIO0_REG + (gpio_num * 4)); } /** diff --git a/components/hal/esp32s3/include/hal/gpio_ll.h b/components/hal/esp32s3/include/hal/gpio_ll.h index 93836fb663..62b4bd1d8c 100644 --- a/components/hal/esp32s3/include/hal/gpio_ll.h +++ b/components/hal/esp32s3/include/hal/gpio_ll.h @@ -200,7 +200,29 @@ static inline void gpio_ll_input_disable(gpio_dev_t *hw, uint32_t gpio_num) */ static inline void gpio_ll_input_enable(gpio_dev_t *hw, uint32_t gpio_num) { - PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[gpio_num]); + PIN_INPUT_ENABLE(IO_MUX_GPIO0_REG + (gpio_num * 4)); +} + +/** + * @brief Enable GPIO pin filter + * + * @param hw Peripheral GPIO hardware instance address. + * @param gpio_num GPIO number of the pad. + */ +static inline void gpio_ll_pin_filter_enable(gpio_dev_t *hw, uint32_t gpio_num) +{ + PIN_FILTER_EN(IO_MUX_GPIO0_REG + (gpio_num * 4)); +} + +/** + * @brief Disable GPIO pin filter + * + * @param hw Peripheral GPIO hardware instance address. + * @param gpio_num GPIO number of the pad. + */ +static inline void gpio_ll_pin_filter_disable(gpio_dev_t *hw, uint32_t gpio_num) +{ + PIN_FILTER_DIS(IO_MUX_GPIO0_REG + (gpio_num * 4)); } /** diff --git a/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in index 54171ea6ac..8e0bd7f712 100644 --- a/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in @@ -207,6 +207,10 @@ config SOC_GPIO_PIN_COUNT int default 21 +config SOC_GPIO_SUPPORT_PIN_GLITCH_FILTER + bool + default y + config SOC_GPIO_SUPPORTS_RTC_INDEPENDENT bool default y diff --git a/components/soc/esp32c2/include/soc/io_mux_reg.h b/components/soc/esp32c2/include/soc/io_mux_reg.h index b610a6e9dd..b54614e477 100644 --- a/components/soc/esp32c2/include/soc/io_mux_reg.h +++ b/components/soc/esp32c2/include/soc/io_mux_reg.h @@ -65,6 +65,11 @@ #define MCU_SEL_M (MCU_SEL_V << MCU_SEL_S) #define MCU_SEL_V 0x7 #define MCU_SEL_S 12 +/* Pin filter (Pulse width shorter than 2 clock cycles will be filtered out) */ +#define FILTER_EN (BIT(15)) +#define FILTER_EN_M (FILTER_EN_V << FILTER_EN_S) +#define FILTER_EN_V 1 +#define FILTER_EN_S 15 #define PIN_SLP_INPUT_ENABLE(PIN_NAME) SET_PERI_REG_MASK(PIN_NAME,SLP_IE) #define PIN_SLP_INPUT_DISABLE(PIN_NAME) CLEAR_PERI_REG_MASK(PIN_NAME,SLP_IE) @@ -78,14 +83,16 @@ #define PIN_SLP_SEL_DISABLE(PIN_NAME) CLEAR_PERI_REG_MASK(PIN_NAME,SLP_SEL) -#define PIN_INPUT_ENABLE(PIN_NAME) SET_PERI_REG_MASK(PIN_NAME,FUN_IE) -#define PIN_INPUT_DISABLE(PIN_NAME) CLEAR_PERI_REG_MASK(PIN_NAME,FUN_IE) -#define PIN_SET_DRV(PIN_NAME, drv) REG_SET_FIELD(PIN_NAME, FUN_DRV, (drv)); -#define PIN_PULLUP_DIS(PIN_NAME) REG_CLR_BIT(PIN_NAME, FUN_PU) -#define PIN_PULLUP_EN(PIN_NAME) REG_SET_BIT(PIN_NAME, FUN_PU) -#define PIN_PULLDWN_DIS(PIN_NAME) REG_CLR_BIT(PIN_NAME, FUN_PD) -#define PIN_PULLDWN_EN(PIN_NAME) REG_SET_BIT(PIN_NAME, FUN_PD) -#define PIN_FUNC_SELECT(PIN_NAME, FUNC) REG_SET_FIELD(PIN_NAME, MCU_SEL, FUNC) +#define PIN_INPUT_ENABLE(PIN_NAME) SET_PERI_REG_MASK(PIN_NAME,FUN_IE) +#define PIN_INPUT_DISABLE(PIN_NAME) CLEAR_PERI_REG_MASK(PIN_NAME,FUN_IE) +#define PIN_SET_DRV(PIN_NAME, drv) REG_SET_FIELD(PIN_NAME, FUN_DRV, (drv)); +#define PIN_PULLUP_DIS(PIN_NAME) REG_CLR_BIT(PIN_NAME, FUN_PU) +#define PIN_PULLUP_EN(PIN_NAME) REG_SET_BIT(PIN_NAME, FUN_PU) +#define PIN_PULLDWN_DIS(PIN_NAME) REG_CLR_BIT(PIN_NAME, FUN_PD) +#define PIN_PULLDWN_EN(PIN_NAME) REG_SET_BIT(PIN_NAME, FUN_PD) +#define PIN_FUNC_SELECT(PIN_NAME, FUNC) REG_SET_FIELD(PIN_NAME, MCU_SEL, FUNC) +#define PIN_FILTER_EN(PIN_NAME) REG_SET_BIT(PIN_NAME, FILTER_EN) +#define PIN_FILTER_DIS(PIN_NAME) REG_CLR_BIT(PIN_NAME, FILTER_EN) #define IO_MUX_GPIO0_REG PERIPHS_IO_MUX_XTAL_32K_P_U #define IO_MUX_GPIO1_REG PERIPHS_IO_MUX_XTAL_32K_N_U diff --git a/components/soc/esp32c2/include/soc/soc_caps.h b/components/soc/esp32c2/include/soc/soc_caps.h index 58da616a01..47a0d42bac 100644 --- a/components/soc/esp32c2/include/soc/soc_caps.h +++ b/components/soc/esp32c2/include/soc/soc_caps.h @@ -102,8 +102,9 @@ /*-------------------------- GPIO CAPS ---------------------------------------*/ // ESP32-C2 has 1 GPIO peripheral -#define SOC_GPIO_PORT (1U) -#define SOC_GPIO_PIN_COUNT (21) +#define SOC_GPIO_PORT 1U +#define SOC_GPIO_PIN_COUNT 21 +#define SOC_GPIO_SUPPORT_PIN_GLITCH_FILTER 1 // Target has no full RTC IO subsystem, so GPIO is 100% "independent" of RTC // On ESP32-C2, Digital IOs have their own registers to control pullup/down capability, independent of RTC registers. diff --git a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in index af535e9290..d328f4a92c 100644 --- a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in @@ -299,6 +299,10 @@ config SOC_GPIO_PIN_COUNT int default 22 +config SOC_GPIO_SUPPORT_PIN_GLITCH_FILTER + bool + default y + config SOC_GPIO_SUPPORTS_RTC_INDEPENDENT bool default y diff --git a/components/soc/esp32c3/include/soc/io_mux_reg.h b/components/soc/esp32c3/include/soc/io_mux_reg.h index 6d5ae6da2f..c814bdd956 100644 --- a/components/soc/esp32c3/include/soc/io_mux_reg.h +++ b/components/soc/esp32c3/include/soc/io_mux_reg.h @@ -64,6 +64,11 @@ #define MCU_SEL_M (MCU_SEL_V << MCU_SEL_S) #define MCU_SEL_V 0x7 #define MCU_SEL_S 12 +/* Pin filter (Pulse width shorter than 2 clock cycles will be filtered out) */ +#define FILTER_EN (BIT(15)) +#define FILTER_EN_M (FILTER_EN_V << FILTER_EN_S) +#define FILTER_EN_V 1 +#define FILTER_EN_S 15 #define PIN_SLP_INPUT_ENABLE(PIN_NAME) SET_PERI_REG_MASK(PIN_NAME,SLP_IE) #define PIN_SLP_INPUT_DISABLE(PIN_NAME) CLEAR_PERI_REG_MASK(PIN_NAME,SLP_IE) @@ -77,14 +82,16 @@ #define PIN_SLP_SEL_DISABLE(PIN_NAME) CLEAR_PERI_REG_MASK(PIN_NAME,SLP_SEL) -#define PIN_INPUT_ENABLE(PIN_NAME) SET_PERI_REG_MASK(PIN_NAME,FUN_IE) -#define PIN_INPUT_DISABLE(PIN_NAME) CLEAR_PERI_REG_MASK(PIN_NAME,FUN_IE) -#define PIN_SET_DRV(PIN_NAME, drv) REG_SET_FIELD(PIN_NAME, FUN_DRV, (drv)); -#define PIN_PULLUP_DIS(PIN_NAME) REG_CLR_BIT(PIN_NAME, FUN_PU) -#define PIN_PULLUP_EN(PIN_NAME) REG_SET_BIT(PIN_NAME, FUN_PU) -#define PIN_PULLDWN_DIS(PIN_NAME) REG_CLR_BIT(PIN_NAME, FUN_PD) -#define PIN_PULLDWN_EN(PIN_NAME) REG_SET_BIT(PIN_NAME, FUN_PD) -#define PIN_FUNC_SELECT(PIN_NAME, FUNC) REG_SET_FIELD(PIN_NAME, MCU_SEL, FUNC) +#define PIN_INPUT_ENABLE(PIN_NAME) SET_PERI_REG_MASK(PIN_NAME,FUN_IE) +#define PIN_INPUT_DISABLE(PIN_NAME) CLEAR_PERI_REG_MASK(PIN_NAME,FUN_IE) +#define PIN_SET_DRV(PIN_NAME, drv) REG_SET_FIELD(PIN_NAME, FUN_DRV, (drv)); +#define PIN_PULLUP_DIS(PIN_NAME) REG_CLR_BIT(PIN_NAME, FUN_PU) +#define PIN_PULLUP_EN(PIN_NAME) REG_SET_BIT(PIN_NAME, FUN_PU) +#define PIN_PULLDWN_DIS(PIN_NAME) REG_CLR_BIT(PIN_NAME, FUN_PD) +#define PIN_PULLDWN_EN(PIN_NAME) REG_SET_BIT(PIN_NAME, FUN_PD) +#define PIN_FUNC_SELECT(PIN_NAME, FUNC) REG_SET_FIELD(PIN_NAME, MCU_SEL, FUNC) +#define PIN_FILTER_EN(PIN_NAME) REG_SET_BIT(PIN_NAME, FILTER_EN) +#define PIN_FILTER_DIS(PIN_NAME) REG_CLR_BIT(PIN_NAME, FILTER_EN) #define IO_MUX_GPIO0_REG PERIPHS_IO_MUX_XTAL_32K_P_U #define IO_MUX_GPIO1_REG PERIPHS_IO_MUX_XTAL_32K_N_U diff --git a/components/soc/esp32c3/include/soc/soc_caps.h b/components/soc/esp32c3/include/soc/soc_caps.h index a443795fdb..9c79e1895d 100644 --- a/components/soc/esp32c3/include/soc/soc_caps.h +++ b/components/soc/esp32c3/include/soc/soc_caps.h @@ -140,8 +140,9 @@ /*-------------------------- GPIO CAPS ---------------------------------------*/ // ESP32-C3 has 1 GPIO peripheral -#define SOC_GPIO_PORT (1U) -#define SOC_GPIO_PIN_COUNT (22) +#define SOC_GPIO_PORT 1U +#define SOC_GPIO_PIN_COUNT 22 +#define SOC_GPIO_SUPPORT_PIN_GLITCH_FILTER 1 // Target has no full RTC IO subsystem, so GPIO is 100% "independent" of RTC // On ESP32-C3, Digital IOs have their own registers to control pullup/down capability, independent of RTC registers. diff --git a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in index 3027883033..244bd789a6 100644 --- a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in @@ -279,6 +279,14 @@ config SOC_GPIO_PIN_COUNT int default 31 +config SOC_GPIO_SUPPORT_PIN_GLITCH_FILTER + bool + default y + +config SOC_GPIO_FLEX_GLITCH_FILTER_NUM + int + default 8 + config SOC_GPIO_SUPPORT_ETM bool default y diff --git a/components/soc/esp32c6/include/soc/gpio_ext_struct.h b/components/soc/esp32c6/include/soc/gpio_ext_struct.h index 7bcb54adf2..1468d5ef2a 100644 --- a/components/soc/esp32c6/include/soc/gpio_ext_struct.h +++ b/components/soc/esp32c6/include/soc/gpio_ext_struct.h @@ -70,22 +70,22 @@ typedef union { */ typedef union { struct { - /** filter_ch0_en : R/W; bitpos: [0]; default: 0; + /** filter_chn_en : R/W; bitpos: [0]; default: 0; * Glitch Filter channel enable bit. */ - uint32_t filter_ch0_en:1; - /** filter_ch0_input_io_num : R/W; bitpos: [6:1]; default: 0; + uint32_t filter_chn_en:1; + /** filter_chn_input_io_num : R/W; bitpos: [6:1]; default: 0; * Glitch Filter input io number. */ - uint32_t filter_ch0_input_io_num:6; - /** filter_ch0_window_thres : R/W; bitpos: [12:7]; default: 0; + uint32_t filter_chn_input_io_num:6; + /** filter_chn_window_thres : R/W; bitpos: [12:7]; default: 0; * Glitch Filter window threshold. */ - uint32_t filter_ch0_window_thres:6; - /** filter_ch0_window_width : R/W; bitpos: [18:13]; default: 0; + uint32_t filter_chn_window_thres:6; + /** filter_chn_window_width : R/W; bitpos: [18:13]; default: 0; * Glitch Filter window width. */ - uint32_t filter_ch0_window_width:6; + uint32_t filter_chn_window_width:6; uint32_t reserved_19:13; }; uint32_t val; diff --git a/components/soc/esp32c6/include/soc/io_mux_reg.h b/components/soc/esp32c6/include/soc/io_mux_reg.h index cbba6b20f4..0e255ac519 100644 --- a/components/soc/esp32c6/include/soc/io_mux_reg.h +++ b/components/soc/esp32c6/include/soc/io_mux_reg.h @@ -63,6 +63,11 @@ #define MCU_SEL_M (MCU_SEL_V << MCU_SEL_S) #define MCU_SEL_V 0x7 #define MCU_SEL_S 12 +/* Pin filter (Pulse width shorter than 2 clock cycles will be filtered out) */ +#define FILTER_EN (BIT(15)) +#define FILTER_EN_M (FILTER_EN_V << FILTER_EN_S) +#define FILTER_EN_V 1 +#define FILTER_EN_S 15 #define PIN_SLP_INPUT_ENABLE(PIN_NAME) SET_PERI_REG_MASK(PIN_NAME,SLP_IE) #define PIN_SLP_INPUT_DISABLE(PIN_NAME) CLEAR_PERI_REG_MASK(PIN_NAME,SLP_IE) @@ -83,6 +88,8 @@ #define PIN_PULLDWN_DIS(PIN_NAME) REG_CLR_BIT(PIN_NAME, FUN_PD) #define PIN_PULLDWN_EN(PIN_NAME) REG_SET_BIT(PIN_NAME, FUN_PD) #define PIN_FUNC_SELECT(PIN_NAME, FUNC) REG_SET_FIELD(PIN_NAME, MCU_SEL, FUNC) +#define PIN_FILTER_EN(PIN_NAME) REG_SET_BIT(PIN_NAME, FILTER_EN) +#define PIN_FILTER_DIS(PIN_NAME) REG_CLR_BIT(PIN_NAME, FILTER_EN) #define IO_MUX_GPIO0_REG PERIPHS_IO_MUX_XTAL_32K_P_U #define IO_MUX_GPIO1_REG PERIPHS_IO_MUX_XTAL_32K_N_U diff --git a/components/soc/esp32c6/include/soc/soc_caps.h b/components/soc/esp32c6/include/soc/soc_caps.h index e0a5075abf..0f9d99c411 100644 --- a/components/soc/esp32c6/include/soc/soc_caps.h +++ b/components/soc/esp32c6/include/soc/soc_caps.h @@ -150,8 +150,10 @@ /*-------------------------- GPIO CAPS ---------------------------------------*/ // ESP32-C6 has 1 GPIO peripheral -#define SOC_GPIO_PORT (1U) -#define SOC_GPIO_PIN_COUNT (31) +#define SOC_GPIO_PORT 1U +#define SOC_GPIO_PIN_COUNT 31 +#define SOC_GPIO_SUPPORT_PIN_GLITCH_FILTER 1 +#define SOC_GPIO_FLEX_GLITCH_FILTER_NUM 8 // GPIO peripheral has the ETM extension #define SOC_GPIO_SUPPORT_ETM 1 diff --git a/components/soc/esp32h4/include/rev1/soc/io_mux_reg.h b/components/soc/esp32h4/include/rev1/soc/io_mux_reg.h index 62bcd9ac29..45aad3cdb8 100644 --- a/components/soc/esp32h4/include/rev1/soc/io_mux_reg.h +++ b/components/soc/esp32h4/include/rev1/soc/io_mux_reg.h @@ -64,6 +64,11 @@ #define MCU_SEL_M (MCU_SEL_V << MCU_SEL_S) #define MCU_SEL_V 0x7 #define MCU_SEL_S 12 +/* Pin filter (Pulse width shorter than 2 clock cycles will be filtered out) */ +#define FILTER_EN (BIT(15)) +#define FILTER_EN_M (FILTER_EN_V << FILTER_EN_S) +#define FILTER_EN_V 1 +#define FILTER_EN_S 15 #define PIN_SLP_INPUT_ENABLE(PIN_NAME) SET_PERI_REG_MASK(PIN_NAME,SLP_IE) #define PIN_SLP_INPUT_DISABLE(PIN_NAME) CLEAR_PERI_REG_MASK(PIN_NAME,SLP_IE) @@ -77,14 +82,16 @@ #define PIN_SLP_SEL_DISABLE(PIN_NAME) CLEAR_PERI_REG_MASK(PIN_NAME,SLP_SEL) -#define PIN_INPUT_ENABLE(PIN_NAME) SET_PERI_REG_MASK(PIN_NAME,FUN_IE) -#define PIN_INPUT_DISABLE(PIN_NAME) CLEAR_PERI_REG_MASK(PIN_NAME,FUN_IE) -#define PIN_SET_DRV(PIN_NAME, drv) REG_SET_FIELD(PIN_NAME, FUN_DRV, (drv)); -#define PIN_PULLUP_DIS(PIN_NAME) REG_CLR_BIT(PIN_NAME, FUN_PU) -#define PIN_PULLUP_EN(PIN_NAME) REG_SET_BIT(PIN_NAME, FUN_PU) -#define PIN_PULLDWN_DIS(PIN_NAME) REG_CLR_BIT(PIN_NAME, FUN_PD) -#define PIN_PULLDWN_EN(PIN_NAME) REG_SET_BIT(PIN_NAME, FUN_PD) -#define PIN_FUNC_SELECT(PIN_NAME, FUNC) REG_SET_FIELD(PIN_NAME, MCU_SEL, FUNC) +#define PIN_INPUT_ENABLE(PIN_NAME) SET_PERI_REG_MASK(PIN_NAME,FUN_IE) +#define PIN_INPUT_DISABLE(PIN_NAME) CLEAR_PERI_REG_MASK(PIN_NAME,FUN_IE) +#define PIN_SET_DRV(PIN_NAME, drv) REG_SET_FIELD(PIN_NAME, FUN_DRV, (drv)); +#define PIN_PULLUP_DIS(PIN_NAME) REG_CLR_BIT(PIN_NAME, FUN_PU) +#define PIN_PULLUP_EN(PIN_NAME) REG_SET_BIT(PIN_NAME, FUN_PU) +#define PIN_PULLDWN_DIS(PIN_NAME) REG_CLR_BIT(PIN_NAME, FUN_PD) +#define PIN_PULLDWN_EN(PIN_NAME) REG_SET_BIT(PIN_NAME, FUN_PD) +#define PIN_FUNC_SELECT(PIN_NAME, FUNC) REG_SET_FIELD(PIN_NAME, MCU_SEL, FUNC) +#define PIN_FILTER_EN(PIN_NAME) REG_SET_BIT(PIN_NAME, FILTER_EN) +#define PIN_FILTER_DIS(PIN_NAME) REG_CLR_BIT(PIN_NAME, FILTER_EN) #define IO_MUX_GPIO0_REG PERIPHS_IO_MUX_XTAL_32K_P_U #define IO_MUX_GPIO1_REG PERIPHS_IO_MUX_XTAL_32K_N_U diff --git a/components/soc/esp32h4/include/rev2/soc/io_mux_reg.h b/components/soc/esp32h4/include/rev2/soc/io_mux_reg.h index 4182513522..9b5ae4f4dc 100644 --- a/components/soc/esp32h4/include/rev2/soc/io_mux_reg.h +++ b/components/soc/esp32h4/include/rev2/soc/io_mux_reg.h @@ -63,6 +63,11 @@ #define MCU_SEL_M (MCU_SEL_V << MCU_SEL_S) #define MCU_SEL_V 0x7 #define MCU_SEL_S 12 +/* Pin filter (Pulse width shorter than 2 clock cycles will be filtered out) */ +#define FILTER_EN (BIT(15)) +#define FILTER_EN_M (FILTER_EN_V << FILTER_EN_S) +#define FILTER_EN_V 1 +#define FILTER_EN_S 15 #define PIN_SLP_INPUT_ENABLE(PIN_NAME) SET_PERI_REG_MASK(PIN_NAME,SLP_IE) #define PIN_SLP_INPUT_DISABLE(PIN_NAME) CLEAR_PERI_REG_MASK(PIN_NAME,SLP_IE) @@ -75,14 +80,16 @@ #define PIN_SLP_SEL_ENABLE(PIN_NAME) SET_PERI_REG_MASK(PIN_NAME,SLP_SEL) #define PIN_SLP_SEL_DISABLE(PIN_NAME) CLEAR_PERI_REG_MASK(PIN_NAME,SLP_SEL) -#define PIN_INPUT_ENABLE(PIN_NAME) SET_PERI_REG_MASK(PIN_NAME,FUN_IE) -#define PIN_INPUT_DISABLE(PIN_NAME) CLEAR_PERI_REG_MASK(PIN_NAME,FUN_IE) -#define PIN_SET_DRV(PIN_NAME, drv) REG_SET_FIELD(PIN_NAME, FUN_DRV, (drv)); -#define PIN_PULLUP_DIS(PIN_NAME) REG_CLR_BIT(PIN_NAME, FUN_PU) -#define PIN_PULLUP_EN(PIN_NAME) REG_SET_BIT(PIN_NAME, FUN_PU) -#define PIN_PULLDWN_DIS(PIN_NAME) REG_CLR_BIT(PIN_NAME, FUN_PD) -#define PIN_PULLDWN_EN(PIN_NAME) REG_SET_BIT(PIN_NAME, FUN_PD) -#define PIN_FUNC_SELECT(PIN_NAME, FUNC) REG_SET_FIELD(PIN_NAME, MCU_SEL, FUNC) +#define PIN_INPUT_ENABLE(PIN_NAME) SET_PERI_REG_MASK(PIN_NAME,FUN_IE) +#define PIN_INPUT_DISABLE(PIN_NAME) CLEAR_PERI_REG_MASK(PIN_NAME,FUN_IE) +#define PIN_SET_DRV(PIN_NAME, drv) REG_SET_FIELD(PIN_NAME, FUN_DRV, (drv)); +#define PIN_PULLUP_DIS(PIN_NAME) REG_CLR_BIT(PIN_NAME, FUN_PU) +#define PIN_PULLUP_EN(PIN_NAME) REG_SET_BIT(PIN_NAME, FUN_PU) +#define PIN_PULLDWN_DIS(PIN_NAME) REG_CLR_BIT(PIN_NAME, FUN_PD) +#define PIN_PULLDWN_EN(PIN_NAME) REG_SET_BIT(PIN_NAME, FUN_PD) +#define PIN_FUNC_SELECT(PIN_NAME, FUNC) REG_SET_FIELD(PIN_NAME, MCU_SEL, FUNC) +#define PIN_FILTER_EN(PIN_NAME) REG_SET_BIT(PIN_NAME, FILTER_EN) +#define PIN_FILTER_DIS(PIN_NAME) REG_CLR_BIT(PIN_NAME, FILTER_EN) #define IO_MUX_GPIO0_REG PERIPHS_IO_MUX_GPIO0_U #define IO_MUX_GPIO1_REG PERIPHS_IO_MUX_GPIO1_U diff --git a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in index b30588649f..3edca105ed 100644 --- a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in @@ -271,6 +271,10 @@ config SOC_GPIO_PORT int default 1 +config SOC_GPIO_SUPPORT_PIN_GLITCH_FILTER + bool + default y + config SOC_GPIO_PIN_COUNT int default 41 diff --git a/components/soc/esp32h4/include/soc/soc_caps.h b/components/soc/esp32h4/include/soc/soc_caps.h index c990716955..d7772eeed4 100644 --- a/components/soc/esp32h4/include/soc/soc_caps.h +++ b/components/soc/esp32h4/include/soc/soc_caps.h @@ -137,7 +137,9 @@ /*-------------------------- GPIO CAPS ---------------------------------------*/ // ESP32-H4 has 1 GPIO peripheral -#define SOC_GPIO_PORT (1U) +#define SOC_GPIO_PORT 1U +#define SOC_GPIO_SUPPORT_PIN_GLITCH_FILTER 1 + #if CONFIG_IDF_TARGET_ESP32H4_BETA_VERSION_1 #define SOC_GPIO_PIN_COUNT (41) #elif CONFIG_IDF_TARGET_ESP32H4_BETA_VERSION_2 diff --git a/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in index bc7f711550..35e159f3b3 100644 --- a/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in @@ -283,6 +283,10 @@ config SOC_GPIO_PIN_COUNT int default 47 +config SOC_GPIO_SUPPORT_PIN_GLITCH_FILTER + bool + default y + config SOC_GPIO_SUPPORT_RTC_INDEPENDENT bool default y diff --git a/components/soc/esp32s2/include/soc/io_mux_reg.h b/components/soc/esp32s2/include/soc/io_mux_reg.h index 0ba1eb17ff..18a3da1c64 100644 --- a/components/soc/esp32s2/include/soc/io_mux_reg.h +++ b/components/soc/esp32s2/include/soc/io_mux_reg.h @@ -64,26 +64,33 @@ #define MCU_SEL_M (MCU_SEL_V << MCU_SEL_S) #define MCU_SEL_V 0x7 #define MCU_SEL_S 12 +/* Pin filter (Pulse width shorter than 2 clock cycles will be filtered out) */ +#define FILTER_EN (BIT(15)) +#define FILTER_EN_M (FILTER_EN_V << FILTER_EN_S) +#define FILTER_EN_V 1 +#define FILTER_EN_S 15 -#define PIN_SLP_INPUT_ENABLE(PIN_NAME) SET_PERI_REG_MASK(PIN_NAME,SLP_IE) -#define PIN_SLP_INPUT_DISABLE(PIN_NAME) CLEAR_PERI_REG_MASK(PIN_NAME,SLP_IE) -#define PIN_SLP_OUTPUT_ENABLE(PIN_NAME) SET_PERI_REG_MASK(PIN_NAME,SLP_OE) -#define PIN_SLP_OUTPUT_DISABLE(PIN_NAME) CLEAR_PERI_REG_MASK(PIN_NAME,SLP_OE) -#define PIN_SLP_PULLUP_ENABLE(PIN_NAME) SET_PERI_REG_MASK(PIN_NAME,SLP_PU) -#define PIN_SLP_PULLUP_DISABLE(PIN_NAME) CLEAR_PERI_REG_MASK(PIN_NAME,SLP_PU) -#define PIN_SLP_PULLDOWN_ENABLE(PIN_NAME) SET_PERI_REG_MASK(PIN_NAME,SLP_PD) -#define PIN_SLP_PULLDOWN_DISABLE(PIN_NAME) CLEAR_PERI_REG_MASK(PIN_NAME,SLP_PD) -#define PIN_SLP_SEL_ENABLE(PIN_NAME) SET_PERI_REG_MASK(PIN_NAME,SLP_SEL) -#define PIN_SLP_SEL_DISABLE(PIN_NAME) CLEAR_PERI_REG_MASK(PIN_NAME,SLP_SEL) +#define PIN_SLP_INPUT_ENABLE(PIN_NAME) SET_PERI_REG_MASK(PIN_NAME,SLP_IE) +#define PIN_SLP_INPUT_DISABLE(PIN_NAME) CLEAR_PERI_REG_MASK(PIN_NAME,SLP_IE) +#define PIN_SLP_OUTPUT_ENABLE(PIN_NAME) SET_PERI_REG_MASK(PIN_NAME,SLP_OE) +#define PIN_SLP_OUTPUT_DISABLE(PIN_NAME) CLEAR_PERI_REG_MASK(PIN_NAME,SLP_OE) +#define PIN_SLP_PULLUP_ENABLE(PIN_NAME) SET_PERI_REG_MASK(PIN_NAME,SLP_PU) +#define PIN_SLP_PULLUP_DISABLE(PIN_NAME) CLEAR_PERI_REG_MASK(PIN_NAME,SLP_PU) +#define PIN_SLP_PULLDOWN_ENABLE(PIN_NAME) SET_PERI_REG_MASK(PIN_NAME,SLP_PD) +#define PIN_SLP_PULLDOWN_DISABLE(PIN_NAME) CLEAR_PERI_REG_MASK(PIN_NAME,SLP_PD) +#define PIN_SLP_SEL_ENABLE(PIN_NAME) SET_PERI_REG_MASK(PIN_NAME,SLP_SEL) +#define PIN_SLP_SEL_DISABLE(PIN_NAME) CLEAR_PERI_REG_MASK(PIN_NAME,SLP_SEL) -#define PIN_INPUT_ENABLE(PIN_NAME) SET_PERI_REG_MASK(PIN_NAME,FUN_IE) -#define PIN_INPUT_DISABLE(PIN_NAME) CLEAR_PERI_REG_MASK(PIN_NAME,FUN_IE) -#define PIN_SET_DRV(PIN_NAME, drv) REG_SET_FIELD(PIN_NAME, FUN_DRV, (drv)); -#define PIN_PULLUP_DIS(PIN_NAME) REG_CLR_BIT(PIN_NAME, FUN_PU) -#define PIN_PULLUP_EN(PIN_NAME) REG_SET_BIT(PIN_NAME, FUN_PU) -#define PIN_PULLDWN_DIS(PIN_NAME) REG_CLR_BIT(PIN_NAME, FUN_PD) -#define PIN_PULLDWN_EN(PIN_NAME) REG_SET_BIT(PIN_NAME, FUN_PD) -#define PIN_FUNC_SELECT(PIN_NAME, FUNC) REG_SET_FIELD(PIN_NAME, MCU_SEL, FUNC) +#define PIN_INPUT_ENABLE(PIN_NAME) SET_PERI_REG_MASK(PIN_NAME,FUN_IE) +#define PIN_INPUT_DISABLE(PIN_NAME) CLEAR_PERI_REG_MASK(PIN_NAME,FUN_IE) +#define PIN_SET_DRV(PIN_NAME, drv) REG_SET_FIELD(PIN_NAME, FUN_DRV, (drv)); +#define PIN_PULLUP_DIS(PIN_NAME) REG_CLR_BIT(PIN_NAME, FUN_PU) +#define PIN_PULLUP_EN(PIN_NAME) REG_SET_BIT(PIN_NAME, FUN_PU) +#define PIN_PULLDWN_DIS(PIN_NAME) REG_CLR_BIT(PIN_NAME, FUN_PD) +#define PIN_PULLDWN_EN(PIN_NAME) REG_SET_BIT(PIN_NAME, FUN_PD) +#define PIN_FUNC_SELECT(PIN_NAME, FUNC) REG_SET_FIELD(PIN_NAME, MCU_SEL, FUNC) +#define PIN_FILTER_EN(PIN_NAME) REG_SET_BIT(PIN_NAME, FILTER_EN) +#define PIN_FILTER_DIS(PIN_NAME) REG_CLR_BIT(PIN_NAME, FILTER_EN) #define IO_MUX_GPIO0_REG PERIPHS_IO_MUX_GPIO0_U #define IO_MUX_GPIO1_REG PERIPHS_IO_MUX_GPIO1_U diff --git a/components/soc/esp32s2/include/soc/soc_caps.h b/components/soc/esp32s2/include/soc/soc_caps.h index 6470f78a96..9c1c3ee293 100644 --- a/components/soc/esp32s2/include/soc/soc_caps.h +++ b/components/soc/esp32s2/include/soc/soc_caps.h @@ -134,8 +134,9 @@ /*-------------------------- GPIO CAPS ---------------------------------------*/ // ESP32-S2 has 1 GPIO peripheral -#define SOC_GPIO_PORT (1U) -#define SOC_GPIO_PIN_COUNT (47) +#define SOC_GPIO_PORT 1U +#define SOC_GPIO_PIN_COUNT 47 +#define SOC_GPIO_SUPPORT_PIN_GLITCH_FILTER 1 // On ESP32-S2 those PADs which have RTC functions must set pullup/down/capability via RTC register. // On ESP32-S2, Digital IOs have their own registers to control pullup/down/capability, independent with RTC registers. diff --git a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in index 0338fa1b8a..b2bdf24ccf 100644 --- a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in @@ -347,6 +347,10 @@ config SOC_GPIO_PIN_COUNT int default 49 +config SOC_GPIO_SUPPORT_PIN_GLITCH_FILTER + bool + default y + config SOC_GPIO_SUPPORT_RTC_INDEPENDENT bool default y diff --git a/components/soc/esp32s3/include/soc/io_mux_reg.h b/components/soc/esp32s3/include/soc/io_mux_reg.h index e595824e09..b2dfe9eb64 100644 --- a/components/soc/esp32s3/include/soc/io_mux_reg.h +++ b/components/soc/esp32s3/include/soc/io_mux_reg.h @@ -63,6 +63,11 @@ #define MCU_SEL_M (MCU_SEL_V << MCU_SEL_S) #define MCU_SEL_V 0x7 #define MCU_SEL_S 12 +/* Pin filter (Pulse width shorter than 2 clock cycles will be filtered out) */ +#define FILTER_EN (BIT(15)) +#define FILTER_EN_M (FILTER_EN_V << FILTER_EN_S) +#define FILTER_EN_V 1 +#define FILTER_EN_S 15 #define PIN_SLP_INPUT_ENABLE(PIN_NAME) SET_PERI_REG_MASK(PIN_NAME,SLP_IE) #define PIN_SLP_INPUT_DISABLE(PIN_NAME) CLEAR_PERI_REG_MASK(PIN_NAME,SLP_IE) @@ -75,14 +80,16 @@ #define PIN_SLP_SEL_ENABLE(PIN_NAME) SET_PERI_REG_MASK(PIN_NAME,SLP_SEL) #define PIN_SLP_SEL_DISABLE(PIN_NAME) CLEAR_PERI_REG_MASK(PIN_NAME,SLP_SEL) -#define PIN_INPUT_ENABLE(PIN_NAME) SET_PERI_REG_MASK(PIN_NAME,FUN_IE) -#define PIN_INPUT_DISABLE(PIN_NAME) CLEAR_PERI_REG_MASK(PIN_NAME,FUN_IE) -#define PIN_SET_DRV(PIN_NAME, drv) REG_SET_FIELD(PIN_NAME, FUN_DRV, (drv)); -#define PIN_PULLUP_DIS(PIN_NAME) REG_CLR_BIT(PIN_NAME, FUN_PU) -#define PIN_PULLUP_EN(PIN_NAME) REG_SET_BIT(PIN_NAME, FUN_PU) -#define PIN_PULLDWN_DIS(PIN_NAME) REG_CLR_BIT(PIN_NAME, FUN_PD) -#define PIN_PULLDWN_EN(PIN_NAME) REG_SET_BIT(PIN_NAME, FUN_PD) -#define PIN_FUNC_SELECT(PIN_NAME, FUNC) REG_SET_FIELD(PIN_NAME, MCU_SEL, FUNC) +#define PIN_INPUT_ENABLE(PIN_NAME) SET_PERI_REG_MASK(PIN_NAME,FUN_IE) +#define PIN_INPUT_DISABLE(PIN_NAME) CLEAR_PERI_REG_MASK(PIN_NAME,FUN_IE) +#define PIN_SET_DRV(PIN_NAME, drv) REG_SET_FIELD(PIN_NAME, FUN_DRV, (drv)); +#define PIN_PULLUP_DIS(PIN_NAME) REG_CLR_BIT(PIN_NAME, FUN_PU) +#define PIN_PULLUP_EN(PIN_NAME) REG_SET_BIT(PIN_NAME, FUN_PU) +#define PIN_PULLDWN_DIS(PIN_NAME) REG_CLR_BIT(PIN_NAME, FUN_PD) +#define PIN_PULLDWN_EN(PIN_NAME) REG_SET_BIT(PIN_NAME, FUN_PD) +#define PIN_FUNC_SELECT(PIN_NAME, FUNC) REG_SET_FIELD(PIN_NAME, MCU_SEL, FUNC) +#define PIN_FILTER_EN(PIN_NAME) REG_SET_BIT(PIN_NAME, FILTER_EN) +#define PIN_FILTER_DIS(PIN_NAME) REG_CLR_BIT(PIN_NAME, FILTER_EN) #define IO_MUX_GPIO0_REG PERIPHS_IO_MUX_GPIO0_U #define IO_MUX_GPIO1_REG PERIPHS_IO_MUX_GPIO1_U diff --git a/components/soc/esp32s3/include/soc/soc_caps.h b/components/soc/esp32s3/include/soc/soc_caps.h index b6588bc0ec..de2b9abf02 100644 --- a/components/soc/esp32s3/include/soc/soc_caps.h +++ b/components/soc/esp32s3/include/soc/soc_caps.h @@ -142,8 +142,9 @@ /*-------------------------- GPIO CAPS ---------------------------------------*/ // ESP32-S3 has 1 GPIO peripheral -#define SOC_GPIO_PORT (1U) -#define SOC_GPIO_PIN_COUNT (49) +#define SOC_GPIO_PORT 1U +#define SOC_GPIO_PIN_COUNT 49 +#define SOC_GPIO_SUPPORT_PIN_GLITCH_FILTER 1 // On ESP32-S3, Digital IOs have their own registers to control pullup/down/capability, independent with RTC registers. #define SOC_GPIO_SUPPORT_RTC_INDEPENDENT (1)