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:
commit
dd806ce72e
@ -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
|
||||
|
133
cpu/esp32/esp-idf-api/gpio.c
Normal file
133
cpu/esp32/esp-idf-api/gpio.c
Normal 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
|
@ -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.
|
||||
|
@ -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 \
|
||||
#
|
||||
|
||||
|
62
cpu/esp32/include/esp_idf_api/gpio.h
Normal file
62
cpu/esp32/include/esp_idf_api/gpio.h
Normal 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 */
|
@ -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
|
||||
|
@ -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 */
|
||||
/** @} */
|
||||
|
||||
|
@ -1,3 +1,7 @@
|
||||
MODULE = periph
|
||||
|
||||
ifneq (,$(filter periph_gpio,$(USEMODULE)))
|
||||
SRC += gpio_arch.c
|
||||
endif
|
||||
|
||||
include $(RIOTMAKE)/periph.mk
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
129
cpu/esp32/periph/gpio_arch.c
Normal file
129
cpu/esp32/periph/gpio_arch.c
Normal 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 */
|
||||
};
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user