1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

Merge pull request #18270 from gschorcht/cpu/esp32/periph_hal_esp32_gpio

cpu/esp32: use ESP-IDF gpio HAL for periph/gpio
This commit is contained in:
benpicco 2022-07-15 15:44:13 +02:00 committed by GitHub
commit dd806ce72e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 625 additions and 429 deletions

View File

@ -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

View File

@ -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 <gunar@schorcht.net>
* @}
*/
#include <stdbool.h>
#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

View File

@ -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.

View File

@ -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 \
#

View File

@ -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 <gunar@schorcht.net>
* @}
*/
#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 */

View File

@ -23,19 +23,12 @@
#include <stdbool.h>
#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

View File

@ -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 */
/** @} */

View File

@ -1,3 +1,7 @@
MODULE = periph
ifneq (,$(filter periph_gpio,$(USEMODULE)))
SRC += gpio_arch.c
endif
include $(RIOTMAKE)/periph.mk

View File

@ -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 <assert.h>
#include <stdbool.h>
#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
}
}

View File

@ -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 <gunar@schorcht.net>
* @}
*/
#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 */
};

View File

@ -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