ESP32: Add GPIO support

This commit is contained in:
Gregory Nutt 2016-10-26 12:11:24 -06:00
parent 946045075e
commit 650757bbf0
11 changed files with 1241 additions and 362 deletions

View File

@ -163,7 +163,7 @@
/* Total number of peripherals */
#define NR_PERIPHERALS 69
#define ESP32_NPERIPHERALS 69
/* Exceptions
*
@ -192,6 +192,7 @@
#define XTENSA_IRQ_TIMER1 1 /* INTERRUPT, bit 15 */
#define XTENSA_IRQ_TIMER2 2 /* INTERRUPT, bit 16 */
#define XTENSA_NIRQ_INTERNAL 3 /* Number of dispatch internal interrupts */
#define XTENSA_IRQ_FIRSTPERIPH 3 /* First peripheral IRQ number */
/* IRQ numbers for peripheral interrupts coming throught the Interrupt
@ -287,9 +288,26 @@
#define ESP32_IRQ_SREG2 ESP32_IRQ_TG1_WDT_EDGE
#define ESP32_NIRQS_SREG2 5
#define ESP32_NIRQ_PERIPH ESP32_NPERIPHERALS
/* Second level GPIO interrupts. GPIO interrupts are decoded and dispatched as
* a second level of decoding: The first level dispatches to the GPIO interrupt
* handler. The second to the decoded GPIO interrupt handler.
*/
#ifdef CONFIG_ESP32_GPIO_IRQ
# define ESP32_NIRQ_GPIO 40
# define ESP32_FIRST_GPIOIRQ (XTENSA_NIRQ_INTERNAL+ESP32_NIRQ_PERIPH)
# define ESP32_LAST_GPIOIRQ (ESP32_FIRST_GPIOIRQ+ESP32_NIRQ_GPIO-1)
# define ESP32_PIN2IRQ(p) ((p) + ESP32_FIRST_GPIOIRQ)
# define ESP32_IRQ2PIN(i) ((i) - ESP32_FIRST_GPIOIRQ)
#else
# define ESP32_NIRQ_GPIO 0
#endif
/* Total number of interrupts */
#define NR_IRQS (ESP32_IRQ_CACHE_IA+1)
#define NR_IRQS (XTENSA_NIRQ_INTERNAL+ESP32_NIRQ_PERIPH+ESP32_NIRQ_GPIO)
/* CPU Interrupts.
*
@ -347,23 +365,32 @@
#define ESP32_CPUINT_LEVELPERIPH_18 26
#define ESP32_CPUINT_LEVELPERIPH_19 27
#define ESP32_CPUINT_LEVELPERIPH_20 31
#define ESP32_CPUINT_NLEVELPERIPHS 21
#define EPS32_CPUINT_LEVELSET 0x8fbe333f
#define ESP32_CPUINT_EDGEPERIPH_0 10
#define ESP32_CPUINT_EDGEPERIPH_1 22
#define ESP32_CPUINT_EDGEPERIPH_2 28
#define ESP32_CPUINT_EDGEPERIPH_3 30
#define ESP32_CPUINT_NEDGEPERIPHS 4
#define EPS32_CPUINT_EDGESET 0x50400400
#define ESP32_CPUINT_NNMIPERIPHS 4
#define EPS32_CPUINT_NMISET 0x00004000
#define ESP32_CPUINT_TIMER0 6
#define ESP32_CPUINT_SOFTWARE0 7
#define ESP32_CPUINT_PROFILING 11
#define ESP32_CPUINT_TIMER1 15
#define ESP32_CPUINT_TIMER2 16
#define ESP32_CPUINT_SOFTWARE1 29
#define ESP32_CPUINT_NINTERNAL 5
#define ESP32_CPUINT_MAX 31
#define EPS32_CPUINT_PERIPHSET 0xdffe7f3f
#define EPS32_CPUINT_PERIPHSET 0xdffe6f3f
#define EPS32_CPUINT_INTERNALSET 0x200180c0
/* Priority 1: 0-10, 12-13, 17-18 (15)

View File

@ -419,3 +419,4 @@ xtensa_context_restore:
l32i a0, a2, (4 * REG_A0) /* Restore a0 */
l32i a2, a2, (4 * REG_A2) /* Restore A2 */
rfe /* And return from "exception" */

View File

@ -193,6 +193,11 @@ config ESP32_WIRELESS
endmenu # ESP32 Peripheral Selection
config ESP32_GPIO_IRQ
bool "GPIO pin interrupts"
---help---
Enable support for interrupting GPIO pins
config ESP32_BT_RESERVE_DRAM
int "Reserved BT DRAM"
default 0

View File

@ -377,18 +377,22 @@
#define GPIO_PIN_INT_ENA_M ((GPIO_PIN_INT_ENA_V)<<(GPIO_PIN_INT_ENA_S))
#define GPIO_PIN_INT_ENA_V 0x0000001F
#define GPIO_PIN_INT_ENA_S 13
#define GPIO_PIN_CONFIG 0x00000003
#define GPIO_PIN_CONFIG_M ((GPIO_PIN_CONFIG_V)<<(GPIO_PIN_CONFIG_S))
#define GPIO_PIN_CONFIG_V 0x00000003
#define GPIO_PIN_CONFIG_S 11
#define GPIO_PIN_WAKEUP_ENABLE (BIT(10))
#define GPIO_PIN_WAKEUP_ENABLE_M (BIT(10))
#define GPIO_PIN_WAKEUP_ENABLE_V 0x1
#define GPIO_PIN_WAKEUP_ENABLE_S 10
#define GPIO_PIN_INT_TYPE 0x00000007
#define GPIO_PIN_INT_TYPE_M ((GPIO_PIN_INT_TYPE_V)<<(GPIO_PIN_INT_TYPE_S))
#define GPIO_PIN_INT_TYPE_V 0x00000007
#define GPIO_PIN_INT_TYPE_S 7
#define GPIO_PIN_PAD_DRIVER (BIT(2))
#define GPIO_PIN_PAD_DRIVER_M (BIT(2))
#define GPIO_PIN_PAD_DRIVER_V 0x1

