mirror of
https://github.com/apache/nuttx.git
synced 2026-06-04 23:03:27 +08:00
arch/xtensa/esp32: Merge esp32_intdecode with esp32_irq.
Signed-off-by: Abdelatif Guettouche <abdelatif.guettouche@espressif.com>
This commit is contained in:
committed by
Masayuki Ishikawa
parent
79cc12c034
commit
04cd520293
@@ -70,7 +70,7 @@ endif
|
|||||||
# Required ESP32 files (arch/xtensa/src/lx6)
|
# Required ESP32 files (arch/xtensa/src/lx6)
|
||||||
|
|
||||||
CHIP_CSRCS = esp32_allocateheap.c esp32_clockconfig.c esp32_gpio.c
|
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_user.c
|
||||||
CHIP_CSRCS += esp32_dma.c
|
CHIP_CSRCS += esp32_dma.c
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -122,29 +122,29 @@ uintptr_t g_cpu_intstack_top[CONFIG_SMP_NCPUS] =
|
|||||||
};
|
};
|
||||||
#endif /* defined(CONFIG_SMP) && CONFIG_ARCH_INTERRUPTSTACK > 15 */
|
#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 */
|
/* 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
|
#ifdef CONFIG_SMP
|
||||||
uint8_t g_cpu1_intmap[ESP32_NCPUINTS];
|
static uint8_t g_cpu1_intmap[ESP32_NCPUINTS];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static volatile uint8_t g_irqmap[NR_IRQS];
|
||||||
|
|
||||||
/* g_intenable[] is a shadow copy of the per-CPU INTENABLE register
|
/* g_intenable[] is a shadow copy of the per-CPU INTENABLE register
|
||||||
* content.
|
* content.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
uint32_t g_intenable[CONFIG_SMP_NCPUS];
|
static uint32_t g_intenable[CONFIG_SMP_NCPUS];
|
||||||
#else
|
#else
|
||||||
uint32_t g_intenable[1];
|
static uint32_t g_intenable[1];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Private Data
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
/* Bitsets for free, unallocated CPU interrupts available to peripheral
|
/* Bitsets for free, unallocated CPU interrupts available to peripheral
|
||||||
* devices.
|
* 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
|
* Name: esp32_intinfo
|
||||||
*
|
*
|
||||||
@@ -828,3 +841,85 @@ void esp32_teardown_irq(int cpu, int periphid, int cpuint)
|
|||||||
leave_critical_section(irqstate);
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -53,27 +53,6 @@ extern "C"
|
|||||||
#define ESP32_CPUINT_LEVEL 0
|
#define ESP32_CPUINT_LEVEL 0
|
||||||
#define ESP32_CPUINT_EDGE 1
|
#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
|
* Public Functions Prototypes
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|||||||
Reference in New Issue
Block a user