diff --git a/arch/xtensa/include/esp32/irq.h b/arch/xtensa/include/esp32/irq.h index 19fc0ab33b..66d330f35a 100644 --- a/arch/xtensa/include/esp32/irq.h +++ b/arch/xtensa/include/esp32/irq.h @@ -279,12 +279,27 @@ #define ESP32_NIRQ_PERIPH ESP32_NPERIPHERALS +#ifdef CONFIG_ESP32_GPIO_IRQ + +/* The PRO and APP CPU have different interrupts sources for the GPIO + * peripheral. Each CPU needs to allocate a separate interrupt and attach + * it to its peripheral. + * Here we add a separate IRQ to differentiate between each interrupt. + * When enabling/disabling the IRQ we handle the APP's GPIO separately + * to correctly retrieve the peripheral. + */ + +# ifdef CONFIG_SMP +# define ESP32_IRQ_APPCPU_GPIO ESP32_NPERIPHERALS +# undef ESP32_NIRQ_PERIPH +# define ESP32_NIRQ_PERIPH ESP32_NPERIPHERALS + 1 +# endif + /* 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) @@ -409,6 +424,24 @@ * Inline functions ****************************************************************************/ +#ifdef CONFIG_ESP32_GPIO_IRQ +#ifdef CONFIG_SMP +static inline int esp32_irq_gpio(int cpu) +{ + if (cpu == 0) + { + return ESP32_IRQ_CPU_GPIO; + } + else + { + return ESP32_IRQ_APPCPU_GPIO; + } +} +#else +# define esp32_irq_gpio(c) (UNUSED(c), ESP32_IRQ_CPU_GPIO) +#endif +#endif + /**************************************************************************** * Public Data ****************************************************************************/ diff --git a/arch/xtensa/src/esp32/esp32_cpustart.c b/arch/xtensa/src/esp32/esp32_cpustart.c index ccef8e1079..2806e193c7 100644 --- a/arch/xtensa/src/esp32/esp32_cpustart.c +++ b/arch/xtensa/src/esp32/esp32_cpustart.c @@ -44,6 +44,7 @@ #include "esp32_region.h" #include "esp32_irq.h" #include "esp32_smp.h" +#include "esp32_gpio.h" #ifdef CONFIG_SMP @@ -208,6 +209,12 @@ void xtensa_appcpu_start(void) xtensa_registerdump(tcb); +#ifdef CONFIG_ESP32_GPIO_IRQ + /* Initialize GPIO interrupt support */ + + esp32_gpioirqinitialize(1); +#endif + #ifndef CONFIG_SUPPRESS_INTERRUPTS /* And Enable interrupts */ diff --git a/arch/xtensa/src/esp32/esp32_gpio.c b/arch/xtensa/src/esp32/esp32_gpio.c index c3f4f9ef4f..cdc537e3a2 100644 --- a/arch/xtensa/src/esp32/esp32_gpio.c +++ b/arch/xtensa/src/esp32/esp32_gpio.c @@ -56,7 +56,11 @@ ****************************************************************************/ #ifdef CONFIG_ESP32_GPIO_IRQ -static int g_gpio_cpuint; +#ifdef CONFIG_SMP +static int g_gpio_cpuint[CONFIG_SMP_NCPUS]; +#else +static int g_gpio_cpuint[1]; +#endif #endif static const uint8_t g_pin2func[40] = @@ -409,22 +413,24 @@ bool esp32_gpioread(int pin) ****************************************************************************/ #ifdef CONFIG_ESP32_GPIO_IRQ -void esp32_gpioirqinitialize(void) +void esp32_gpioirqinitialize(int cpu) { - int cpu; +#ifdef CONFIG_SMP + DEBUGASSERT(cpu >= 0 && cpu <= CONFIG_SMP_NCPUS); +#else + DEBUGASSERT(cpu == 0); +#endif /* Setup the GPIO interrupt. */ - cpu = up_cpu_index(); - - g_gpio_cpuint = esp32_setup_irq(cpu, ESP32_PERIPH_CPU_GPIO, - 1, ESP32_CPUINT_LEVEL); - DEBUGASSERT(g_gpio_cpuint >= 0); + g_gpio_cpuint[cpu] = esp32_setup_irq(cpu, ESP32_PERIPH_CPU_GPIO, + 1, ESP32_CPUINT_LEVEL); + DEBUGASSERT(g_gpio_cpuint[cpu] >= 0); /* Attach and enable the interrupt handler */ - DEBUGVERIFY(irq_attach(ESP32_IRQ_CPU_GPIO, gpio_interrupt, NULL)); - up_enable_irq(ESP32_IRQ_CPU_GPIO); + DEBUGVERIFY(irq_attach(esp32_irq_gpio(cpu), gpio_interrupt, NULL)); + up_enable_irq(esp32_irq_gpio(cpu)); } #endif @@ -441,10 +447,8 @@ void esp32_gpioirqenable(int irq, gpio_intrtype_t intrtype) { uintptr_t regaddr; uint32_t regval; -#ifdef CONFIG_SMP - int cpu; -#endif int pin; + int cpu = up_cpu_index(); DEBUGASSERT(irq >= ESP32_FIRST_GPIOIRQ && irq <= ESP32_LAST_GPIOIRQ); @@ -454,7 +458,7 @@ void esp32_gpioirqenable(int irq, gpio_intrtype_t intrtype) /* Get the address of the GPIO PIN register for this pin */ - up_disable_irq(ESP32_IRQ_CPU_GPIO); + up_disable_irq(esp32_irq_gpio(cpu)); regaddr = GPIO_REG(pin); regval = getreg32(regaddr); @@ -470,7 +474,6 @@ void esp32_gpioirqenable(int irq, gpio_intrtype_t intrtype) */ #ifdef CONFIG_SMP - cpu = up_cpu_index(); if (cpu != 0) { /* APP_CPU */ @@ -488,7 +491,7 @@ void esp32_gpioirqenable(int irq, gpio_intrtype_t intrtype) regval |= (intrtype << GPIO_PIN_INT_TYPE_S); putreg32(regval, regaddr); - up_enable_irq(ESP32_IRQ_CPU_GPIO); + up_enable_irq(esp32_irq_gpio(cpu)); } #endif @@ -506,6 +509,7 @@ void esp32_gpioirqdisable(int irq) uintptr_t regaddr; uint32_t regval; int pin; + int cpu = up_cpu_index(); DEBUGASSERT(irq >= ESP32_FIRST_GPIOIRQ && irq <= ESP32_LAST_GPIOIRQ); @@ -515,14 +519,14 @@ void esp32_gpioirqdisable(int irq) /* Get the address of the GPIO PIN register for this pin */ - up_disable_irq(ESP32_IRQ_CPU_GPIO); + up_disable_irq(esp32_irq_gpio(cpu)); regaddr = GPIO_REG(pin); regval = getreg32(regaddr); regval &= ~(GPIO_PIN_INT_ENA_M | GPIO_PIN_INT_TYPE_M); putreg32(regval, regaddr); - up_enable_irq(ESP32_IRQ_CPU_GPIO); + up_enable_irq(esp32_irq_gpio(cpu)); } #endif diff --git a/arch/xtensa/src/esp32/esp32_gpio.h b/arch/xtensa/src/esp32/esp32_gpio.h index 06f677fbee..5d7cc8518e 100644 --- a/arch/xtensa/src/esp32/esp32_gpio.h +++ b/arch/xtensa/src/esp32/esp32_gpio.h @@ -144,9 +144,9 @@ extern "C" ****************************************************************************/ #ifdef CONFIG_ESP32_GPIO_IRQ -void esp32_gpioirqinitialize(void); +void esp32_gpioirqinitialize(int c); #else -# define esp32_gpioirqinitialize() +# define esp32_gpioirqinitialize(c) #endif /**************************************************************************** diff --git a/arch/xtensa/src/esp32/esp32_irq.c b/arch/xtensa/src/esp32/esp32_irq.c index 97f32bdd17..bb3f137673 100644 --- a/arch/xtensa/src/esp32/esp32_irq.c +++ b/arch/xtensa/src/esp32/esp32_irq.c @@ -481,7 +481,7 @@ void up_irqinitialize(void) #ifdef CONFIG_ESP32_GPIO_IRQ /* Initialize GPIO interrupt support */ - esp32_gpioirqinitialize(); + esp32_gpioirqinitialize(0); #endif #ifndef CONFIG_SUPPRESS_INTERRUPTS @@ -544,6 +544,17 @@ void up_disable_irq(int irq) uintptr_t regaddr; uint8_t *intmap; +#ifdef CONFIG_ESP32_GPIO_IRQ +#ifdef CONFIG_SMP + /* The APP's CPU GPIO is a special case. See esp32/irq.h */ + + if (periph == ESP32_IRQ_APPCPU_GPIO) + { + periph = ESP32_IRQ_CPU_GPIO; + } +#endif +#endif + DEBUGASSERT(periph >= 0 && periph < ESP32_NPERIPHERALS); esp32_intinfo(cpu, periph, ®addr, &intmap); @@ -588,6 +599,17 @@ void up_enable_irq(int irq) uintptr_t regaddr; uint8_t *intmap; +#ifdef CONFIG_ESP32_GPIO_IRQ +#ifdef CONFIG_SMP + /* The APP's CPU GPIO is a special case. See esp32/irq.h */ + + if (periph == ESP32_IRQ_APPCPU_GPIO) + { + periph = ESP32_IRQ_CPU_GPIO; + } +#endif +#endif + DEBUGASSERT(periph >= 0 && periph < ESP32_NPERIPHERALS); esp32_intinfo(cpu, periph, ®addr, &intmap);