arch/xtensa/esp32: Merge esp32_intdecode with esp32_irq.

Signed-off-by: Abdelatif Guettouche <abdelatif.guettouche@espressif.com>
This commit is contained in:
Abdelatif Guettouche 2021-08-17 22:16:45 +02:00 committed by Masayuki Ishikawa
parent 79cc12c034
commit 04cd520293
4 changed files with 105 additions and 168 deletions

View File

@ -70,7 +70,7 @@ endif
# Required ESP32 files (arch/xtensa/src/lx6)
CHIP_CSRCS = esp32_allocateheap.c esp32_clockconfig.c esp32_gpio.c
CHIP_CSRCS += esp32_intdecode.c esp32_irq.c esp32_region.c
CHIP_CSRCS += esp32_irq.c esp32_region.c
CHIP_CSRCS += esp32_user.c
CHIP_CSRCS += esp32_dma.c

View File

@ -1,137 +0,0 @@
/****************************************************************************
* arch/xtensa/src/esp32/esp32_intdecode.c
*
* 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.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <assert.h>
#include <nuttx/arch.h>
#include <arch/irq.h>
#include "xtensa.h"
#include "esp32_irq.h"
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: xtensa_intclear
****************************************************************************/
static inline void xtensa_intclear(uint32_t mask)
{
__asm__ __volatile__
(
"wsr %0, INTCLEAR\n"
: "=r"(mask) : :
);
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: xtensa_int_decode
*
* Description:
* Determine the peripheral that generated the interrupt and dispatch
* handling to the registered interrupt handler via xtensa_irq_dispatch().
*
* Input Parameters:
* cpuints - Set of pending interrupts valid for this level
* regs - Saves processor state on the stack
*
* Returned Value:
* Normally the same value as regs is returned. But, in the event of an
* interrupt level context switch, the returned value will, instead point
* to the saved processor state in the TCB of the newly started task.
*
****************************************************************************/
uint32_t *xtensa_int_decode(uint32_t cpuints, uint32_t *regs)
{
uint8_t *intmap;
uint32_t mask;
int bit;
#ifdef CONFIG_SMP
int cpu;
#endif
#ifdef CONFIG_SMP
/* Select PRO or APP CPU interrupt mapping table */
cpu = up_cpu_index();
if (cpu != 0)
{
intmap = g_cpu1_intmap;
}
else
#endif
{
intmap = g_cpu0_intmap;
}
/* Skip over zero bits, eight at a time */
for (bit = 0, mask = 0xff;
bit < ESP32_NCPUINTS && (cpuints & mask) == 0;
bit += 8, mask <<= 8);
/* Process each pending CPU interrupt */
for (; bit < ESP32_NCPUINTS && cpuints != 0; bit++)
{
mask = (1 << bit);
if ((cpuints & mask) != 0)
{
/* Extract the IRQ number from the mapping table */
uint8_t irq = intmap[bit];
DEBUGASSERT(irq != CPUINT_UNASSIGNED);
/* Clear software or edge-triggered interrupt */
xtensa_intclear(mask);
/* Dispatch the CPU interrupt.
*
* NOTE that regs may be altered in the case of an interrupt
* level context switch.
*/
regs = xtensa_irq_dispatch((int)irq, regs);
/* Clear the bit in the pending interrupt so that perhaps
* we can exit the look early.
*/
cpuints &= ~mask;
}
}
return regs;
}

View File

@ -122,29 +122,29 @@ 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 Data
****************************************************************************/
/* Maps a CPU interrupt to the IRQ of the attached peripheral interrupt */
uint8_t g_cpu0_intmap[ESP32_NCPUINTS];
static uint8_t g_cpu0_intmap[ESP32_NCPUINTS];
#ifdef CONFIG_SMP
uint8_t g_cpu1_intmap[ESP32_NCPUINTS];
static uint8_t g_cpu1_intmap[ESP32_NCPUINTS];
#endif
static volatile uint8_t g_irqmap[NR_IRQS];
/* g_intenable[] is a shadow copy of the per-CPU INTENABLE register
* content.
*/
#ifdef CONFIG_SMP
uint32_t g_intenable[CONFIG_SMP_NCPUS];
static uint32_t g_intenable[CONFIG_SMP_NCPUS];
#else
uint32_t g_intenable[1];
static uint32_t g_intenable[1];
#endif
/****************************************************************************
* Private Data
****************************************************************************/
/* Bitsets for free, unallocated CPU interrupts available to peripheral
* devices.
*/
@ -230,6 +230,19 @@ static inline void xtensa_disable_all(void)
);
}
/****************************************************************************
* Name: xtensa_intclear
****************************************************************************/
static inline void xtensa_intclear(uint32_t mask)
{
__asm__ __volatile__
(
"wsr %0, INTCLEAR\n"
: "=r"(mask) : :
);
}
/****************************************************************************
* Name: esp32_intinfo
*
@ -828,3 +841,85 @@ void esp32_teardown_irq(int cpu, int periphid, int cpuint)
leave_critical_section(irqstate);
}
/****************************************************************************
* Name: xtensa_int_decode
*
* Description:
* Determine the peripheral that generated the interrupt and dispatch
* handling to the registered interrupt handler via xtensa_irq_dispatch().
*
* Input Parameters:
* cpuints - Set of pending interrupts valid for this level
* regs - Saves processor state on the stack
*
* Returned Value:
* Normally the same value as regs is returned. But, in the event of an
* interrupt level context switch, the returned value will, instead point
* to the saved processor state in the TCB of the newly started task.
*
****************************************************************************/
uint32_t *xtensa_int_decode(uint32_t cpuints, uint32_t *regs)
{
uint8_t *intmap;
uint32_t mask;
int bit;
#ifdef CONFIG_SMP
int cpu;
#endif
#ifdef CONFIG_SMP
/* Select PRO or APP CPU interrupt mapping table */
cpu = up_cpu_index();
if (cpu != 0)
{
intmap = g_cpu1_intmap;
}
else
#endif
{
intmap = g_cpu0_intmap;
}
/* Skip over zero bits, eight at a time */
for (bit = 0, mask = 0xff;
bit < ESP32_NCPUINTS && (cpuints & mask) == 0;
bit += 8, mask <<= 8);
/* Process each pending CPU interrupt */
for (; bit < ESP32_NCPUINTS && cpuints != 0; bit++)
{
mask = (1 << bit);
if ((cpuints & mask) != 0)
{
/* Extract the IRQ number from the mapping table */
uint8_t irq = intmap[bit];
DEBUGASSERT(irq != CPUINT_UNASSIGNED);
/* Clear software or edge-triggered interrupt */
xtensa_intclear(mask);
/* Dispatch the CPU interrupt.
*
* NOTE that regs may be altered in the case of an interrupt
* level context switch.
*/
regs = xtensa_irq_dispatch((int)irq, regs);
/* Clear the bit in the pending interrupt so that perhaps
* we can exit the look early.
*/
cpuints &= ~mask;
}
}
return regs;
}

View File

@ -53,27 +53,6 @@ extern "C"
#define ESP32_CPUINT_LEVEL 0
#define ESP32_CPUINT_EDGE 1
/****************************************************************************
* Public Data
****************************************************************************/
/* Maps a CPU interrupt to the IRQ of the attached peripheral interrupt */
extern uint8_t g_cpu0_intmap[ESP32_NCPUINTS];
#ifdef CONFIG_SMP
extern uint8_t g_cpu1_intmap[ESP32_NCPUINTS];
#endif
/* g_intenable[] is a shadow copy of the per-CPU INTENABLE register
* content.
*/
#ifdef CONFIG_SMP
extern uint32_t g_intenable[CONFIG_SMP_NCPUS];
#else
extern uint32_t g_intenable[1];
#endif
/****************************************************************************
* Public Functions Prototypes
****************************************************************************/