View File

@ -0,0 +1,288 @@
/****************************************************************************
* arch/xtensa/src/esp32/esp32_gpio.c
*
* Developed for NuttX by:
*
* Copyright (C) 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Derivies from sample code provided by Expressif Systems:
*
* Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
****************************************************************************/
#ifndef __ARCH_XTENSA_SRC_ESP32_CHIP_ESP32_MUX_H
#define __ARCH_XTENSA_SRC_ESP32_CHIP_ESP32_MUX_H 1
/****************************************************************************
* Included Files
****************************************************************************/
#include "chip/esp32_soc.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define SLP_OE (BIT(0))
#define SLP_SEL (BIT(1))
#define SLP_PD (BIT(2))
#define SLP_PU (BIT(3))
#define SLP_IE (BIT(4))
#define SLP_DRV 0x3
#define SLP_DRV_S 5
#define FUN_PD (BIT(7))
#define FUN_PU (BIT(8))
#define FUN_IE (BIT(9))
#define FUN_DRV 0x3
#define FUN_DRV_S 10
#define MCU_SEL 0x7
#define MCU_SEL_S 12
#define PIN_INPUT_ENABLE(PIN_NAME) SET_PERI_REG_MASK(PIN_NAME,FUN_IE)
#define PIN_INPUT_DISABLE(PIN_NAME) CLEAR_PERI_REG_MASK(PIN_NAME,FUN_IE)
#define PIN_SET_DRV(PIN_NAME, drv) REG_SET_FIELD(PIN_NAME, FUN_DRV, (drv));
#define PIN_PULLUP_DIS(PIN_NAME) REG_CLR_BIT(PIN_NAME, FUN_PU)
#define PIN_PULLUP_EN(PIN_NAME) REG_SET_BIT(PIN_NAME, FUN_PU)
#define PIN_PULLDWN_DIS(PIN_NAME) REG_CLR_BIT(PIN_NAME, FUN_PD)
#define PIN_PULLDWN_EN(PIN_NAME) REG_SET_BIT(PIN_NAME, FUN_PD)
#define PIN_FUNC_SELECT(PIN_NAME, FUNC) REG_SET_FIELD(PIN_NAME, MCU_SEL, FUNC)
#define PIN_FUNC_GPIO 2
#define PIN_CTRL (DR_REG_IO_MUX_BASE +0x00)
#define CLK_OUT3 0xf
#define CLK_OUT3_S 8
#define CLK_OUT2 0xf
#define CLK_OUT2_S 4
#define CLK_OUT1 0xf
#define CLK_OUT1_S 0
#define PERIPHS_IO_MUX_GPIO0_U (DR_REG_IO_MUX_BASE +0x44)
#define FUNC_GPIO0_EMAC_TX_CLK 5
#define FUNC_GPIO0_GPIO0 2
#define FUNC_GPIO0_CLK_OUT1 1
#define FUNC_GPIO0_GPIO0_0 0
#define PERIPHS_IO_MUX_U0TXD_U (DR_REG_IO_MUX_BASE +0x88)
#define FUNC_U0TXD_EMAC_RXD2 3
#define FUNC_U0TXD_GPIO1 2
#define FUNC_U0TXD_CLK_OUT3 1
#define FUNC_U0TXD_U0TXD 0
#define PERIPHS_IO_MUX_GPIO2_U (DR_REG_IO_MUX_BASE +0x40)
#define FUNC_GPIO2_SD_DATA0 4
#define FUNC_GPIO2_HS2_DATA0 3
#define FUNC_GPIO2_GPIO2 2
#define FUNC_GPIO2_HSPIWP 1
#define FUNC_GPIO2_GPIO2_0 0
#define PERIPHS_IO_MUX_U0RXD_U (DR_REG_IO_MUX_BASE +0x84)
#define FUNC_U0RXD_GPIO3 2
#define FUNC_U0RXD_CLK_OUT2 1
#define FUNC_U0RXD_U0RXD 0
#define PERIPHS_IO_MUX_GPIO4_U (DR_REG_IO_MUX_BASE +0x48)
#define FUNC_GPIO4_EMAC_TX_ER 5
#define FUNC_GPIO4_SD_DATA1 4
#define FUNC_GPIO4_HS2_DATA1 3
#define FUNC_GPIO4_GPIO4 2
#define FUNC_GPIO4_HSPIHD 1
#define FUNC_GPIO4_GPIO4_0 0
#define PERIPHS_IO_MUX_GPIO5_U (DR_REG_IO_MUX_BASE +0x6c)
#define FUNC_GPIO5_EMAC_RX_CLK 5
#define FUNC_GPIO5_HS1_DATA6 3
#define FUNC_GPIO5_GPIO5 2
#define FUNC_GPIO5_VSPICS0 1
#define FUNC_GPIO5_GPIO5_0 0
#define PERIPHS_IO_MUX_SD_CLK_U (DR_REG_IO_MUX_BASE +0x60)
#define FUNC_SD_CLK_U1CTS 4
#define FUNC_SD_CLK_HS1_CLK 3
#define FUNC_SD_CLK_GPIO6 2
#define FUNC_SD_CLK_SPICLK 1
#define FUNC_SD_CLK_SD_CLK 0
#define PERIPHS_IO_MUX_SD_DATA0_U (DR_REG_IO_MUX_BASE +0x64)
#define FUNC_SD_DATA0_U2RTS 4
#define FUNC_SD_DATA0_HS1_DATA0 3
#define FUNC_SD_DATA0_GPIO7 2
#define FUNC_SD_DATA0_SPIQ 1
#define FUNC_SD_DATA0_SD_DATA0 0
#define PERIPHS_IO_MUX_SD_DATA1_U (DR_REG_IO_MUX_BASE +0x68)
#define FUNC_SD_DATA1_U2CTS 4
#define FUNC_SD_DATA1_HS1_DATA1 3
#define FUNC_SD_DATA1_GPIO8 2
#define FUNC_SD_DATA1_SPID 1
#define FUNC_SD_DATA1_SD_DATA1 0
#define PERIPHS_IO_MUX_SD_DATA2_U (DR_REG_IO_MUX_BASE +0x54)
#define FUNC_SD_DATA2_U1RXD 4
#define FUNC_SD_DATA2_HS1_DATA2 3
#define FUNC_SD_DATA2_GPIO9 2
#define FUNC_SD_DATA2_SPIHD 1
#define FUNC_SD_DATA2_SD_DATA2 0
#define PERIPHS_IO_MUX_SD_DATA3_U (DR_REG_IO_MUX_BASE +0x58)
#define FUNC_SD_DATA3_U1TXD 4
#define FUNC_SD_DATA3_HS1_DATA3 3
#define FUNC_SD_DATA3_GPIO10 2
#define FUNC_SD_DATA3_SPIWP 1
#define FUNC_SD_DATA3_SD_DATA3 0
#define PERIPHS_IO_MUX_SD_CMD_U (DR_REG_IO_MUX_BASE +0x5c)
#define FUNC_SD_CMD_U1RTS 4
#define FUNC_SD_CMD_HS1_CMD 3
#define FUNC_SD_CMD_GPIO11 2
#define FUNC_SD_CMD_SPICS0 1
#define FUNC_SD_CMD_SD_CMD 0
#define PERIPHS_IO_MUX_MTDI_U (DR_REG_IO_MUX_BASE +0x34)
#define FUNC_MTDI_EMAC_TXD3 5
#define FUNC_MTDI_SD_DATA2 4
#define FUNC_MTDI_HS2_DATA2 3
#define FUNC_MTDI_GPIO12 2
#define FUNC_MTDI_HSPIQ 1
#define FUNC_MTDI_MTDI 0
#define PERIPHS_IO_MUX_MTCK_U (DR_REG_IO_MUX_BASE +0x38)
#define FUNC_MTCK_EMAC_RX_ER 5
#define FUNC_MTCK_SD_DATA3 4
#define FUNC_MTCK_HS2_DATA3 3
#define FUNC_MTCK_GPIO13 2
#define FUNC_MTCK_HSPID 1
#define FUNC_MTCK_MTCK 0
#define PERIPHS_IO_MUX_MTMS_U (DR_REG_IO_MUX_BASE +0x30)
#define FUNC_MTMS_EMAC_TXD2 5
#define FUNC_MTMS_SD_CLK 4
#define FUNC_MTMS_HS2_CLk 3
#define FUNC_MTMS_GPIO14 2
#define FUNC_MTMS_HSPICLK 1
#define FUNC_MTMS_MTMS 0
#define PERIPHS_IO_MUX_MTDO_U (DR_REG_IO_MUX_BASE +0x3c)
#define FUNC_MTDO_EMAC_RXD3 5
#define FUNC_MTDO_SD_CMD 4
#define FUNC_MTDO_HS2_CMD 3
#define FUNC_MTDO_GPIO15 2
#define FUNC_MTDO_HSPICS0 1
#define FUNC_MTDO_MTDO 0
#define PERIPHS_IO_MUX_GPIO16_U (DR_REG_IO_MUX_BASE +0x4c)
#define FUNC_GPIO16_EMAC_CLK_OUT 5
#define FUNC_GPIO16_U2RXD 4
#define FUNC_GPIO16_HS1_DATA4 3
#define FUNC_GPIO16_GPIO16 2
#define FUNC_GPIO16_GPIO16_0 0
#define PERIPHS_IO_MUX_GPIO17_U (DR_REG_IO_MUX_BASE +0x50)
#define FUNC_GPIO17_EMAC_CLK_OUT_180 5
#define FUNC_GPIO17_U2TXD 4
#define FUNC_GPIO17_HS1_DATA5 3
#define FUNC_GPIO17_GPIO17 2
#define FUNC_GPIO17_GPIO17_0 0
#define PERIPHS_IO_MUX_GPIO18_U (DR_REG_IO_MUX_BASE +0x70)
#define FUNC_GPIO18_HS1_DATA7 3
#define FUNC_GPIO18_GPIO18 2
#define FUNC_GPIO18_VSPICLK 1
#define FUNC_GPIO18_GPIO18_0 0
#define PERIPHS_IO_MUX_GPIO19_U (DR_REG_IO_MUX_BASE +0x74)
#define FUNC_GPIO19_EMAC_TXD0 5
#define FUNC_GPIO19_U0CTS 3
#define FUNC_GPIO19_GPIO19 2
#define FUNC_GPIO19_VSPIQ 1
#define FUNC_GPIO19_GPIO19_0 0
#define PERIPHS_IO_MUX_GPIO20_U (DR_REG_IO_MUX_BASE +0x78)
#define FUNC_GPIO20_GPIO20 2
#define FUNC_GPIO20_GPIO20_0 0
#define PERIPHS_IO_MUX_GPIO21_U (DR_REG_IO_MUX_BASE +0x7c)
#define FUNC_GPIO21_EMAC_TX_EN 5
#define FUNC_GPIO21_GPIO21 2
#define FUNC_GPIO21_VSPIHD 1
#define FUNC_GPIO21_GPIO21_0 0
#define PERIPHS_IO_MUX_GPIO22_U (DR_REG_IO_MUX_BASE +0x80)
#define FUNC_GPIO22_EMAC_TXD1 5
#define FUNC_GPIO22_U0RTS 3
#define FUNC_GPIO22_GPIO22 2
#define FUNC_GPIO22_VSPIWP 1
#define FUNC_GPIO22_GPIO22_0 0
#define PERIPHS_IO_MUX_GPIO23_U (DR_REG_IO_MUX_BASE +0x8c)
#define FUNC_GPIO23_HS1_STROBE 3
#define FUNC_GPIO23_GPIO23 2
#define FUNC_GPIO23_VSPID 1
#define FUNC_GPIO23_GPIO23_0 0
#define PERIPHS_IO_MUX_GPIO24_U (DR_REG_IO_MUX_BASE +0x90)
#define FUNC_GPIO24_GPIO24 2
#define FUNC_GPIO24_GPIO24_0 0
#define PERIPHS_IO_MUX_GPIO25_U (DR_REG_IO_MUX_BASE +0x24)
#define FUNC_GPIO25_EMAC_RXD0 5
#define FUNC_GPIO25_GPIO25 2
#define FUNC_GPIO25_GPIO25_0 0
#define PERIPHS_IO_MUX_GPIO26_U (DR_REG_IO_MUX_BASE +0x28)
#define FUNC_GPIO26_EMAC_RXD1 5
#define FUNC_GPIO26_GPIO26 2
#define FUNC_GPIO26_GPIO26_0 0
#define PERIPHS_IO_MUX_GPIO27_U (DR_REG_IO_MUX_BASE +0x2c)
#define FUNC_GPIO27_EMAC_RX_DV 5
#define FUNC_GPIO27_GPIO27 2
#define FUNC_GPIO27_GPIO27_0 0
#define PERIPHS_IO_MUX_GPIO32_U (DR_REG_IO_MUX_BASE +0x1c)
#define FUNC_GPIO32_GPIO32 2
#define FUNC_GPIO32_GPIO32_0 0
#define PERIPHS_IO_MUX_GPIO33_U (DR_REG_IO_MUX_BASE +0x20)
#define FUNC_GPIO33_GPIO33 2
#define FUNC_GPIO33_GPIO33_0 0
#define PERIPHS_IO_MUX_GPIO34_U (DR_REG_IO_MUX_BASE +0x14)
#define FUNC_GPIO34_GPIO34 2
#define FUNC_GPIO34_GPIO34_0 0
#define PERIPHS_IO_MUX_GPIO35_U (DR_REG_IO_MUX_BASE +0x18)
#define FUNC_GPIO35_GPIO35 2
#define FUNC_GPIO35_GPIO35_0 0
#define PERIPHS_IO_MUX_GPIO36_U (DR_REG_IO_MUX_BASE +0x04)
#define FUNC_GPIO36_GPIO36 2
#define FUNC_GPIO36_GPIO36_0 0
#define PERIPHS_IO_MUX_GPIO37_U (DR_REG_IO_MUX_BASE +0x08)
#define FUNC_GPIO37_GPIO37 2
#define FUNC_GPIO37_GPIO37_0 0
#define PERIPHS_IO_MUX_GPIO38_U (DR_REG_IO_MUX_BASE +0x0c)
#define FUNC_GPIO38_GPIO38 2
#define FUNC_GPIO38_GPIO38_0 0
#define PERIPHS_IO_MUX_GPIO39_U (DR_REG_IO_MUX_BASE +0x10)
#define FUNC_GPIO39_GPIO39 2
#define FUNC_GPIO39_GPIO39_0 0
#endif /* __ARCH_XTENSA_SRC_ESP32_CHIP_ESP32_MUX_H */

