mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
532 lines
18 KiB
C
532 lines
18 KiB
C
/*
|
|
* Copyright (C) 2018 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 Low-level GPIO driver implementation for ESP32
|
|
*
|
|
* @author Gunar Schorcht <gunar@schorcht.net>
|
|
* @}
|
|
*/
|
|
|
|
#define ENABLE_DEBUG (0)
|
|
#include "debug.h"
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include "log.h"
|
|
#include "periph/gpio.h" /* RIOT gpio.h */
|
|
|
|
#include "esp/common_macros.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_io_reg.h"
|
|
#include "soc/rtc_io_struct.h"
|
|
#include "xtensa/xtensa_api.h"
|
|
|
|
#include "esp_common.h"
|
|
#include "adc_arch.h"
|
|
#include "gpio_arch.h"
|
|
#include "irq_arch.h"
|
|
#include "syscalls.h"
|
|
|
|
#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 */
|
|
};
|
|
|
|
/* Table of RTCIO GPIO pins information */
|
|
static const struct _rtc_gpio_t _rtc_gpios[] = {
|
|
{ 0, RTC_IO_SENSOR_PADS_REG, 27, 32, 32 }, /* rtc0 (gpio36) - no pullup/pulldown */
|
|
{ 1, RTC_IO_SENSOR_PADS_REG, 26, 32, 32 }, /* rtc1 (gpio37) - no pullup/pulldown */
|
|
{ 2, RTC_IO_SENSOR_PADS_REG, 25, 32, 32 }, /* rtc2 (gpio38) - no pullup/pulldown */
|
|
{ 3, RTC_IO_SENSOR_PADS_REG, 24, 32, 32 }, /* rtc3 (gpio39) - no pullup/pulldown */
|
|
{ 4, RTC_IO_ADC_PAD_REG, 29, 32, 32 }, /* rtc4 (gpio34) - no pullup/pulldown */
|
|
{ 5, RTC_IO_ADC_PAD_REG, 28, 32, 32 }, /* rtc5 (gpio35) - no pullup/pulldown */
|
|
{ 6, RTC_IO_PAD_DAC1_REG, 17, 27, 28 }, /* rtc6 (gpio25) */
|
|
{ 7, RTC_IO_PAD_DAC2_REG, 17, 27, 28 }, /* rtc7 (gpio26) */
|
|
{ 8, RTC_IO_XTAL_32K_PAD_REG, 18, 27, 28 },/* rtc8 (gpio33) */
|
|
{ 9, RTC_IO_XTAL_32K_PAD_REG, 17, 22, 23 },/* rtc9 (gpio32) */
|
|
{ 10, RTC_IO_TOUCH_PAD0_REG, 19, 27, 28 }, /* rtc10 (gpio4) */
|
|
{ 11, RTC_IO_TOUCH_PAD1_REG, 19, 27, 28 }, /* rtc11 (gpio0) */
|
|
{ 12, RTC_IO_TOUCH_PAD2_REG, 19, 27, 28 }, /* rtc12 (gpio2) */
|
|
{ 13, RTC_IO_TOUCH_PAD3_REG, 19, 27, 28 }, /* rtc13 (gpio15) */
|
|
{ 14, RTC_IO_TOUCH_PAD4_REG, 19, 27, 28 }, /* rtc14 (gpio13) */
|
|
{ 15, RTC_IO_TOUCH_PAD5_REG, 19, 27, 28 }, /* rtc15 (gpio12) */
|
|
{ 16, RTC_IO_TOUCH_PAD6_REG, 19, 27, 28 }, /* rtc16 (gpio14) */
|
|
{ 17, RTC_IO_TOUCH_PAD7_REG, 19, 27, 28 } /* rtc17 (gpio27) */
|
|
};
|
|
|
|
/* 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 thes 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 */
|
|
_GPIO, /* gpio32 */
|
|
_GPIO, /* gpio33 */
|
|
_GPIO, /* gpio34 */
|
|
_GPIO, /* gpio35 */
|
|
_GPIO, /* gpio36 */
|
|
_GPIO, /* gpio37 */
|
|
_GPIO, /* gpio38 */
|
|
_GPIO /* gpio39 */
|
|
};
|
|
|
|
/* String representation of usage types */
|
|
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 */
|
|
|
|
#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_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)
|
|
|
|
int gpio_init(gpio_t pin, gpio_mode_t mode)
|
|
{
|
|
CHECK_PARAM_RET(pin < GPIO_PIN_NUMOF, -1);
|
|
|
|
/* check if the pin can be used as GPIO or if it is used for something else */
|
|
if (_gpio_pin_usage[pin] != _GPIO) {
|
|
LOG_TAG_ERROR("gpio", "GPIO%d is already used as %s signal\n", pin,
|
|
_gpio_pin_usage_str[_gpio_pin_usage[pin]]);
|
|
return -1;
|
|
}
|
|
|
|
/* 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;
|
|
|
|
case GPIO_IN_PD:
|
|
case GPIO_IN_PU:
|
|
/* GPIOs 34 ... 39 have no software controlable pullups/pulldowns */
|
|
LOG_TAG_ERROR("gpio",
|
|
"GPIO%d has no pullups/pulldowns\n", pin);
|
|
return -1;
|
|
default: break;
|
|
}
|
|
}
|
|
|
|
const struct _rtc_gpio_t* rtc = (_gpio_to_rtc[pin] != -1) ?
|
|
&_rtc_gpios[_gpio_to_rtc[pin]] : NULL;
|
|
|
|
/* 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));
|
|
}
|
|
|
|
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));
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#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] = { };
|
|
|
|
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();
|
|
}
|
|
|
|
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)) {
|
|
return -1;
|
|
}
|
|
|
|
gpio_isr_ctx_table[pin].cb = cb;
|
|
gpio_isr_ctx_table[pin].arg = arg;
|
|
|
|
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;
|
|
|
|
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));
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void gpio_irq_enable (gpio_t pin)
|
|
{
|
|
CHECK_PARAM(pin < GPIO_PIN_NUMOF);
|
|
|
|
gpio_int_enabled_table [pin] = true;
|
|
}
|
|
|
|
void gpio_irq_disable (gpio_t pin)
|
|
{
|
|
CHECK_PARAM(pin < GPIO_PIN_NUMOF);
|
|
|
|
gpio_int_enabled_table [pin] = false;
|
|
}
|
|
|
|
#endif /* MODULE_PERIPH_GPIO_IRQ */
|
|
|
|
int gpio_read (gpio_t pin)
|
|
{
|
|
CHECK_PARAM_RET(pin < GPIO_PIN_NUMOF, -1);
|
|
return GPIO_REG_BIT_GET(in, in1, pin) ? 1 : 0;
|
|
}
|
|
|
|
void gpio_write (gpio_t pin, int value)
|
|
{
|
|
DEBUG("%s gpio=%u val=%d\n", __func__, pin, value);
|
|
CHECK_PARAM(pin < GPIO_PIN_NUMOF);
|
|
if (value) {
|
|
GPIO_PIN_SET(pin);
|
|
}
|
|
else {
|
|
GPIO_PIN_CLR(pin);
|
|
}
|
|
}
|
|
|
|
void gpio_set (gpio_t pin)
|
|
{
|
|
DEBUG("%s gpio=%u\n", __func__, pin);
|
|
CHECK_PARAM(pin < GPIO_PIN_NUMOF);
|
|
GPIO_PIN_SET(pin);
|
|
}
|
|
|
|
void gpio_clear (gpio_t pin)
|
|
{
|
|
DEBUG("%s gpio=%u\n", __func__, pin);
|
|
CHECK_PARAM(pin < GPIO_PIN_NUMOF);
|
|
GPIO_PIN_CLR(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);
|
|
}
|
|
|
|
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;
|
|
return 0;
|
|
}
|
|
|
|
gpio_pin_usage_t gpio_get_pin_usage (gpio_t pin)
|
|
{
|
|
return (pin < GPIO_PIN_NUMOF) ? _gpio_pin_usage[pin] : _NOT_EXIST;
|
|
}
|
|
|
|
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)]];
|
|
}
|
|
|
|
|
|
void gpio_pullup_dis (gpio_t pin)
|
|
{
|
|
CHECK_PARAM(pin < GPIO_PIN_NUMOF);
|
|
|
|
const struct _rtc_gpio_t* rtc = (_gpio_to_rtc[pin] != -1) ?
|
|
&_rtc_gpios[_gpio_to_rtc[pin]] : NULL;
|
|
|
|
REG_CLR_BIT(_gpio_to_iomux_reg[pin], FUN_PU);
|
|
if (rtc) {
|
|
REG_CLR_BIT(rtc->reg, BIT(rtc->pullup));
|
|
}
|
|
}
|
|
|
|
int8_t gpio_is_rtcio (gpio_t pin)
|
|
{
|
|
return _gpio_to_rtc[pin];
|
|
}
|
|
|
|
int gpio_config_sleep_mode (gpio_t pin, bool mode, bool input)
|
|
{
|
|
return rtcio_config_sleep_mode (pin, mode, input);
|
|
}
|
|
|
|
int gpio_set_direction(gpio_t pin, gpio_mode_t mode)
|
|
{
|
|
/* TODO implementation, for the moment we simply initialize the GPIO */
|
|
return gpio_init(pin, mode);
|
|
}
|