arch/esp32: Properly handle GPIO interrupt in SMP.
The PRO CPU and APP CPU have different peripherals for GPIO interrupts. Each CPU needs to allocate an interrupt and attach it to its GPIO peripheral. Signed-off-by: Abdelatif Guettouche <abdelatif.guettouche@espressif.com>
This commit is contained in:
parent
5df1a544cf
commit
1385ea7673
@ -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
|
||||
****************************************************************************/
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user