View File

@ -54,10 +54,6 @@
* Pre-processor Definitions
****************************************************************************/
#define ESP32_INTSET(n) ((1 << (n)) - 1)
#define ESP32_LEVEL_SET ESP32_INTSET(ESP32_CPUINT_NLEVELPERIPHS)
#define ESP32_EDGE_SET ESP32_INTSET(ESP32_CPUINT_NEDGEPERIPHS)
/* Mapping Peripheral IDs to map register addresses
*
* PERIPHERAL ID DPORT REGISTER OFFSET
@ -169,12 +165,11 @@ static uint32_t g_intenable[1];
/* Bitsets for free, unallocated CPU interrupts */
static uint32_t g_level_ints = ESP32_LEVEL_SET;
static uint32_t g_edge_ints = ESP32_EDGE_SET;
static uint32_t g_free_cpuints = 0xffffffff;
/* Bitsets for each interrupt priority 1-5 */
static uint32_t g_priority[5] =
static const uint32_t g_priority[5] =
{
ESP32_INTPRI1_MASK,
ESP32_INTPRI2_MASK,
@ -187,6 +182,75 @@ static uint32_t g_priority[5] =
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: esp32_alloc_cpuint
*
* Description:
* Allocate a CPU interrupt
*
* Input Parameters:
* mask - mask of candidate CPU interrupts. The CPU interrupt will be
* be allocated from free interrupts within this set
*
* Returned Value:
* On success, the allocated level-sensitive, CPU interrupt numbr is
* returned. A negated errno is returned on failure. The only possible
* failure is that all level-sensitive CPU interrupts have already been
* allocated.
*
****************************************************************************/
int esp32_alloc_levelint(uint32_t mask)
{
irqstate_t flags;
uint32_t mask;
uint32_t intset;
int cpuint;
int ret = -ENOMEM;
/* Check if there are is CPU interrupts with the requrested properties
* available.
*/
flags = enter_critical_section();
intset = g_free_cpuints & mask;
if (intset != 0)
{
/* Skip over initial unavailable CPU interrupts quickly in groups
* of 8 interrupt.
*/
for (cpuint = 0, mask = 0xff;
cpuint <= ESP32_CPUINT_MAX;
cpuint += 8, mask <<= 8);
/* Search for an unallocated CPU interrupt number in the remaining
* intset.
*/
for (; cpuint <= ESP32_CPUINT_MAX; cpuint++)
{
/* If the bit corresponding to the CPU interrupt is '1', then
* that CPU interrupt is available.
*/
mask = (1ul << cpuint);
if ((intset & mask) != 0)
{
/* Got it! */
g_free_cpuints &= ~mask;
ret = cpuint;
break;
}
}
}
leave_critical_section(flags);
return ret;
}
/****************************************************************************
* Public Functions
****************************************************************************/
@ -258,83 +322,17 @@ void up_enable_irq(int cpuint)
int esp32_alloc_levelint(int priority)
{
irqstate_t flags;
uint32_t mask;
uint32_t intset;
int cpuint;
int ret = -ENOMEM;
DEBUGASSERT(priority >= ESP32_MIN_PRIORITY && priority <= ESP32_MAX_PRIORITY)
DEBUGASSERT(priority >= ESP32_MIN_PRIORITY &&
priority <= ESP32_MAX_PRIORITY)
/* Check if there are any level CPU interrupts available */
flags = enter_critical_section();
intset = g_level_ints & g_priority[ESP32_PRIO_INDEX(priority)] & ESP32_LEVEL_SET;
if (intset != 0)
{
/* Skip over initial zeroes as quickly in groups of 8 bits. */
for (cpuint = 0, mask = 0xff;
cpuint <= ESP32_CPUINT_MAX && (intset & mask) == 0;
cpuint += 8, mask <<= 8);
/* Search for an unallocated CPU interrupt number in the remaining intset. */
for (; cpuint <= ESP32_CPUINT_MAX && intset != 0; cpuint++)
{
/* If the bit corresponding to the CPU interrupt is '1', then
* that CPU interrupt is available.
/* Check if there are any level CPU interrupts available at the requested
* interrupt priority.
*/
mask = (1ul << cpuint);
if ((intset & mask) != 0)
{
/* Got it! */
g_level_ints &= ~mask;
ret = cpuint;
break;
}
/* Clear the bit in intset so that we may exit the loop sooner */
intset &= ~mask;
}
}
leave_critical_section(flags);
return ret;
}
/****************************************************************************
* Name: esp32_free_levelint
*
* Description:
* Free a previoulsy allocated level CPU interrupt
*
* Input Parameters:
* The CPU interrupt number to be freed
*
* Returned Value:
* None
*
****************************************************************************/
void esp32_free_levelint(int cpuint)
{
irqstate_t flags;
uint32_t mask;
DEBUGASSERT(cpuint >= 0 && cpuint < ESP32_CPUINT_NLEVELPERIPHS);
/* Mark the CPU interrupt as available */
mask = (1ul << cpuint);
flags = enter_critical_section();
DEBUGASSERT((g_level_ints & mask) == 0);
g_level_ints |= mask;
leave_critical_section(flags);
mask = g_priority[ESP32_PRIO_INDEX(priority)] & EPS32_CPUINT_LEVELSET;
return esp_alloc_cpuint(mask);
}
/****************************************************************************
@ -356,60 +354,24 @@ void esp32_free_levelint(int cpuint)
int esp32_alloc_edgeint(int priority)
{
irqstate_t flags;
uint32_t mask;
uint32_t intset;
int cpuint;
int ret = -ENOMEM;
DEBUGASSERT(priority >= ESP32_MIN_PRIORITY && priority <= ESP32_MAX_PRIORITY)
DEBUGASSERT(priority >= ESP32_MIN_PRIORITY &&
priority <= ESP32_MAX_PRIORITY)
/* Check if there are any level CPU interrupts available */
flags = enter_critical_section();
intset = g_edge_ints & g_priority[ESP32_PRIO_INDEX(priority)] & ESP32_EDGE_SET;
if (intset != 0)
{
/* Skip over initial zeroes as quickly in groups of 8 bits. */
for (cpuint = 0, mask = 0xff;
cpuint <= ESP32_CPUINT_MAX && (intset & mask) == 0;
cpuint += 8, mask <<= 8);
/* Search for an unallocated CPU interrupt number in the remaining intset. */
for (; cpuint <= ESP32_CPUINT_MAX && intset != 0; cpuint++)
{
/* If the bit corresponding to the CPU interrupt is '1', then
* that CPU interrupt is available.
/* Check if there are any edge CPU interrupts available at the requested
* interrupt priority.
*/
mask = (1ul << cpuint);
if ((intset & mask) != 0)
{
/* Got it! */
g_edge_ints &= ~mask;
ret = cpuint;
break;
}
/* Clear the bit in intset so that we may exit the loop sooner */
intset &= ~mask;
}
}
leave_critical_section(flags);
return ret;
mask = g_priority[ESP32_PRIO_INDEX(priority)] & EPS32_CPUINT_EDGESET;
return esp_alloc_cpuint(mask);
}
/****************************************************************************
* Name: esp32_free_edgeint
* Name: esp32_free_cpuint
*
* Description:
* Free a previoulsy allocated edge CPU interrupt
* Free a previoulsy allocated CPU interrupt
*
* Input Parameters:
* The CPU interrupt number to be freed
@ -419,7 +381,7 @@ int esp32_alloc_edgeint(int priority)
*
****************************************************************************/
void esp32_free_edgeint(int cpuint)
void esp32_free_cpuint(int cpuint)
{
irqstate_t flags;
uint32_t mask;
@ -430,8 +392,8 @@ void esp32_free_edgeint(int cpuint)
mask = (1ul << cpuint);
flags = enter_critical_section();
DEBUGASSERT((g_edge_ints & mask) == 0);
g_edge_ints |= mask;
DEBUGASSERT((g_free_cpuints & mask) == 0);
g_free_cpuints |= mask;
leave_critical_section(flags);
}
@ -455,7 +417,7 @@ void esp32_attach_peripheral(int cpu, int periphid, int cpuint)
{
uintptr_t regaddr;
DEBUGASSERT(periphid >= 0 && periphid < NR_PERIPHERALS);
DEBUGASSERT(periphid >= 0 && periphid < ESP32_NPERIPHERALS);
DEBUGASSERT(cpuint >= 0 && cpuint <= ESP32_CPUINT_MAX);
#ifdef CONFIG_SMP
DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS);
@ -492,7 +454,7 @@ void esp32_detach_peripheral(int cpu, int periphid)
{
uintptr_t regaddr;
DEBUGASSERT(periphid >= 0 && periphid < NR_PERIPHERALS);
DEBUGASSERT(periphid >= 0 && periphid < ESP32_NPERIPHERALS);
#ifdef CONFIG_SMP
DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS);

