2015-11-30 22:56:40 +00:00
|
|
|
/* GPIO management functions
|
|
|
|
*
|
|
|
|
* Part of esp-open-rtos
|
|
|
|
* Copyright (C) 2015 Angus Gratton
|
|
|
|
* BSD Licensed as described in the file LICENSE
|
|
|
|
*/
|
|
|
|
#include <esp/gpio.h>
|
2016-08-30 11:22:05 +00:00
|
|
|
#include <esp/rtc_regs.h>
|
2015-11-30 22:56:40 +00:00
|
|
|
|
|
|
|
void gpio_enable(const uint8_t gpio_num, const gpio_direction_t direction)
|
|
|
|
{
|
2016-08-30 11:22:05 +00:00
|
|
|
if (gpio_num == 16) {
|
|
|
|
RTC.GPIO_CFG[3] = (RTC.GPIO_CFG[3] & 0xffffffbc) | 1;
|
|
|
|
RTC.GPIO_CONF = (RTC.GPIO_CONF & 0xfffffffe) | 0;
|
|
|
|
switch (direction) {
|
|
|
|
case GPIO_INPUT:
|
|
|
|
RTC.GPIO_ENABLE = (RTC.GPIO_OUT & 0xfffffffe);
|
|
|
|
break;
|
|
|
|
case GPIO_OUTPUT:
|
|
|
|
case GPIO_OUT_OPEN_DRAIN:
|
|
|
|
/* TODO open drain? */
|
|
|
|
RTC.GPIO_ENABLE = (RTC.GPIO_OUT & 0xfffffffe) | 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-02-22 02:34:11 +00:00
|
|
|
switch (direction) {
|
2015-11-30 22:56:40 +00:00
|
|
|
case GPIO_INPUT:
|
2016-02-22 02:34:11 +00:00
|
|
|
GPIO.ENABLE_OUT_CLEAR = BIT(gpio_num);
|
|
|
|
iomux_set_gpio_function(gpio_num, false);
|
2015-11-30 22:56:40 +00:00
|
|
|
break;
|
|
|
|
case GPIO_OUTPUT:
|
2016-02-22 02:34:11 +00:00
|
|
|
GPIO.CONF[gpio_num] &= ~GPIO_CONF_OPEN_DRAIN;
|
|
|
|
GPIO.ENABLE_OUT_SET = BIT(gpio_num);
|
|
|
|
iomux_set_gpio_function(gpio_num, true);
|
2015-11-30 22:56:40 +00:00
|
|
|
break;
|
|
|
|
case GPIO_OUT_OPEN_DRAIN:
|
|
|
|
GPIO.CONF[gpio_num] |= GPIO_CONF_OPEN_DRAIN;
|
|
|
|
GPIO.ENABLE_OUT_SET = BIT(gpio_num);
|
2016-02-22 02:34:11 +00:00
|
|
|
iomux_set_gpio_function(gpio_num, true);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void gpio_set_pullup(uint8_t gpio_num, bool enabled, bool enabled_during_sleep)
|
|
|
|
{
|
|
|
|
uint32_t flags = 0;
|
|
|
|
|
|
|
|
if (enabled) {
|
|
|
|
flags |= IOMUX_PIN_PULLUP;
|
|
|
|
}
|
|
|
|
if (enabled_during_sleep) {
|
|
|
|
flags |= IOMUX_PIN_PULLUP_SLEEP;
|
|
|
|
}
|
|
|
|
iomux_set_pullup_flags(gpio_to_iomux(gpio_num), flags);
|
2015-11-30 22:56:40 +00:00
|
|
|
}
|
|
|
|
|
2016-11-29 19:58:24 +00:00
|
|
|
static gpio_interrupt_handler_t gpio_interrupt_handlers[16] = { 0 };
|
|
|
|
|
2017-07-22 12:09:09 +00:00
|
|
|
void __attribute__((weak)) IRAM gpio_interrupt_handler(void *arg)
|
2016-11-29 19:58:24 +00:00
|
|
|
{
|
|
|
|
uint32_t status_reg = GPIO.STATUS;
|
|
|
|
GPIO.STATUS_CLEAR = status_reg;
|
|
|
|
|
|
|
|
uint8_t gpio_idx;
|
2017-07-22 12:09:09 +00:00
|
|
|
while ((gpio_idx = __builtin_ffs(status_reg)))
|
2016-11-29 19:58:24 +00:00
|
|
|
{
|
|
|
|
gpio_idx--;
|
|
|
|
status_reg &= ~BIT(gpio_idx);
|
2017-07-22 12:09:09 +00:00
|
|
|
if (FIELD2VAL(GPIO_CONF_INTTYPE, GPIO.CONF[gpio_idx])) {
|
2016-11-29 19:58:24 +00:00
|
|
|
gpio_interrupt_handler_t handler = gpio_interrupt_handlers[gpio_idx];
|
|
|
|
if (handler) {
|
|
|
|
handler(gpio_idx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void gpio_set_interrupt(const uint8_t gpio_num, const gpio_inttype_t int_type, gpio_interrupt_handler_t handler)
|
|
|
|
{
|
|
|
|
gpio_interrupt_handlers[gpio_num] = handler;
|
|
|
|
|
|
|
|
GPIO.CONF[gpio_num] = SET_FIELD(GPIO.CONF[gpio_num], GPIO_CONF_INTTYPE, int_type);
|
2017-07-22 12:09:09 +00:00
|
|
|
if (int_type != GPIO_INTTYPE_NONE) {
|
|
|
|
_xt_isr_attach(INUM_GPIO, gpio_interrupt_handler, NULL);
|
2016-11-29 19:58:24 +00:00
|
|
|
_xt_isr_unmask(1<<INUM_GPIO);
|
|
|
|
}
|
|
|
|
}
|