arch/xtensa/esp32: Map NuttX's IRQs to ESP32 CPU interrupts.
This map also keeps track of the CPU that attached the IRQ. This will be used to properly disable the interrupt in the correct CPU in SMP mode. Signed-off-by: Abdelatif Guettouche <abdelatif.guettouche@espressif.com>
This commit is contained in:
parent
c826c37277
commit
633cdf8e27
@ -34,11 +34,13 @@
|
||||
#include <nuttx/irq.h>
|
||||
#include <arch/irq.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
|
@ -33,10 +33,13 @@
|
||||
#include <arch/irq.h>
|
||||
|
||||
#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
|
||||
*
|
||||
|
85
arch/xtensa/src/esp32/esp32_irq.h
Normal file
85
arch/xtensa/src/esp32/esp32_irq.h
Normal file
@ -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 <nuttx/config.h>
|
||||
|
||||
#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 */
|
Loading…
Reference in New Issue
Block a user