View File

@ -65,22 +65,6 @@
int esp32_alloc_levelint(int priority);
/****************************************************************************
* Name: esp32_free_levelint
*
* Description:
* Free a previoulsy allocated level CPU interrupt
*
* Input Parameters:
* cpuint - The CPU interrupt number to be freed
*
* Returned Value:
* None
*
****************************************************************************/
void esp32_free_levelint(int cpuint);
/****************************************************************************
* Name: esp32_alloc_edgeint
*
@ -101,10 +85,10 @@ void esp32_free_levelint(int cpuint);
int esp32_alloc_edgeint(int priority);
/****************************************************************************
* Name: esp32_free_edgeint
* Name: esp32_free_cpuint
*
* Description:
* Free a previoulsy allocated edge CPU interrupt
* Free a previoulsy allocated CPU interrupt
*
* Input Parameters:
* cpuint - The CPU interrupt number to be freed
@ -114,7 +98,7 @@ int esp32_alloc_edgeint(int priority);
*
****************************************************************************/
void esp32_free_edgeint(int cpuint, int priority);
void esp32_free_cpuint(int cpuint, int priority);
/****************************************************************************
* Name: esp32_attach_peripheral

View File

@ -148,7 +148,7 @@ int xtensa_start_handler(int irq, FAR void *context)
/* Detach all peripheral sources APP CPU interrupts */
for (i = 0; i < NR_PERIPHERALS)
for (i = 0; i < ESP32_NPERIPHERALS; i++)
{
esp32_detach_peripheral(1, i);;
}

