diff --git a/arch/xtensa/src/esp32/esp32_cpuint.c b/arch/xtensa/src/esp32/esp32_cpuint.c index 515ac471e4..d0764ae483 100644 --- a/arch/xtensa/src/esp32/esp32_cpuint.c +++ b/arch/xtensa/src/esp32/esp32_cpuint.c @@ -34,11 +34,13 @@ #include #include -#include "hardware/esp32_dport.h" -#include "esp32_cpuint.h" #include "xtensa.h" -#include "sched/sched.h" +#include "hardware/esp32_dport.h" + +#include "esp32_irq.h" + +#include "esp32_cpuint.h" /**************************************************************************** * Pre-processor Definitions @@ -156,16 +158,6 @@ uint8_t g_cpu1_intmap[ESP32_NCPUINTS]; * Private Data ****************************************************************************/ -/* g_intenable[] is a shadow copy of the per-CPU INTENABLE register - * content. - */ - -#ifdef CONFIG_SMP -static uint32_t g_intenable[CONFIG_SMP_NCPUS]; -#else -static uint32_t g_intenable[1]; -#endif - /* Bitsets for free, unallocated CPU interrupts available to peripheral * devices. */ @@ -389,40 +381,6 @@ int esp32_cpuint_initialize(void) return OK; } -/**************************************************************************** - * Name: up_disable_irq - * - * Description: - * Disable the CPU interrupt specified by 'cpuint' - * - ****************************************************************************/ - -void up_disable_irq(int cpuint) -{ - int cpu = up_cpu_index(); - - DEBUGASSERT(cpuint >= 0 && cpuint <= ESP32_CPUINT_MAX); - - xtensa_disable_cpuint(&g_intenable[cpu], (1ul << cpuint)); -} - -/**************************************************************************** - * Name: up_enable_irq - * - * Description: - * Enable the CPU interrupt specified by 'cpuint' - * - ****************************************************************************/ - -void up_enable_irq(int cpuint) -{ - int cpu = up_cpu_index(); - - DEBUGASSERT(cpuint >= 0 && cpuint <= ESP32_CPUINT_MAX); - - xtensa_enable_cpuint(&g_intenable[cpu], (1ul << cpuint)); -} - /**************************************************************************** * Name: esp32_alloc_levelint * @@ -552,6 +510,9 @@ void esp32_attach_peripheral(int cpu, int periphid, int cpuint) { uintptr_t regaddr; uint8_t *intmap; + int irq; + + irq = ESP32_PERIPH2IRQ(periphid); DEBUGASSERT(periphid >= 0 && periphid < ESP32_NPERIPHERALS); DEBUGASSERT(cpuint >= 0 && cpuint <= ESP32_CPUINT_MAX); @@ -572,6 +533,7 @@ void esp32_attach_peripheral(int cpu, int periphid, int cpuint) DEBUGASSERT(intmap[cpuint] == CPUINT_UNASSIGNED); intmap[cpuint] = periphid + XTENSA_IRQ_FIRSTPERIPH; + esp32_mapirq(irq, cpu, cpuint); putreg32(cpuint, regaddr); } @@ -598,6 +560,9 @@ void esp32_detach_peripheral(int cpu, int periphid, int cpuint) { uintptr_t regaddr; uint8_t *intmap; + int irq; + + irq = ESP32_PERIPH2IRQ(periphid); DEBUGASSERT(periphid >= 0 && periphid < ESP32_NPERIPHERALS); #ifdef CONFIG_SMP @@ -617,6 +582,7 @@ void esp32_detach_peripheral(int cpu, int periphid, int cpuint) DEBUGASSERT(intmap[cpuint] != CPUINT_UNASSIGNED); intmap[cpuint] = CPUINT_UNASSIGNED; + esp32_unmapirq(irq); putreg32(NO_CPUINT, regaddr); } diff --git a/arch/xtensa/src/esp32/esp32_irq.c b/arch/xtensa/src/esp32/esp32_irq.c index 617f716001..3c6cd2db4a 100644 --- a/arch/xtensa/src/esp32/esp32_irq.c +++ b/arch/xtensa/src/esp32/esp32_irq.c @@ -33,10 +33,13 @@ #include #include "xtensa.h" + #include "esp32_cpuint.h" #include "esp32_smp.h" #include "esp32_gpio.h" +#include "esp32_irq.h" + /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ @@ -47,10 +50,25 @@ # define INTSTACK_ALLOC (CONFIG_SMP_NCPUS * INTSTACK_SIZE) #endif +#define IRQ_UNMAPPED 0xff +#define IRQ_GETCPU(m) (((m) & 0x80) >> 0x07) +#define IRQ_GETCPUINT(m) ((m) & 0x7f) +#define IRQ_MKMAP(c, i) (((c) << 0x07) | (i)) + /**************************************************************************** * Public Data ****************************************************************************/ +/* g_intenable[] is a shadow copy of the per-CPU INTENABLE register + * content. + */ + +#ifdef CONFIG_SMP +static uint32_t g_intenable[CONFIG_SMP_NCPUS]; +#else +static uint32_t g_intenable[1]; +#endif + /* g_current_regs[] holds a reference to the current interrupt level * register storage structure. It is non-NULL only during interrupt * processing. Access to g_current_regs[] must be through the macro @@ -88,6 +106,8 @@ uintptr_t g_cpu_intstack_top[CONFIG_SMP_NCPUS] = }; #endif /* defined(CONFIG_SMP) && CONFIG_ARCH_INTERRUPTSTACK > 15 */ +static volatile uint8_t g_irqmap[NR_IRQS]; + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -152,6 +172,12 @@ static inline void xtensa_attach_fromcpu1_interrupt(void) void up_irqinitialize(void) { + int i; + for (i = 0; i < NR_IRQS; i++) + { + g_irqmap[i] = IRQ_UNMAPPED; + } + /* Initialize CPU interrupts */ esp32_cpuint_initialize(); @@ -179,6 +205,121 @@ void up_irqinitialize(void) #endif } +/**************************************************************************** + * Name: esp32_mapirq + * + * Description: + * Map the given IRQ to the CPU and allocated CPU interrupt. + * + * Input Parameters: + * irq - IRQ number (see esp32/include/irq.h) + * cpu - The CPU receiving the interrupt 0=PRO CPU 1=APP CPU + * cpuint - The allocated CPU interrupt. + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp32_mapirq(int irq, int cpu, int cpuint) +{ + DEBUGASSERT(irq >= 0 && irq < NR_IRQS); + DEBUGASSERT(cpuint >= 0 && cpuint <= ESP32_CPUINT_MAX); +#ifdef CONFIG_SMP + DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS); +#else + DEBUGASSERT(cpu == 0); +#endif + + g_irqmap[irq] = IRQ_MKMAP(cpu, cpuint); +} + +/**************************************************************************** + * Name: esp32_unmapirq + * + * Description: + * Unmap the given IRQ. + * + * Input Parameters: + * irq - IRQ number (see esp32/include/irq.h) + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp32_unmapirq(int irq) +{ + DEBUGASSERT(irq >= 0 && irq < NR_IRQS); + + g_irqmap[irq] = IRQ_UNMAPPED; +} + +/**************************************************************************** + * Name: up_disable_irq + * + * Description: + * Disable the IRQ specified by 'irq' + * + ****************************************************************************/ + +void up_disable_irq(int irq) +{ + int cpu = up_cpu_index(); + int cpuint = IRQ_GETCPUINT(g_irqmap[irq]); + + if (g_irqmap[irq] == IRQ_UNMAPPED) + { + /* This interrupt is already disabled. */ + + return; + } + + DEBUGASSERT(cpuint >= 0 && cpuint <= ESP32_CPUINT_MAX); +#ifdef CONFIG_SMP + DEBUGASSERT(cpu >= 0 && cpu <= CONFIG_SMP_NCPUS); +#else + DEBUGASSERT(cpu == 0); +#endif + + xtensa_disable_cpuint(&g_intenable[cpu], (1ul << cpuint)); +} + +/**************************************************************************** + * Name: up_enable_irq + * + * Description: + * Enable the IRQ specified by 'irq' + * + ****************************************************************************/ + +void up_enable_irq(int irq) +{ + int cpu = IRQ_GETCPU(g_irqmap[irq]); + int cpuint = IRQ_GETCPUINT(g_irqmap[irq]); + + /* The internal Timer 0 interrupt is not attached to any peripheral, and + * thus has no mapping, it has to be handled separately. + * We know it's enabled early before the second CPU has started, so we don't + * need any IPC call. + */ + + if (irq == XTENSA_IRQ_TIMER0) + { + cpu = 0; + cpuint = ESP32_CPUINT_TIMER0; + } + + DEBUGASSERT(cpuint >= 0 && cpuint <= ESP32_CPUINT_MAX); +#ifdef CONFIG_SMP + DEBUGASSERT(cpu >= 0 && cpu <= CONFIG_SMP_NCPUS); +#else + DEBUGASSERT(cpu == 0); +#endif + + xtensa_enable_cpuint(&g_intenable[cpu], (1ul << cpuint)); +} + /**************************************************************************** * Name: xtensa_intstack_top * diff --git a/arch/xtensa/src/esp32/esp32_irq.h b/arch/xtensa/src/esp32/esp32_irq.h new file mode 100644 index 0000000000..65a0429ed3 --- /dev/null +++ b/arch/xtensa/src/esp32/esp32_irq.h @@ -0,0 +1,85 @@ +/**************************************************************************** + * arch/xtensa/src/esp32/esp32_irq.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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_IRQ_H +#define __ARCH_XTENSA_SRC_ESP32_ESP32_IRQ_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Functions Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: esp32_mapirq + * + * Description: + * Map the given IRQ to the CPU and allocated CPU interrupt. + * + * Input Parameters: + * irq - IRQ number (see esp32/include/irq.h) + * cpu - The CPU receiving the interrupt 0=PRO CPU 1=APP CPU + * cpuint - The allocated CPU interrupt. + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp32_mapirq(int irq, int cpu, int cpuint); + +/**************************************************************************** + * Name: esp32_unmapirq + * + * Description: + * Unmap the given IRQ. + * + * Input Parameters: + * irq - IRQ number (see esp32/include/irq.h) + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp32_unmapirq(int irq); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_XTENSA_SRC_ESP32_ESP32_IRQ_H */