diff --git a/cpu/esp32/Makefile.dep b/cpu/esp32/Makefile.dep index cb0978229e..f6ffdc9f99 100644 --- a/cpu/esp32/Makefile.dep +++ b/cpu/esp32/Makefile.dep @@ -72,6 +72,10 @@ ifneq (,$(filter periph_adc periph_dac,$(USEMODULE))) FEATURES_REQUIRED += periph_adc_ctrl endif +ifneq (,$(filter periph_gpio,$(USEMODULE))) + USEMODULE += esp_idf_gpio +endif + ifneq (,$(filter periph_i2c,$(USEMODULE))) ifneq (,$(filter esp_i2c_hw,$(USEMODULE))) USEMODULE += ztimer_msec diff --git a/cpu/esp32/esp-idf-api/gpio.c b/cpu/esp32/esp-idf-api/gpio.c new file mode 100644 index 0000000000..1f99013eac --- /dev/null +++ b/cpu/esp32/esp-idf-api/gpio.c @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2022 Gunar Schorcht + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup cpu_esp32_esp_idf_api + * @{ + * + * @file + * @brief Interface for the ESP-IDF GPIO HAL API + * + * @author Gunar Schorcht + * @} + */ + +#include + +#include "driver/gpio.h" +#include "driver/rtc_io.h" +#include "hal/gpio_hal.h" +#include "esp_sleep.h" + +#include "esp_idf_api/gpio.h" + +esp_err_t esp_idf_gpio_config(const gpio_config_t *cfg) +{ + return gpio_config(cfg); +} + +esp_err_t esp_idf_gpio_intr_enable(gpio_num_t gpio_num) +{ + return gpio_intr_enable(gpio_num); +} + +esp_err_t esp_idf_gpio_intr_disable(gpio_num_t gpio_num) +{ + return gpio_intr_disable(gpio_num); +} + +esp_err_t esp_idf_gpio_set_intr_type(gpio_num_t gpio_num, + gpio_int_type_t intr_type) +{ + return gpio_set_intr_type(gpio_num, intr_type); +} + +esp_err_t esp_idf_gpio_install_isr_service(int intr_alloc_flags) + +{ + return gpio_install_isr_service(intr_alloc_flags); +} + +esp_err_t esp_idf_gpio_isr_handler_add(gpio_num_t gpio_num, + gpio_isr_t isr_handler, void *args) + +{ + return gpio_isr_handler_add(gpio_num, isr_handler, args); +} + +esp_err_t esp_idf_gpio_wakeup_enable(gpio_num_t gpio_num, + gpio_int_type_t intr_type) + +{ + return gpio_wakeup_enable(gpio_num, intr_type); +} + +#ifdef ESP_PM_GPIO_HOLD +esp_err_t esp_idf_gpio_deep_sleep_hold(void) +{ +#if SOC_RTCIO_HOLD_SUPPORTED + extern esp_err_t rtc_gpio_force_hold_en_all(void); + return rtc_gpio_force_hold_en_all(); +#elif SOC_GPIO_SUPPORT_FORCE_HOLD + gpio_deep_sleep_hold_en(); + return ESP_OK; +#else + _Static_assert(0, "ESP32x SoC does not support hold feature in deep sleep"); + return ESP_FAIL; +#endif +#if CPU_FAM_ESP32 + /* isolating GPIO12 from external circuits is especially recommended for + * ESP32-WROVER that have an external pullup on GPIO12 */ + rtc_gpio_isolate(GPIO_NUM_12); +#endif +} +#endif /* ESP_PM_GPIO_HOLD */ + +#if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED +esp_err_t esp_idf_rtc_gpio_deinit(gpio_num_t gpio_num) + +{ + if (!rtc_gpio_is_valid_gpio(gpio_num)) { + return ESP_ERR_INVALID_ARG; + } + return rtc_gpio_deinit(gpio_num); +} + +esp_err_t esp_idf_rtc_gpio_pullup_en(gpio_num_t gpio_num) +{ + if (!rtc_gpio_is_valid_gpio(gpio_num)) { + return ESP_ERR_INVALID_ARG; + } + return rtc_gpio_pullup_en(gpio_num); +} + +esp_err_t esp_idf_rtc_gpio_pullup_dis(gpio_num_t gpio_num) +{ + if (!rtc_gpio_is_valid_gpio(gpio_num)) { + return ESP_ERR_INVALID_ARG; + } + return rtc_gpio_pullup_dis(gpio_num); +} + +esp_err_t esp_idf_rtc_gpio_pulldown_en(gpio_num_t gpio_num) +{ + if (!rtc_gpio_is_valid_gpio(gpio_num)) { + return ESP_ERR_INVALID_ARG; + } + return rtc_gpio_pulldown_en(gpio_num); +} + +esp_err_t esp_idf_rtc_gpio_pulldown_dis(gpio_num_t gpio_num) +{ + if (!rtc_gpio_is_valid_gpio(gpio_num)) { + return ESP_ERR_INVALID_ARG; + } + return rtc_gpio_pulldown_dis(gpio_num); +} + +#endif diff --git a/cpu/esp32/esp-idf/gpio/Kconfig b/cpu/esp32/esp-idf/gpio/Kconfig index 89cbea1320..0fe2ba2739 100644 --- a/cpu/esp32/esp-idf/gpio/Kconfig +++ b/cpu/esp32/esp-idf/gpio/Kconfig @@ -9,5 +9,8 @@ config MODULE_ESP_IDF_GPIO bool depends on TEST_KCONFIG depends on MODULE_ESP_IDF + + default y if MODULE_PERIPH_GPIO + help ESP-IDF code for peripheral GPIO. diff --git a/cpu/esp32/esp-idf/gpio/Makefile b/cpu/esp32/esp-idf/gpio/Makefile index d0b5d0a233..d6612517a3 100644 --- a/cpu/esp32/esp-idf/gpio/Makefile +++ b/cpu/esp32/esp-idf/gpio/Makefile @@ -3,6 +3,9 @@ MODULE = esp_idf_gpio # source files to be compiled for this module ESP32_SDK_SRC = \ components/driver/gpio.c \ + components/driver/rtc_io.c \ + components/driver/rtc_module.c \ + components/hal/gpio_hal.c \ components/soc/$(CPU)/gpio_periph.c \ # diff --git a/cpu/esp32/include/esp_idf_api/gpio.h b/cpu/esp32/include/esp_idf_api/gpio.h new file mode 100644 index 0000000000..d5b3492044 --- /dev/null +++ b/cpu/esp32/include/esp_idf_api/gpio.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2022 Gunar Schorcht + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup cpu_esp32_esp_idf_api + * @{ + * + * @file + * @brief Interface for the ESP-IDF GPIO API + * + * @author Gunar Schorcht + * @} + */ + +#ifndef ESP_IDF_API_GPIO_H +#define ESP_IDF_API_GPIO_H + +#include "esp_err.h" + +#ifndef DOXYGEN /* Hide implementation details from doxygen */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @name ESP-IDF interface wrapper functions + * @{ + */ +esp_err_t esp_idf_gpio_config(const gpio_config_t *cfg); + +esp_err_t esp_idf_gpio_intr_enable(gpio_num_t gpio_num); +esp_err_t esp_idf_gpio_intr_disable(gpio_num_t gpio_num); +esp_err_t esp_idf_gpio_set_intr_type(gpio_num_t gpio_num, + gpio_int_type_t intr_type); +esp_err_t esp_idf_gpio_install_isr_service(int intr_alloc_flags); +esp_err_t esp_idf_gpio_isr_handler_add(gpio_num_t gpio_num, + gpio_isr_t isr_handler, void *args); + +esp_err_t esp_idf_gpio_wakeup_enable(gpio_num_t gpio_num, + gpio_int_type_t intr_type); +esp_err_t esp_idf_gpio_deep_sleep_hold(void); + +esp_err_t esp_idf_rtc_gpio_deinit(gpio_num_t gpio_num); +esp_err_t esp_idf_rtc_gpio_pullup_en(gpio_num_t gpio_num); +esp_err_t esp_idf_rtc_gpio_pullup_dis(gpio_num_t gpio_num); +esp_err_t esp_idf_rtc_gpio_pulldown_en(gpio_num_t gpio_num); +esp_err_t esp_idf_rtc_gpio_pulldown_dis(gpio_num_t gpio_num); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* DOXYGEN */ +#endif /* ESP_IDF_API_GPIO_H */ diff --git a/cpu/esp32/include/gpio_arch.h b/cpu/esp32/include/gpio_arch.h index 7b9a984806..6c037ac2bf 100644 --- a/cpu/esp32/include/gpio_arch.h +++ b/cpu/esp32/include/gpio_arch.h @@ -23,19 +23,12 @@ #include #include "gpio_arch_common.h" +#include "periph/gpio.h" #ifdef __cplusplus extern "C" { #endif -#ifndef DOXYGEN -/** - * @brief Returns the RTCIO pin number or -1 if the pin is not an RTCIO pin - */ -int8_t gpio_is_rtcio (gpio_t pin); - -#endif /* DOXYGEN */ - /** * @brief Called before the power management enters a light or deep sleep mode * @param mode sleep mode that is entered diff --git a/cpu/esp32/include/periph_cpu.h b/cpu/esp32/include/periph_cpu.h index 84599c8e33..a1b1c6097d 100644 --- a/cpu/esp32/include/periph_cpu.h +++ b/cpu/esp32/include/periph_cpu.h @@ -101,7 +101,7 @@ typedef unsigned int gpio_t; * @brief Define CPU specific number of GPIO pins * @{ */ -#define GPIO_PIN_NUMOF (40) +#define GPIO_PIN_NUMOF (SOC_GPIO_PIN_COUNT) /** @} */ #ifndef DOXYGEN @@ -112,14 +112,13 @@ typedef unsigned int gpio_t; */ #define HAVE_GPIO_FLANK_T typedef enum { - GPIO_NONE = 0, - GPIO_RISING = 1, /**< emit interrupt on rising flank */ - GPIO_FALLING = 2, /**< emit interrupt on falling flank */ - GPIO_BOTH = 3, /**< emit interrupt on both flanks */ - GPIO_LOW = 4, /**< emit interrupt on low level */ - GPIO_HIGH = 5 /**< emit interrupt on low level */ + GPIO_NONE, + GPIO_RISING, /**< emit interrupt on rising flank */ + GPIO_FALLING, /**< emit interrupt on falling flank */ + GPIO_BOTH, /**< emit interrupt on both flanks */ + GPIO_LOW, /**< emit interrupt on low level */ + GPIO_HIGH /**< emit interrupt on low level */ } gpio_flank_t; - /** @} */ /** @@ -137,9 +136,10 @@ typedef enum { GPIO_OD_PU, /**< open-drain output with pull-up */ GPIO_IN_OUT, /**< input and output */ GPIO_IN_OD, /**< input and open-drain output */ - GPIO_IN_OD_PU /**< input and open-drain output */ + GPIO_IN_OD_PU /**< input and open-drain output with pull-up */ } gpio_mode_t; /** @} */ + #endif /* ndef DOXYGEN */ /** @} */ diff --git a/cpu/esp32/periph/Makefile b/cpu/esp32/periph/Makefile index d6a5d0455c..ad23cff825 100644 --- a/cpu/esp32/periph/Makefile +++ b/cpu/esp32/periph/Makefile @@ -1,3 +1,7 @@ MODULE = periph +ifneq (,$(filter periph_gpio,$(USEMODULE))) + SRC += gpio_arch.c +endif + include $(RIOTMAKE)/periph.mk diff --git a/cpu/esp32/periph/gpio.c b/cpu/esp32/periph/gpio.c index 3b24fe8e03..b0c5c4d3bd 100644 --- a/cpu/esp32/periph/gpio.c +++ b/cpu/esp32/periph/gpio.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 Gunar Schorcht + * Copyright (C) 2022 Gunar Schorcht * * This file is subject to the terms and conditions of the GNU Lesser * General Public License v2.1. See the file LICENSE in the top level @@ -18,231 +18,56 @@ * @} */ -#define ENABLE_DEBUG 0 -#include "debug.h" - #include #include #include "log.h" #include "periph/gpio.h" /* RIOT gpio.h */ +#include "hal/gpio_hal.h" +#include "hal/gpio_types.h" +#include "hal/rtc_io_types.h" #include "esp/common_macros.h" +#include "esp_intr_alloc.h" #include "rom/ets_sys.h" #include "soc/gpio_reg.h" #include "soc/gpio_sig_map.h" #include "soc/gpio_struct.h" #include "soc/io_mux_reg.h" #include "soc/rtc_cntl_reg.h" -#include "soc/rtc_io_reg.h" -#include "soc/rtc_io_struct.h" -#include "xtensa/xtensa_api.h" +#include "soc/rtc_io_periph.h" +#if __xtensa__ +#include "xtensa/xtensa_api.h" +#endif + +#include "esp_idf_api/gpio.h" + +#include "adc_arch.h" +#include "bitfield.h" #include "esp_common.h" #include "esp_sleep.h" -#include "adc_arch.h" -#include "adc_ctrl.h" #include "gpio_arch.h" #include "irq_arch.h" #include "syscalls.h" +#define ENABLE_DEBUG 0 +#include "debug.h" + #define ESP_PM_WUP_PINS_ANY_HIGH ESP_EXT1_WAKEUP_ANY_HIGH #define ESP_PM_WUP_PINS_ALL_LOW ESP_EXT1_WAKEUP_ALL_LOW #ifndef ESP_PM_WUP_LEVEL -#define ESP_PM_WUP_LEVEL ESP_PM_WUP_PINS_ANY_HIGH +#define ESP_PM_WUP_LEVEL ESP_PM_WUP_PINS_ANY_HIGH #endif -#define GPIO_PRO_CPU_INTR_ENA (BIT(2)) +#define GPIO_PRO_CPU_INTR_ENA (BIT(2)) -/* GPIO to IOMUX register mapping (see Technical Reference, Section 4.12 Register Summary) - https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf */ - -const uint32_t _gpio_to_iomux_reg[GPIO_PIN_NUMOF] = -{ - PERIPHS_IO_MUX_GPIO0_U, /* GPIO0 */ - PERIPHS_IO_MUX_U0TXD_U, /* GPIO1 */ - PERIPHS_IO_MUX_GPIO2_U, /* GPIO2 */ - PERIPHS_IO_MUX_U0RXD_U, /* GPIO3 */ - PERIPHS_IO_MUX_GPIO4_U, /* GPIO4 */ - PERIPHS_IO_MUX_GPIO5_U, /* GPIO5 */ - PERIPHS_IO_MUX_SD_CLK_U, /* GPIO6 used for FLASH */ - PERIPHS_IO_MUX_SD_DATA0_U, /* GPIO7 used for FLASH */ - PERIPHS_IO_MUX_SD_DATA1_U, /* GPIO8 used for FLASH */ - PERIPHS_IO_MUX_SD_DATA2_U, /* GPIO9 used for FLASH in qio or qout mode */ - PERIPHS_IO_MUX_SD_DATA3_U, /* GPIO10 used for FLASH in qio or qout mode */ - PERIPHS_IO_MUX_SD_CMD_U, /* GPIO11 used for FLASH */ - PERIPHS_IO_MUX_MTDI_U, /* GPIO12 used as JTAG for OCD */ - PERIPHS_IO_MUX_MTCK_U, /* GPIO13 used as JTAG for OCD */ - PERIPHS_IO_MUX_MTMS_U, /* GPIO14 used as JTAG for OCD */ - PERIPHS_IO_MUX_MTDO_U, /* GPIO15 used as JTAG for OCD */ - PERIPHS_IO_MUX_GPIO16_U, /* GPIO16 used as CS for PSRAM TODO */ - PERIPHS_IO_MUX_GPIO17_U, /* GPIO17 */ - PERIPHS_IO_MUX_GPIO18_U, /* GPIO18 */ - PERIPHS_IO_MUX_GPIO19_U, /* GPIO19 */ - 0, /* GPIO20 not available */ - PERIPHS_IO_MUX_GPIO21_U, /* GPIO21 */ - PERIPHS_IO_MUX_GPIO22_U, /* GPIO22 */ - PERIPHS_IO_MUX_GPIO23_U, /* GPIO23 */ - 0, /* GPIO24 not available */ - PERIPHS_IO_MUX_GPIO25_U, /* GPIO25 */ - PERIPHS_IO_MUX_GPIO26_U, /* GPIO26 */ - PERIPHS_IO_MUX_GPIO27_U, /* GPIO27 */ - 0, /* GPIO28 not available */ - 0, /* GPIO29 not available */ - 0, /* GPIO30 not available */ - 0, /* GPIO31 not available */ - PERIPHS_IO_MUX_GPIO32_U, /* GPIO32 */ - PERIPHS_IO_MUX_GPIO33_U, /* GPIO33 */ - PERIPHS_IO_MUX_GPIO34_U, /* GPIO34 */ - PERIPHS_IO_MUX_GPIO35_U, /* GPIO35 */ - PERIPHS_IO_MUX_GPIO36_U, /* GPIO36 */ - PERIPHS_IO_MUX_GPIO37_U, /* GPIO37 */ - PERIPHS_IO_MUX_GPIO38_U, /* GPIO38 */ - PERIPHS_IO_MUX_GPIO39_U, /* GPIO39 */ -}; - -/* - * Following table defines which GPIOs have to be handled using RTC_GPIO - * registers since pull-up and pull-down resistors for pads with both GPIO - * and RTC_GPIO functionality can only be controlled via RTC_GPIO registers - * https://www.espressif.com/sites/default/files/documentation/eco_and_workarounds_for_bugs_in_esp32_en.pdf - * - * The table contains the RTC_GPIO num or -1 if it is not an RTC_GPIO pin. - */ - -static const int8_t _gpio_to_rtc[GPIO_PIN_NUMOF] = { - 11, /* gpio0 */ - -1, /* gpio1 */ - 12, /* gpio2 */ - -1, /* gpio3 */ - 10, /* gpio4 */ - -1, /* gpio5 */ - -1, /* gpio6 */ - -1, /* gpio7 */ - -1, /* gpio8 */ - -1, /* gpio9 */ - -1, /* gpio10 */ - -1, /* gpio11 */ - 15, /* gpio12 */ - 14, /* gpio13 */ - 16, /* gpio14 */ - 13, /* gpio15 */ - -1, /* gpio16 */ - -1, /* gpio17 */ - -1, /* gpio18 */ - -1, /* gpio19 */ - -1, /* gpio20 */ - -1, /* gpio21 */ - -1, /* gpio22 */ - -1, /* gpio23 */ - -1, /* gpio24 */ - 6, /* gpio25 */ - 7, /* gpio26 */ - 17, /* gpio27 */ - -1, /* gpio28 */ - -1, /* gpio29 */ - -1, /* gpio30 */ - -1, /* gpio31 */ - 9, /* gpio32 */ - 8, /* gpio33 */ - 4, /* gpio34 */ - 5, /* gpio35 */ - 0, /* gpio36 */ - 1, /* gpio37 */ - 2, /* gpio38 */ - 9 /* gpio39 */ -}; - -/** - * @brief Register information type for RTCIO GPIO pins (for internal use only) - */ -struct _rtc_gpio_t { - uint8_t num; /**< RTC_GPIO pin number */ - uint32_t reg; /**< register of the RTC_GPIO pin */ - uint8_t mux; /**< mux io/rtc bit [0..31] in the register, 32 - no mux */ - uint8_t pullup; /**< pullup bit [0..31] in the register, 32 - no pullup */ - uint8_t pulldown; /**< pulldown bit [0..31] in the register, 32 - no pulldown */ - uint8_t drive; /**< drive strength start bit [0..30] in the register */ -}; - -/* Table of RTCIO GPIO pins information */ -static const struct _rtc_gpio_t _rtc_gpios[] = { - { 0, RTC_IO_SENSOR_PADS_REG, 27, 32, 32, 32 }, /* rtc0 (gpio36) SENSOR_VP/SENSE 1 */ - { 1, RTC_IO_SENSOR_PADS_REG, 26, 32, 32, 32 }, /* rtc1 (gpio37) SENSOR_CAPP/SENSE 2 */ - { 2, RTC_IO_SENSOR_PADS_REG, 25, 32, 32, 32 }, /* rtc2 (gpio38) SENSOR_CAPN/SENSE 3 */ - { 3, RTC_IO_SENSOR_PADS_REG, 24, 32, 32, 32 }, /* rtc3 (gpio39) SENSOR_VN/SENSE 4*/ - { 4, RTC_IO_ADC_PAD_REG, 29, 32, 32, 32 }, /* rtc4 (gpio34) VDET_1/ADC1 */ - { 5, RTC_IO_ADC_PAD_REG, 28, 32, 32, 32 }, /* rtc5 (gpio35) VDET_2/ADC2 */ - { 6, RTC_IO_PAD_DAC1_REG, 17, 27, 28, 30 }, /* rtc6 (gpio25) DAC1 */ - { 7, RTC_IO_PAD_DAC2_REG, 17, 27, 28, 30 }, /* rtc7 (gpio26) DAC1 */ - { 8, RTC_IO_XTAL_32K_PAD_REG, 18, 27, 28, 30 }, /* rtc8 (gpio33) XTAL_32K_N */ - { 9, RTC_IO_XTAL_32K_PAD_REG, 17, 22, 23, 25 }, /* rtc9 (gpio32) XTAL_32K_P */ - { 10, RTC_IO_TOUCH_PAD0_REG, 19, 27, 28, 29 }, /* rtc10 (gpio4) TOUCH0 */ - { 11, RTC_IO_TOUCH_PAD1_REG, 19, 27, 28, 29 }, /* rtc11 (gpio0) TOUCH1 */ - { 12, RTC_IO_TOUCH_PAD2_REG, 19, 27, 28, 29 }, /* rtc12 (gpio2) TOUCH2 */ - { 13, RTC_IO_TOUCH_PAD3_REG, 19, 27, 28, 29 }, /* rtc13 (gpio15) TOUCH3 */ - { 14, RTC_IO_TOUCH_PAD4_REG, 19, 27, 28, 29 }, /* rtc14 (gpio13) TOUCH4 */ - { 15, RTC_IO_TOUCH_PAD5_REG, 19, 27, 28, 29 }, /* rtc15 (gpio12) TOUCH5 */ - { 16, RTC_IO_TOUCH_PAD6_REG, 19, 27, 28, 29 }, /* rtc16 (gpio14) TOUCH6 */ - { 17, RTC_IO_TOUCH_PAD7_REG, 19, 27, 28, 29 } /* rtc17 (gpio27) TOUCH7 */ -}; - -/* Table of the usage type of each GPIO pin */ -gpio_pin_usage_t _gpio_pin_usage [GPIO_PIN_NUMOF] = { - _GPIO, /* gpio0 */ - _UART, /* gpio1 configured as direct I/O UART0 RxD */ - _GPIO, /* gpio2 */ - _UART, /* gpio3 configured as direct I/O UART0 TxD */ - _GPIO, /* gpio4 */ - _GPIO, /* gpio5 configurable as direct I/O VSPI CS0 */ - _SPIF, /* gpio6 not configurable, used as SPI SCK */ - _SPIF, /* gpio7 not configurable, used as SPI MISO */ - _SPIF, /* gpio8 not configurable, used as SPI MOSI */ - #if defined(FLASH_MODE_QIO) || defined(FLASH_MODE_QOUT) - /* in qio and qout mode these pins are used for quad SPI */ - _SPIF, /* gpio9 not configurable, used as SPI HD */ - _SPIF, /* gpio10 not configurable, used as SPI WP */ - #else - /* otherwise these pins can be used as GPIO */ - _GPIO, /* gpio9 */ - _GPIO, /* gpio10 */ - #endif - _SPIF, /* gpio11 not configurable, used as SPI CS0 */ - _GPIO, /* gpio12 configurable as direct I/O HSPI MISO */ - _GPIO, /* gpio13 configurable as direct I/O HSPI MOSI */ - _GPIO, /* gpio14 configurable as direct I/O HSPI SCK */ - _GPIO, /* gpio15 configurable as direct I/O HSPI CS0 */ - _GPIO, /* gpio16 */ - _GPIO, /* gpio17 */ - _GPIO, /* gpio18 configurable as direct I/O VSPI SCK */ - _GPIO, /* gpio19 configurable as direct I/O VSPI MISO */ - _NOT_EXIST, /* gpio20 */ - _GPIO, /* gpio21 */ - _GPIO, /* gpio22 */ - _GPIO, /* gpio23 configurable as direct I/O VSPI MOSI */ - _NOT_EXIST, /* gpio24 */ - _GPIO, /* gpio25 */ - _GPIO, /* gpio26 */ - _GPIO, /* gpio27 */ - _NOT_EXIST, /* gpio28 */ - _NOT_EXIST, /* gpio29 */ - _NOT_EXIST, /* gpio30 */ - _NOT_EXIST, /* gpio31 */ -#if MODULE_ESP_RTC_TIMER_32K - _NOT_EXIST, /* gpio32 used for external 32K crystal */ - _NOT_EXIST, /* gpio33 used for external 32K crystal */ -#else - _GPIO, /* gpio32 */ - _GPIO, /* gpio33 */ +/* architecture specific tables */ +extern gpio_pin_usage_t _gpio_pin_usage [GPIO_PIN_NUMOF]; +#if !IS_USED(MODULE_ESP_IDF_GPIO_HAL) +extern const uint32_t _gpio_to_iomux_reg[GPIO_PIN_NUMOF]; #endif - _GPIO, /* gpio34 */ - _GPIO, /* gpio35 */ - _GPIO, /* gpio36 */ - _GPIO, /* gpio37 */ - _GPIO, /* gpio38 */ - _GPIO /* gpio39 */ -}; /* String representation of usage types */ const char* _gpio_pin_usage_str[] = @@ -250,21 +75,28 @@ const char* _gpio_pin_usage_str[] = "GPIO", "ADC", "CAN", "DAC", "EMAC", "I2C", "PWM", "SPI", "SPI Flash", "UART", "N/A" }; -#define FUN_GPIO 2 /* the function number for all GPIOs */ +#ifdef ESP_PM_WUP_PINS +/* for saving the pullup/pulldown settings of wakeup pins in deep sleep mode */ +static bool _gpio_pin_pu[GPIO_PIN_NUMOF] = { }; +static bool _gpio_pin_pd[GPIO_PIN_NUMOF] = { }; +#endif -#define GPIO_PIN_SET(b) if (b < 32) GPIO.out_w1ts = BIT(b); else GPIO.out1_w1ts.val = BIT(b-32) -#define GPIO_PIN_CLR(b) if (b < 32) GPIO.out_w1tc = BIT(b); else GPIO.out1_w1tc.val = BIT(b-32) -#define GPIO_PIN_GET(b) (b < 32) ? (GPIO.out >> b) & 1 : (GPIO.out1.val >> (b-32)) & 1 +#if defined(MCU_ESP32) -#define GPIO_REG_BIT_GET(l,h,b) ((b < 32) ? GPIO.l & BIT(b) : GPIO.h.val & BIT(b-32)) -#define GPIO_REG_BIT_SET(l,h,b) if (b < 32) GPIO.l |= BIT(b); else GPIO.h.val |= BIT(b-32) -#define GPIO_REG_BIT_CLR(l,h,b) if (b < 32) GPIO.l &= ~BIT(b); else GPIO.h.val &= ~BIT(b-32) -#define GPIO_REG_BIT_XOR(l,h,b) if (b < 32) GPIO.l ^= BIT(b); else GPIO.h.val ^= BIT(b-32) -#define REG_SET_CLR_BIT(c,r,f) if (c) REG_SET_BIT(r,f); else REG_CLR_BIT(r,f) +#define GPIO_IN_GET(b) (b < 32) ? GPIO.in & BIT(b) : GPIO.in1.val & BIT(b-32) +#define GPIO_OUT_SET(b) if (b < 32) GPIO.out_w1ts = BIT(b); else GPIO.out1_w1ts.val = BIT(b-32) +#define GPIO_OUT_CLR(b) if (b < 32) GPIO.out_w1tc = BIT(b); else GPIO.out1_w1tc.val = BIT(b-32) +#define GPIO_OUT_XOR(b) if (b < 32) GPIO.out ^= BIT(b); else GPIO.out1.val ^= BIT(b-32) +#define GPIO_OUT_GET(b) (b < 32) ? (GPIO.out >> b) & 1 : (GPIO.out1.val >> (b-32)) & 1 -int gpio_init(gpio_t pin, gpio_mode_t mode) +#else +#error "Platform implementation is missing" +#endif + +#ifndef NDEBUG +int _gpio_init_mode_check(gpio_t pin, gpio_mode_t mode) { - CHECK_PARAM_RET(pin < GPIO_PIN_NUMOF, -1); + assert(pin < GPIO_PIN_NUMOF); /* check if the pin can be used as GPIO or if it is used for something else */ if (_gpio_pin_usage[pin] != _GPIO) { @@ -272,251 +104,273 @@ int gpio_init(gpio_t pin, gpio_mode_t mode) _gpio_pin_usage_str[_gpio_pin_usage[pin]]); return -1; } + return 0; +} +#endif - /* check additional limitations for GPIOs 34 ... 39 */ - if (pin > GPIO33) { - switch (mode) { - case GPIO_OUT: - case GPIO_OD: - case GPIO_OD_PU: - case GPIO_IN_OUT: - case GPIO_IN_OD: - case GPIO_IN_OD_PU: - /* GPIOs 34 ... 39 cannot be used as output */ - LOG_TAG_ERROR("gpio", - "GPIO%d can only be used as input\n", pin); - return -1; +int gpio_init(gpio_t pin, gpio_mode_t mode) +{ + DEBUG("%s: gpio=%d mode=%d\n", __func__, pin, mode); + assert(_gpio_init_mode_check(pin, mode) == 0); + assert(pin < GPIO_PIN_NUMOF); - case GPIO_IN_PD: - case GPIO_IN_PU: - /* GPIOs 34 ... 39 have no software controllable pullups/pulldowns */ - LOG_TAG_ERROR("gpio", - "GPIO%d has no pullups/pulldowns\n", pin); - return -1; - default: break; - } - } + gpio_config_t cfg = { }; - const struct _rtc_gpio_t* rtc = (_gpio_to_rtc[pin] != -1) ? - &_rtc_gpios[_gpio_to_rtc[pin]] : NULL; +#if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED + /* if we come from deep sleep, the GPIO is configured as RTC IO */ + esp_idf_rtc_gpio_deinit(pin); +#endif - /* if pin is a RTC_GPIO, reset RTC function to route RTC pin to GPIO pin */ - if (rtc) { - REG_CLR_BIT(rtc->reg, BIT(rtc->mux)); - } + cfg.pin_bit_mask = (1ULL << pin); switch (mode) { - - case GPIO_IN: - case GPIO_IN_PD: - case GPIO_IN_PU: - /* according to Technical Reference it is not necessary - to configure the GPIO matrix to read GPIOs from - GPIO_IN_REG/GPIO_IN1_REG */ - #if 0 - /* configure the GPIO matrix for the inputs */ - GPIO.func_in_sel_cfg[signal].sig_in_sel = 0; /* route through GPIO matrix */ - GPIO.func_in_sel_cfg[signal].sig_in_inv = 0; /* do not invert input */ - GPIO.func_in_sel_cfg[signal].func_sel = pin; /* connect signal to GPIOx */ - #endif - - /* disable the output for input-only signals */ - GPIO.func_out_sel_cfg[pin].oen_sel = 1; - GPIO_REG_BIT_SET(enable_w1tc, enable1_w1tc, pin); - - /* set the FUN_IE bit for input */ - REG_SET_BIT(_gpio_to_iomux_reg[pin], FUN_IE); - - /* FUN_GPIO / FUN_WPU / FUN_WPD are set later */ - break; - - case GPIO_OUT: - case GPIO_OD: - case GPIO_OD_PU: - /* configure GPIO signal in the GPIO matrix */ - GPIO.func_out_sel_cfg[pin].func_sel = SIG_GPIO_OUT_IDX; - - /* enable the output */ - GPIO.func_out_sel_cfg[pin].oen_sel = 1; - GPIO_REG_BIT_SET(enable_w1ts, enable1_w1ts, pin); - - /* set pad driver to one for open drain outputs */ - GPIO.pin[pin].pad_driver = (mode == GPIO_OD || mode == GPIO_OD_PU) ? 1 : 0; - - /* set pad driver also for RTC pin if it is a RTC_GPIO */ - if (rtc) { - RTCIO.pin[rtc->num].pad_driver = GPIO.pin[pin].pad_driver; - } - - /* clear the FUN_IE bit */ - REG_CLR_BIT(_gpio_to_iomux_reg[pin], FUN_IE); - - /* FUN_GPIO / FUN_WPU / FUN_WPD are set later */ - break; - - case GPIO_IN_OUT: - case GPIO_IN_OD: - case GPIO_IN_OD_PU: - /* configure GPIO signal in the GPIO matrix */ - GPIO.func_out_sel_cfg[pin].func_sel = SIG_GPIO_OUT_IDX; - - /* enable the output */ - GPIO.func_out_sel_cfg[pin].oen_sel = 1; - GPIO_REG_BIT_SET(enable_w1ts, enable1_w1ts, pin); - - /* set pad driver to one for open drain outputs */ - GPIO.pin[pin].pad_driver = (mode == GPIO_IN_OD || mode == GPIO_IN_OD_PU) ? 1 : 0; - - /* set pad driver also for RTC pin if it is a RTC_GPIO */ - if (rtc) { - RTCIO.pin[rtc->num].pad_driver = GPIO.pin[pin].pad_driver; - } - - /* enable the input */ - REG_SET_BIT(_gpio_to_iomux_reg[pin], FUN_IE); - - /* FUN_GPIO / FUN_WPU / FUN_WPD are set later */ - break; - } - /* select GPIO as IO_MUX function (FUN_GPIO) */ - REG_SET_FIELD(_gpio_to_iomux_reg[pin], MCU_SEL, FUN_GPIO); - - /* enable/disable the pull-up resistor (FUN_WPU) */ - REG_SET_CLR_BIT(mode == GPIO_IN_PU || mode == GPIO_OD_PU || mode == GPIO_IN_OD_PU, - _gpio_to_iomux_reg[pin], FUN_PU); - - /* enable/disable the pull-down resistor (FUN_WPD) */ - REG_SET_CLR_BIT(mode == GPIO_IN_PD, _gpio_to_iomux_reg[pin], FUN_PD); - - /* handle pull-up/pull-down resistors for RTC_GPIOs */ - if (rtc) { - /* enable/disable the pull-up resistor (FUN_WPU) */ - REG_SET_CLR_BIT(mode == GPIO_IN_PU || mode == GPIO_OD_PU || mode == GPIO_IN_OD_PU, - rtc->reg, BIT(rtc->pullup)); - /* enable/disable the pull-down resistor (FUN_WPD) */ - REG_SET_CLR_BIT(mode == GPIO_IN_PD, rtc->reg, BIT(rtc->pulldown)); + case GPIO_IN: + case GPIO_IN_PD: + case GPIO_IN_PU: + cfg.mode = GPIO_MODE_DEF_INPUT; + break; + case GPIO_IN_OD: + case GPIO_IN_OD_PU: + cfg.mode = (GPIO_MODE_DEF_INPUT) | (GPIO_MODE_DEF_OUTPUT) | (GPIO_MODE_DEF_OD); + break; + case GPIO_IN_OUT: + cfg.mode = (GPIO_MODE_DEF_INPUT) | (GPIO_MODE_DEF_OUTPUT); + break; + case GPIO_OUT: + cfg.mode = GPIO_MODE_DEF_OUTPUT; + break; + case GPIO_OD: + case GPIO_OD_PU: + cfg.mode = (GPIO_MODE_DEF_OUTPUT) | (GPIO_MODE_DEF_OD); + break; } - return 0; + /* digital GPIO configuration */ + cfg.pull_up_en = ((mode == GPIO_IN_PU) || + (mode == GPIO_OD_PU) || + (mode == GPIO_IN_OD_PU)) ? GPIO_PULLUP_ENABLE + : GPIO_PULLUP_DISABLE; + cfg.pull_down_en = (mode == GPIO_IN_PD) ? GPIO_PULLUP_ENABLE + : GPIO_PULLUP_DISABLE; + cfg.intr_type = GPIO_INTR_DISABLE; + +#ifdef ESP_PM_WUP_PINS +/* for saving the pullup/pulldown settings of wakeup pins in deep sleep mode */ + _gpio_pin_pu[pin] = cfg.pull_up_en; + _gpio_pin_pd[pin] = cfg.pull_down_en; +#endif + + return (esp_idf_gpio_config(&cfg) == ESP_OK) ? 0 : -1; } #if MODULE_PERIPH_GPIO_IRQ -static gpio_isr_ctx_t gpio_isr_ctx_table [GPIO_PIN_NUMOF] = { }; -static bool gpio_int_enabled_table [GPIO_PIN_NUMOF] = { }; +/* interrupt enabled state is required for sleep modes */ +static bool gpio_int_enabled_table[GPIO_PIN_NUMOF] = { }; -void IRAM gpio_int_handler (void* arg) -{ - irq_isr_enter(); - (void)arg; - - for (unsigned i = 0; i < GPIO_PIN_NUMOF; i++) { - if (GPIO_REG_BIT_GET(status, status1, i)) { - GPIO_REG_BIT_SET(status_w1tc, status1_w1tc, i); - if (gpio_int_enabled_table[i] && GPIO.pin[i].int_type) { - gpio_isr_ctx_table[i].cb (gpio_isr_ctx_table[i].arg); - } - } - } - irq_isr_exit(); -} +static bool _isr_installed = false; int gpio_init_int(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank, gpio_cb_t cb, void *arg) { - if (gpio_init(pin, mode)) { + DEBUG("%s: gpio=%d mode=%d flank=%d\n", __func__, pin, mode, flank); + assert(_gpio_init_mode_check(pin, mode) == 0); + + if (gpio_init(pin, mode) != 0) { return -1; } - gpio_isr_ctx_table[pin].cb = cb; - gpio_isr_ctx_table[pin].arg = arg; + gpio_int_type_t type = GPIO_INTR_DISABLE; - GPIO.pin[pin].int_type = flank; - if (flank != GPIO_NONE) { - gpio_int_enabled_table [pin] = (gpio_isr_ctx_table[pin].cb != NULL); - GPIO.pin[pin].int_ena = GPIO_PRO_CPU_INTR_ENA; - GPIO.pin[pin].int_type = flank; - GPIO.pin[pin].wakeup_enable = 1; - - intr_matrix_set(PRO_CPU_NUM, ETS_GPIO_INTR_SOURCE, CPU_INUM_GPIO); - xt_set_interrupt_handler(CPU_INUM_GPIO, gpio_int_handler, NULL); - xt_ints_on(BIT(CPU_INUM_GPIO)); + switch (flank) { + case GPIO_NONE: + type = GPIO_INTR_DISABLE; + break; + case GPIO_RISING: + type = GPIO_INTR_POSEDGE; + break; + case GPIO_FALLING: + type = GPIO_INTR_NEGEDGE; + break; + case GPIO_BOTH: + type = GPIO_INTR_ANYEDGE; + break; + case GPIO_LOW: + type = GPIO_INTR_LOW_LEVEL; + break; + case GPIO_HIGH: + type = GPIO_INTR_HIGH_LEVEL; + break; } - return 0; + if (esp_idf_gpio_set_intr_type(pin, type) != ESP_OK) { + return -1; + } + + if (!_isr_installed && + esp_idf_gpio_install_isr_service(ESP_INTR_FLAG_LEVEL1) != ESP_OK) { + return -1; + } + _isr_installed = true; + + if (esp_idf_gpio_isr_handler_add(pin, cb, arg) != ESP_OK) { + return -1; + } + + gpio_irq_enable(pin); + + return (gpio_int_enabled_table[pin]) ? 0 : -1; } -void gpio_irq_enable (gpio_t pin) +void gpio_irq_enable(gpio_t pin) { - CHECK_PARAM(pin < GPIO_PIN_NUMOF); + DEBUG("%s: gpio=%d\n", __func__, pin); + assert(pin < GPIO_PIN_NUMOF); - gpio_int_enabled_table [pin] = true; + if (esp_idf_gpio_intr_enable(pin) == ESP_OK) { + gpio_int_enabled_table[pin] = true; + } } -void gpio_irq_disable (gpio_t pin) +void gpio_irq_disable(gpio_t pin) { - CHECK_PARAM(pin < GPIO_PIN_NUMOF); + DEBUG("%s: gpio=%d\n", __func__, pin); + assert(pin < GPIO_PIN_NUMOF); - gpio_int_enabled_table [pin] = false; + if (esp_idf_gpio_intr_disable(pin) == ESP_OK) { + gpio_int_enabled_table[pin] = false; + } } #endif /* MODULE_PERIPH_GPIO_IRQ */ -int gpio_read (gpio_t pin) +#if IS_USED(MODULE_ESP_IDF_GPIO_HAL) + +static gpio_hal_context_t _gpio_hal_ctx = { + .dev = GPIO_HAL_GET_HW(GPIO_PORT_0) +}; + +/* + * Since `gpio_hal_get_level` returns the current pin level and not the value + * last written to the output, we have to handle the state of each pin in a + * separate static variable. + */ +static BITFIELD(_output, GPIO_PIN_NUMOF); + +int gpio_read(gpio_t pin) { - CHECK_PARAM_RET(pin < GPIO_PIN_NUMOF, -1); + assert(pin < GPIO_PIN_NUMOF); + + /* if the pin is not an input, it alsways returns 0 */ + /* TODO: not really clear whether it should return the last written value + * in this case. */ + int value = gpio_hal_get_level(&_gpio_hal_ctx, pin); + + DEBUG("%s gpio=%u val=%d\n", __func__, pin, value); + return value; +} + +void gpio_write(gpio_t pin, int value) +{ + DEBUG("%s gpio=%u val=%d\n", __func__, pin, value); + assert(pin < GPIO_PIN_NUMOF); + + if (value) { + bf_set(_output, pin); + } + else { + bf_unset(_output, pin); + } + gpio_hal_set_level(&_gpio_hal_ctx, pin, value); +} + +void gpio_set(gpio_t pin) +{ + DEBUG("%s gpio=%u\n", __func__, pin); + assert(pin < GPIO_PIN_NUMOF); + + bf_set(_output, pin); + gpio_hal_set_level(&_gpio_hal_ctx, pin, 1); +} + +void gpio_clear(gpio_t pin) +{ + DEBUG("%s gpio=%u\n", __func__, pin); + assert(pin < GPIO_PIN_NUMOF); + + bf_unset(_output, pin); + gpio_hal_set_level(&_gpio_hal_ctx, pin, 0); +} + +void gpio_toggle(gpio_t pin) +{ + DEBUG("%s gpio=%u\n", __func__, pin); + assert(pin < GPIO_PIN_NUMOF); + + bf_toggle(_output, pin); + gpio_hal_set_level(&_gpio_hal_ctx, pin, bf_isset(_output, pin) ? 1 : 0); +} + +#else /* IS_USED(MODULE_ESP_IDF_GPIO_HAL) */ + +int gpio_read(gpio_t pin) +{ + assert(pin < GPIO_PIN_NUMOF); + int value; if (REG_GET_BIT(_gpio_to_iomux_reg[pin], FUN_IE)) { /* in case the pin is any kind of input, read from input register */ - value = GPIO_REG_BIT_GET(in, in1, pin) ? 1 : 0; + value = (GPIO_IN_GET(pin)) ? 1 : 0; } else { /* otherwise read the last value written to the output register */ - value = GPIO_PIN_GET(pin); + value = GPIO_OUT_GET(pin); } DEBUG("%s gpio=%u val=%d\n", __func__, pin, value); return value; } -void gpio_write (gpio_t pin, int value) +void gpio_write(gpio_t pin, int value) { DEBUG("%s gpio=%u val=%d\n", __func__, pin, value); - CHECK_PARAM(pin < GPIO_PIN_NUMOF); + assert(pin < GPIO_PIN_NUMOF); if (value) { - GPIO_PIN_SET(pin); + GPIO_OUT_SET(pin); } else { - GPIO_PIN_CLR(pin); + GPIO_OUT_CLR(pin); } } -void gpio_set (gpio_t pin) +void gpio_set(gpio_t pin) { DEBUG("%s gpio=%u\n", __func__, pin); - CHECK_PARAM(pin < GPIO_PIN_NUMOF); - GPIO_PIN_SET(pin); + assert(pin < GPIO_PIN_NUMOF); + GPIO_OUT_SET(pin); } -void gpio_clear (gpio_t pin) +void gpio_clear(gpio_t pin) { DEBUG("%s gpio=%u\n", __func__, pin); - CHECK_PARAM(pin < GPIO_PIN_NUMOF); - GPIO_PIN_CLR(pin); + assert(pin < GPIO_PIN_NUMOF); + GPIO_OUT_CLR(pin); } -void gpio_toggle (gpio_t pin) +void gpio_toggle(gpio_t pin) { DEBUG("%s gpio=%u\n", __func__, pin); - CHECK_PARAM(pin < GPIO_PIN_NUMOF); - GPIO_REG_BIT_XOR(out, out1, pin); + assert(pin < GPIO_PIN_NUMOF); + GPIO_OUT_XOR(pin); } +#endif /* IS_USED(MODULE_ESP_IDF_GPIO_HAL) */ + int gpio_set_pin_usage(gpio_t pin, gpio_pin_usage_t usage) { - CHECK_PARAM_RET(pin < GPIO_PIN_NUMOF, -1); - _gpio_pin_usage [pin] = usage; + assert(pin < GPIO_PIN_NUMOF); + _gpio_pin_usage[pin] = usage; return 0; } @@ -530,34 +384,22 @@ const char* gpio_get_pin_usage_str(gpio_t pin) return _gpio_pin_usage_str[_gpio_pin_usage[((pin < GPIO_PIN_NUMOF) ? pin : _NOT_EXIST)]]; } -int8_t gpio_is_rtcio (gpio_t pin) -{ - return _gpio_to_rtc[pin]; -} - #if MODULE_PERIPH_GPIO_IRQ static uint32_t gpio_int_saved_type[GPIO_PIN_NUMOF]; #endif void gpio_pm_sleep_enter(unsigned mode) { - /* - * Activate the power domain for RTC peripherals either when - * ESP_PM_GPIO_HOLD is defined or when light sleep mode is activated. - * As long as the RTC peripherals are active, the pad state of RTC GPIOs - * is held in deep sleep and the pad state of all GPIOs is held in light - * sleep. - */ + if (mode == ESP_PM_DEEP_SLEEP) { #ifdef ESP_PM_GPIO_HOLD - SET_PERI_REG_BITS(RTC_CNTL_HOLD_FORCE_REG, 0x3FFFF, 0x3FFFF, 0); - esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON); -#else - if (mode == ESP_PM_LIGHT_SLEEP) { + /* + * Activate the power domain for RTC peripherals when + * ESP_PM_GPIO_HOLD is defined for deep sleep mode. + */ + esp_idf_gpio_deep_sleep_hold(); esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON); - } #endif - if (mode == ESP_PM_DEEP_SLEEP) { #ifdef ESP_PM_WUP_PINS static const gpio_t wup_pins[] = { ESP_PM_WUP_PINS }; /* @@ -567,26 +409,51 @@ void gpio_pm_sleep_enter(unsigned mode) uint64_t wup_pin_mask = 0; for (unsigned i = 0; i < ARRAY_SIZE(wup_pins); i++) { wup_pin_mask |= 1ULL << wup_pins[i]; + +#if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED + /* If internal pullups/pulldowns are used, they have to be + activated also in deep sleep mode in RTC power domain */ + bool pu_pd_used = false; + + assert(rtc_io_num_map[wup_pins[i]] >= 0); + if (_gpio_pin_pu[wup_pins[i]]) { + pu_pd_used = true; + esp_idf_rtc_gpio_pullup_en(wup_pins[i]); + } + else { + esp_idf_rtc_gpio_pullup_dis(wup_pins[i]); + } + if (_gpio_pin_pd[wup_pins[i]]) { + pu_pd_used = true; + esp_idf_rtc_gpio_pulldown_en(wup_pins[i]); + } + else { + esp_idf_rtc_gpio_pulldown_dis(wup_pins[i]); + } + if (pu_pd_used) { + /* If internal pullups/pulldowns are used, the RTC power domain + * must remain active in deep sleep mode */ + esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON); + } +#endif /* SOC_RTCIO_INPUT_OUTPUT_SUPPORTED */ } esp_sleep_enable_ext1_wakeup(wup_pin_mask, ESP_PM_WUP_LEVEL); #endif /* ESP_PM_WUP_PINS */ } else { #if MODULE_PERIPH_GPIO_IRQ - esp_sleep_enable_gpio_wakeup(); for (unsigned i = 0; i < GPIO_PIN_NUMOF; i++) { - const struct _rtc_gpio_t* rtc = - (_gpio_to_rtc[i] != -1) ? &_rtc_gpios[_gpio_to_rtc[i]] : NULL; - if (gpio_int_enabled_table[i] && GPIO.pin[i].int_type) { gpio_int_saved_type[i] = GPIO.pin[i].int_type; - switch (GPIO.pin[i].int_type) { + switch (gpio_int_saved_type[i]) { + case GPIO_LOW: case GPIO_FALLING: - GPIO.pin[i].int_type = GPIO_LOW; + esp_idf_gpio_wakeup_enable(i, GPIO_INTR_LOW_LEVEL); DEBUG("%s gpio=%u GPIO_LOW\n", __func__, i); break; + case GPIO_HIGH: case GPIO_RISING: - GPIO.pin[i].int_type = GPIO_HIGH; + esp_idf_gpio_wakeup_enable(i, GPIO_INTR_HIGH_LEVEL); DEBUG("%s gpio=%u GPIO_HIGH\n", __func__, i); break; case GPIO_BOTH: @@ -596,12 +463,9 @@ void gpio_pm_sleep_enter(unsigned mode) default: break; } - if (rtc) { - RTCIO.pin[rtc->num].wakeup_enable = 1; - RTCIO.pin[rtc->num].int_type = GPIO.pin[i].int_type; - } } } + esp_sleep_enable_gpio_wakeup(); #endif } } diff --git a/cpu/esp32/periph/gpio_arch.c b/cpu/esp32/periph/gpio_arch.c new file mode 100644 index 0000000000..034af61645 --- /dev/null +++ b/cpu/esp32/periph/gpio_arch.c @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2022 Gunar Schorcht + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup cpu_esp32 + * @ingroup drivers_periph_gpio + * @{ + * + * @file + * @brief Architecture-specific GPIO definitions for ESP32 variant (family) + * + * @author Gunar Schorcht + * @} + */ + +#include "gpio_arch.h" +#include "soc/io_mux_reg.h" + +#if !IS_USED(MODULE_ESP_IDF_GPIO_HAL) + +/* GPIO to IOMUX register mapping (see Technical Reference, Section 4.12 Register Summary) + https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf */ + +const uint32_t _gpio_to_iomux_reg[GPIO_PIN_NUMOF] = +{ + PERIPHS_IO_MUX_GPIO0_U, /* GPIO0 */ + PERIPHS_IO_MUX_U0TXD_U, /* GPIO1 */ + PERIPHS_IO_MUX_GPIO2_U, /* GPIO2 */ + PERIPHS_IO_MUX_U0RXD_U, /* GPIO3 */ + PERIPHS_IO_MUX_GPIO4_U, /* GPIO4 */ + PERIPHS_IO_MUX_GPIO5_U, /* GPIO5 */ + PERIPHS_IO_MUX_SD_CLK_U, /* GPIO6 is used for Flash */ + PERIPHS_IO_MUX_SD_DATA0_U, /* GPIO7 is used for Flash */ + PERIPHS_IO_MUX_SD_DATA1_U, /* GPIO8 is used for Flash */ + PERIPHS_IO_MUX_SD_DATA2_U, /* GPIO9 is used for Flash in qio or qout mode */ + PERIPHS_IO_MUX_SD_DATA3_U, /* GPIO10 is used for Flash in qio or qout mode */ + PERIPHS_IO_MUX_SD_CMD_U, /* GPIO11 is used for Flash */ + PERIPHS_IO_MUX_MTDI_U, /* GPIO12 is used as JTAG for OCD */ + PERIPHS_IO_MUX_MTCK_U, /* GPIO13 is used as JTAG for OCD */ + PERIPHS_IO_MUX_MTMS_U, /* GPIO14 is used as JTAG for OCD */ + PERIPHS_IO_MUX_MTDO_U, /* GPIO15 is used as JTAG for OCD */ + PERIPHS_IO_MUX_GPIO16_U, /* GPIO16 is used as CS for PSRAM TODO */ + PERIPHS_IO_MUX_GPIO17_U, /* GPIO17 */ + PERIPHS_IO_MUX_GPIO18_U, /* GPIO18 */ + PERIPHS_IO_MUX_GPIO19_U, /* GPIO19 */ + 0, /* GPIO20 is not available */ + PERIPHS_IO_MUX_GPIO21_U, /* GPIO21 */ + PERIPHS_IO_MUX_GPIO22_U, /* GPIO22 */ + PERIPHS_IO_MUX_GPIO23_U, /* GPIO23 */ + 0, /* GPIO24 is not available */ + PERIPHS_IO_MUX_GPIO25_U, /* GPIO25 */ + PERIPHS_IO_MUX_GPIO26_U, /* GPIO26 */ + PERIPHS_IO_MUX_GPIO27_U, /* GPIO27 */ + 0, /* GPIO28 is not available */ + 0, /* GPIO29 is not available */ + 0, /* GPIO30 is not available */ + 0, /* GPIO31 is not available */ + PERIPHS_IO_MUX_GPIO32_U, /* GPIO32 */ + PERIPHS_IO_MUX_GPIO33_U, /* GPIO33 */ + PERIPHS_IO_MUX_GPIO34_U, /* GPIO34 */ + PERIPHS_IO_MUX_GPIO35_U, /* GPIO35 */ + PERIPHS_IO_MUX_GPIO36_U, /* GPIO36 */ + PERIPHS_IO_MUX_GPIO37_U, /* GPIO37 */ + PERIPHS_IO_MUX_GPIO38_U, /* GPIO38 */ + PERIPHS_IO_MUX_GPIO39_U, /* GPIO39 */ +}; + +#endif /* !IS_USED(MODULE_ESP_IDF_GPIO_HAL) */ + +/* Table of the usage type of each GPIO pin */ +gpio_pin_usage_t _gpio_pin_usage [GPIO_PIN_NUMOF] = { + _GPIO, /* GPIO0 */ + _UART, /* GPIO1 is used as direct I/O UART0 RxD */ + _GPIO, /* GPIO2 */ + _UART, /* GPIO3 is used as direct I/O UART0 TxD */ + _GPIO, /* GPIO4 */ + _GPIO, /* GPIO5 */ + _SPIF, /* GPIO6 is used as direct I/O SPI SCK for Flash */ + _SPIF, /* GPIO7 is used as direct I/O SPI MISO for Flash */ + _SPIF, /* GPIO8 is used as direct I/O SPI MOSI for Flash */ + #if defined(FLASH_MODE_QIO) || defined(FLASH_MODE_QOUT) + /* in qio and qout mode these pins are used in Flash */ + _SPIF, /* GPIO9 is used as direct I/O SPI HD for Flash */ + _SPIF, /* GPIO10 is used as direct I/O SPI WP for Flash */ + #else + /* otherwise these pins can be used as GPIO */ + _GPIO, /* GPIO9 */ + _GPIO, /* GPIO10 */ + #endif + _SPIF, /* GPIO11 is used as direct I/O SPI CS0 for Flash */ + _GPIO, /* GPIO12 */ + _GPIO, /* GPIO13 */ + _GPIO, /* GPIO14 */ + _GPIO, /* GPIO15 */ + _GPIO, /* GPIO16 */ + _GPIO, /* GPIO17 */ + _GPIO, /* GPIO18 */ + _GPIO, /* GPIO19 */ + _NOT_EXIST, /* GPIO20 does not exist */ + _GPIO, /* GPIO21 */ + _GPIO, /* GPIO22 */ + _GPIO, /* GPIO23 */ + _NOT_EXIST, /* GPIO24 does not exist */ + _GPIO, /* GPIO25 */ + _GPIO, /* GPIO26 */ + _GPIO, /* GPIO27 */ + _NOT_EXIST, /* GPIO28 does not exist */ + _NOT_EXIST, /* GPIO29 does not exist */ + _NOT_EXIST, /* GPIO30 does not exist */ + _NOT_EXIST, /* GPIO31 does not exist */ +#if MODULE_ESP_RTC_TIMER_32K + _NOT_EXIST, /* GPIO32 is used for external 32K crystal */ + _NOT_EXIST, /* GPIO33 is used for external 32K crystal */ +#else + _GPIO, /* GPIO32 */ + _GPIO, /* GPIO33 */ +#endif + _GPIO, /* GPIO34 */ + _GPIO, /* GPIO35 */ + _GPIO, /* GPIO36 */ + _GPIO, /* GPIO37 */ + _GPIO, /* GPIO38 */ + _GPIO /* GPIO39 */ +}; diff --git a/tests/external_board_dirs/esp-ci-boards/esp32-ci/Makefile.dep b/tests/external_board_dirs/esp-ci-boards/esp32-ci/Makefile.dep index 53c6888651..4b5fcc4921 100644 --- a/tests/external_board_dirs/esp-ci-boards/esp32-ci/Makefile.dep +++ b/tests/external_board_dirs/esp-ci-boards/esp32-ci/Makefile.dep @@ -1,6 +1,7 @@ # This must be a different name than 'board' as it is implemented by 'esp32-wrover-kit' USEMODULE += board_esp32-ci +USEMODULE += esp_idf_gpio_hal USEMODULE += esp_idf_heap USEMODULE += esp_log_startup USEMODULE += esp_log_tagged