View File

@ -0,0 +1,423 @@
/****************************************************************************
* arch/xtensa/src/esp32/esp32_gpio.c
*
* Developed for NuttX by:
*
* Copyright (C) 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Derivies from sample code provided by Expressif Systems:
*
* Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <assert.h>
#include <nuttx/irq.h>
#include <arch/irq.h>
#include "chip/esp32_iomux.h"
#include "chip/esp32_gpio.h"
#include "esp32_gpio.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define NGPIO_HPINS (ESP32_NIRQ_GPIO - 32)
#define NGPIO_HMASK ((1ul << NGPIO_HPINS) - 1)
#define _NA_ 0xff
/****************************************************************************
* Private Data
****************************************************************************/
static uint8_t g_gpio_cpuint;
static const uint8_t g_pin2func[40] =
{
0x44, 0x88, 0x40, 0x84, 0x48, 0x6c, 0x60, 0x64, /* 0-7 */
0x68, 0x54, 0x58, 0x5c, 0x34, 0x38, 0x30, 0x3c, /* 8-15 */
0x4c, 0x50, 0x70, 0x74, 0x78, 0x7c, 0x80, 0x8c, /* 16-23 */
_NA_, 0x24, 0x28, 0x2c, _NA_, _NA_, _NA_, _NA_, /* N/A, 25-27, N/A, N/A, N/A, N/A */
0x1c, 0x20, 0x14, 0x18, 0x04, 0x08, 0x0c, 0x10 /* 32-39 */
};
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: gpio_dispatch
*
* Description:
* Second level dispatch for GPIO interrupt handling.
*
****************************************************************************/
#ifdef CONFIG_ESP32_GPIO_IRQ
static void gpio_dispatch(int irq, uint32_t status, uint32_t *regs)
{
uint32_t mask;
int i;
/* Check each bit in the status register */
for (i = 0; i < 32 && status != 0; i++)
{
/* Check if there is an interrupt pending for this pin */
mask = (1ul << i);
if ((status & mask) != 0)
{
/* Yes... perform the second level dispatch */
irq_dispatch(irq + i, regs);
/* Clear the bit in the status so that we might execute this loop
* sooner.
*/
status &= ~mask;
}
}
}
#endif
/****************************************************************************
* Name: gpio_interrupt
*
* Description:
* GPIO interrupt handler.
*
****************************************************************************/
#ifdef CONFIG_ESP32_GPIO_IRQ
static int gpio_interrupt(int irq, FAR void *context)
{
uint32_t status;
uint32_t gpio_intr_status_h = 0;
/* Read and clear the lower GPIO interrupt status */
status = getreg32(GPIO_STATUS_REG);
putreg32(status, GPIO_STATUS_W1TC_REG);
/* Dispatch pending interrupts in the lower GPIO status register */
gpio_dispatch(ESP32_FIRST_GPIOIRQ, status, (uint32_t *)context);
/* Read and clear the upper GPIO interrupt status */
status = getreg32(GPIO_STATUS1_REG) & NGPIO_HMASK;
putreg32(status, GPIO_STATUS1_W1TC_REG);
/* Dispatch pending interrupts in the lower GPIO status register */
gpio_dispatch(ESP32_FIRST_GPIOIRQ + 32, status, (uint32_t *)context);
reutnr OK;
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: esp32_configgpio
*
* Description:
* Configure a GPIO pin based on encoded pin attributes.
*
****************************************************************************/
int esp32_configgpio(int pin, gpio_pinattr_t attr)
{
uintptr_t regaddr;
uint32_t func;
uint32_t cntl;
DEBUGASSERT(pin >=0 && pin <= ESP32_NIRQ_GPIO);
DEBUGASSERT(pin >=0 && pin <= ESP32_NIRQ_GPIO);
/* Handle input pins */
func = 0;
cntrl = 0;
if ((attr & INPUT) != 0)
{
if (pin < 32)
{
putreg32((1ul << pin), GPIO_ENABLE_W1TC_REG);
}
else
{
putreg32((1ul << (pin - 32), GPIO_ENABLE1_DATA_W1TC);
}
if ((attr & PULLUP) != 0)
{
func |= FUN_PU;
}
else if (attr & PULLDOWN)
{
func |= FUN_PD;
}
}
/* Handle output pins */
else if ((attr & OUTPUT) != 0)
{
if (pin < 32)
{
putreg32((1ul << pin), GPIO_ENABLE_DATA_W1TS);
}
else
{
putreg32((1ul << (pin - 32), GPIO_ENABLE1_DATA_W1TS);
}
}
/* Add drivers */
func |= ((uint32_t)(2ul << FUN_DRV_S);
/* Input enable... Required for output as well? */
func |= FUN_IE;
if ((attr & (INPUT | OUTPUT)) != 0)
{
func |= ((uint32_t)(2 << MCU_SEL_S);
}
else if (attr == SPECIAL)
{
func |= ((uint32_t)(((pin) == 1 || (pin) == 3) ? 0 : 1) << MCU_SEL_S);
}
else
{
func |= ((uint32_t)(attr >> 5) << MCU_SEL_S);
}
if ((attr & OPEN_DRAIN) != 0)
{
cntl = (1 << GPIO_PIN_PAD_DRIVER_S);
}
regaddr = DR_REG_IO_MUX_BASE + g_pin2func[pin];
putreg32(func, regaddr);
regaddr = GPIO_REG(pin);
putreg32(cntl, regaddr);
}
/****************************************************************************
* Name: esp32_gpiowrite
*
* Description:
* Write one or zero to the selected GPIO pin
*
****************************************************************************/
void esp32_gpiowrite(int pin, bool value)
{
if (pin > 39)
{
return;
}
if (value)
{
if (pin < 32)
{
GPIO.out_w1ts = ((uint32_t) 1 << pin);
}
else
{
GPIO.out1_w1ts.val = ((uint32_t) 1 << (pin - 32));
}
}
else
{
if (pin < 32)
{
GPIO.out_w1tc = ((uint32_t) 1 << pin);
}
else
{
GPIO.out1_w1tc.val = ((uint32_t) 1 << (pin - 32));
}
}
}
/****************************************************************************
* Name: esp32_gpioread
*
* Description:
* Read one or zero from the selected GPIO pin
*
****************************************************************************/
bool esp32_gpioread(int pin)
{
if (pin > 39)
{
return false;
}
if (pin < 32)
{
return ((GPIO.in >> pin) & 1) != 0;
}
else
{
return ((GPIO.in1.val >> (pin - 32)) & 1) != 0;
}
}
/****************************************************************************
* Name: esp32_gpioirqinitialize
*
* Description:
* Initialize logic to support a second level of interrupt decoding for
* GPIO pins.
*
****************************************************************************/
#ifdef CONFIG_ESP32_GPIO_IRQ
void esp32_gpioirqinitialize(void)
{
int cpu;
/* Allocate a level-sensitive, priority 1 CPU interrupt */
g_gpio_cpuint = esp32_alloc_levelint(1);
DEBUGASSERT(g_gpio_cpuint >= 0);
/* Attach the GPIO peripheral to the allocated CPU interrupt */
up_disable_irq(g_gpio_cpuint);
cpu = up_cpu_index();
esp32_attach_peripheral(cpu, ESP32_PERIPH_CPU_GPIO, g_gpio_cpuint);
/* Attach and enable the interrupt handler */
DEBUGVERIFY(irq_attach(ESP32_IRQ_CPU_GPIO, gpio_interrupt));
up_enable_irq(g_gpio_cpuint);
}
#endif
/****************************************************************************
* Name: esp32_gpioirqenable
*
* Description:
* Enable the COPY interrupt for specified GPIO IRQ
*
****************************************************************************/
#ifdef CONFIG_ESP32_GPIO_IRQ
void esp32_gpioirqenable(int irq, gpio_intrtype_t intrtype)
{
uintptr_t regaddr;
uint32_t regval;
int cpu;
int pin;
DEBUGASSERT(irq <= ESP32_FIRST_GPIOIRQ && irq <= ESP32_LAST_GPIOIRQ);
/* Convert the IRQ number to a pin number */
pin = ESP32_IRQ2PIN(irq);
/* Get the address of the GPIO PIN register for this pin */
up_disable_irq(g_gpio_cpuint);
regaddr = GPIO_REG(pin);
regval = getreg32(regaddr);
regval &= ~(GPIO_PIN_INT_ENA_M | GPIO_PIN_INT_TYPE_M);
/* Set the pin ENA field:
*
* Bit 0: APP CPU interrupt enable
* Bit 1: APP CPU non-maskable interrupt enable
* Bit 3: PRO CPU interrupt enable
* Bit 4: PRO CPU non-maskable interrupt enable
* Bit 5: SDIO's extent interrupt enable.
*/
cpu = up_cpu_index();
if (cpu == 0)
{
/* PRO_CPU */
regval |= ((1 << 2) << GPIO_PIN_INT_ENA_S);
}
else
{
/* APP_CPU */
regval |= ((1 << 0) << GPIO_PIN_INT_ENA_S);
}
regval |= (intrtype << GPIO_PIN_INT_TYPE_S);
puttreg32(regval, regaddr);
up_enable_irq(g_gpio_cpuint);
}
#endif
/****************************************************************************
* Name: esp32_gpioirqdisable
*
* Description:
* Disable the interrupt for specified GPIO IRQ
*
****************************************************************************/
#ifdef CONFIG_ESP32_GPIO_IRQ
void esp32_gpioirqdisable(int irq)
{
uintptr_t regaddr;
uint32_t regval;
int pin;
DEBUGASSERT(irq <= ESP32_FIRST_GPIOIRQ && irq <= ESP32_LAST_GPIOIRQ);
/* Convert the IRQ number to a pin number */
pin = ESP32_IRQ2PIN(irq);
/* Get the address of the GPIO PIN register for this pin */
up_disable_irq(g_gpio_cpuint);
regaddr = GPIO_REG(pin);
regval = getreg32(regaddr);
regval &= ~(GPIO_PIN_INT_ENA_M | GPIO_PIN_INT_TYPE_M);
puttreg32(regval, regaddr);
up_enable_irq(g_gpio_cpuint);
}
#endif

View File

@ -0,0 +1,185 @@
/****************************************************************************
* arch/xtensa/src/esp32/esp32_gpio.h
*
* Developed for NuttX by:
*
* Copyright (C) 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Derivies in part from sample code provided by Expressif Systems:
*
* Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
****************************************************************************/
#ifndef __ARCH_XTENSA_SRC_ESP32_ESP32_GPIO_H
#define __ARCH_XTENSA_SRC_ESP32_ESP32_GPIO_H
/****************************************************************************
* Included Files
****************************************************************************/
/* Bit-encoded input to esp32_configgpio() **********************************/
/* Encoded pin attributes used with esp32_configgpio() */
#define INPUT 0x01
#define OUTPUT 0x02
#define PULLUP 0x04
#define INPUT_PULLUP 0x05
#define PULLDOWN 0x08
#define INPUT_PULLDOWN 0x09
#define OPEN_DRAIN 0x10
#define OUTPUT_OPEN_DRAIN 0x12
#define SPECIAL 0xf0
#define FUNCTION_0 0x00
#define FUNCTION_1 0x20
#define FUNCTION_2 0x40
#define FUNCTION_3 0x70
#define FUNCTION_4 0x80
/* Interrupt type used with esp32_gpioirqenable() */
#define DISABLED 0x00
#define RISING 0x01
#define FALLING 0x02
#define CHANGE 0x03
#define ONLOW 0x04
#define ONHIGH 0x05
#define ONLOW_WE 0x0c
#define ONHIGH_WE 0x0d
/****************************************************************************
* Public Types
****************************************************************************/
#ifndef __ASSEMBLY__
/* Must be big enough to hold the the above encodings */
typedef uint8_t gpio_pinattr_t;
typedef uint8_t gpio_intrtype_t;
/****************************************************************************
* Public Data
****************************************************************************/
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* Inline Functions
****************************************************************************/
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: esp32_gpioirqinitialize
*
* Description:
* Initialize logic to support a second level of interrupt decoding for
* GPIO pins.
*
****************************************************************************/
#ifdef CONFIG_ESP32_GPIO_IRQ
void esp32_gpioirqinitialize(void);
#else
# define esp32_gpioirqinitialize()
#endif
/****************************************************************************
* Name: esp32_configgpio
*
* Description:
* Configure a GPIO pin based on encoded pin attributes.
*
****************************************************************************/
int esp32_configgpio(int pin, gpio_pinattr_t attr);
/****************************************************************************
* Name: esp32_gpiowrite
*
* Description:
* Write one or zero to the selected GPIO pin
*
****************************************************************************/
void esp32_gpiowrite(int pin, bool value);
/****************************************************************************
* Name: esp32_gpioread
*
* Description:
* Read one or zero from the selected GPIO pin
*
****************************************************************************/
bool esp32_gpioread(int pin);
/****************************************************************************
* Name: esp32_gpioirqenable
*
* Description:
* Enable the interrupt for specified GPIO IRQ
*
****************************************************************************/
#ifdef CONFIG_ESP32_GPIO_IRQ
void esp32_gpioirqenable(int irq, gpio_intrtype_t intrtype);
#else
# define esp32_gpioirqenable(irq,intrtype)
#endif
/****************************************************************************
* Name: esp32_gpioirqdisable
*
* Description:
* Disable the interrupt for specified GPIO IRQ
*
****************************************************************************/
#ifdef CONFIG_ESP32_GPIO_IRQ
void esp32_gpioirqdisable(int irq);
#else
# define esp32_gpioirqdisable(irq)
#endif
#undef EXTERN
#if defined(__cplusplus)
}
#endif
#endif /* __ASSEMBLY__ */
int digitalRead(uint8_t pin);
void attachInterrupt(uint8_t pin, void (*)(void), int mode);
void detachInterrupt(uint8_t pin);
#ifdef __cplusplus
}
#endif
#endif /* __ARCH_XTENSA_SRC_ESP32_ESP32_GPIO_H */

View File

@ -128,9 +128,9 @@ void xtensa_irq_initialize(void)
/* Detach all peripheral sources PRO CPU interrupts */
for (i = 0; i < NR_PERIPHERALS)
for (i = 0; i < ESP32_NPERIPHERALS; i++)
{
esp32_detach_peripheral(0, i);;
esp32_detach_peripheral(0, i);
}
#if defined(CONFIG_STACK_COLORATION) && CONFIG_ARCH_INTERRUPTSTACK > 3