xtensa: support more than 32 cpu interrupts
The architecture defines maximum of 128 interrupts, whereas previous code only supported 32 interrupts. For every 32 interrupts added, there are three additional registers: INTERRUPT, INTCLEAR, and INTENABLE. This patch adds support for handling these registers. Signed-off-by: chenxiaoyi <chenxiaoyi@xiaomi.com>
This commit is contained in:
parent
b2158c8e3c
commit
886718ade1
10 changed files with 436 additions and 190 deletions
|
|
@ -331,7 +331,16 @@ static inline_function void xtensa_disable_all(void)
|
|||
__asm__ __volatile__
|
||||
(
|
||||
"movi a2, 0\n"
|
||||
"xsr a2, INTENABLE\n"
|
||||
"wsr a2, INTENABLE\n"
|
||||
#if XCHAL_NUM_INTERRUPTS > 32
|
||||
"wsr a2, INTENABLE1\n"
|
||||
#endif
|
||||
#if XCHAL_NUM_INTERRUPTS > 64
|
||||
"wsr a2, INTENABLE2\n"
|
||||
#endif
|
||||
#if XCHAL_NUM_INTERRUPTS > 96
|
||||
"wsr a2, INTENABLE3\n"
|
||||
#endif
|
||||
"rsync\n"
|
||||
: : : "a2"
|
||||
);
|
||||
|
|
@ -341,16 +350,60 @@ static inline_function void xtensa_disable_all(void)
|
|||
* Name: xtensa_intclear
|
||||
****************************************************************************/
|
||||
|
||||
static inline_function void xtensa_intclear(uint32_t mask)
|
||||
static inline_function void xtensa_intclear(uint32_t intnum)
|
||||
{
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"wsr %0, INTCLEAR\n"
|
||||
"rsync\n"
|
||||
:
|
||||
: "r"(mask)
|
||||
:
|
||||
);
|
||||
DEBUGASSERT(intnum < XCHAL_NUM_INTERRUPTS);
|
||||
|
||||
if (intnum < 32)
|
||||
{
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"wsr %0, INTCLEAR\n"
|
||||
"rsync\n"
|
||||
:
|
||||
: "r"(1 << intnum)
|
||||
:
|
||||
);
|
||||
}
|
||||
#if XCHAL_NUM_INTERRUPTS > 32
|
||||
else if (intnum < 64)
|
||||
{
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"wsr %0, INTCLEAR1\n"
|
||||
"rsync\n"
|
||||
:
|
||||
: "r"(1 << (intnum - 32))
|
||||
:
|
||||
);
|
||||
}
|
||||
#endif
|
||||
#if XCHAL_NUM_INTERRUPTS > 64
|
||||
else if (intnum < 96)
|
||||
{
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"wsr %0, INTCLEAR2\n"
|
||||
"rsync\n"
|
||||
:
|
||||
: "r"(1 << (intnum - 64))
|
||||
:
|
||||
);
|
||||
}
|
||||
#endif
|
||||
#if XCHAL_NUM_INTERRUPTS > 96
|
||||
else if (intnum < 128)
|
||||
{
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"wsr %0, INTCLEAR3\n"
|
||||
"rsync\n"
|
||||
:
|
||||
: "r"(1 << (intnum - 96))
|
||||
:
|
||||
);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ list(
|
|||
APPEND
|
||||
SRCS
|
||||
xtensa_context.S
|
||||
xtensa_cpuint.S
|
||||
xtensa_cpuint.c
|
||||
xtensa_panic.S
|
||||
xtensa_assert.c
|
||||
xtensa_cache.c
|
||||
|
|
|
|||
|
|
@ -29,10 +29,10 @@ HEAD_ASRC += xtensa_int_handlers.S xtensa_user_handler.S
|
|||
|
||||
# Common Xtensa files (arch/xtensa/src/common)
|
||||
|
||||
CMN_ASRCS = xtensa_context.S xtensa_cpuint.S xtensa_panic.S
|
||||
CMN_ASRCS = xtensa_context.S xtensa_panic.S
|
||||
|
||||
CMN_CSRCS = xtensa_assert.c xtensa_cache.c xtensa_cpenable.c
|
||||
CMN_CSRCS += xtensa_cpuinfo.c xtensa_createstack.c xtensa_exit.c
|
||||
CMN_CSRCS += xtensa_cpuinfo.c xtensa_cpuint.c xtensa_createstack.c xtensa_exit.c
|
||||
CMN_CSRCS += xtensa_getintstack.c xtensa_initialize.c xtensa_initialstate.c
|
||||
CMN_CSRCS += xtensa_irqdispatch.c xtensa_lowputs.c xtensa_mdelay.c
|
||||
CMN_CSRCS += xtensa_modifyreg8.c xtensa_modifyreg16.c xtensa_modifyreg32.c
|
||||
|
|
|
|||
|
|
@ -236,10 +236,10 @@ void xtensa_window_spill(void);
|
|||
|
||||
/* IRQs */
|
||||
|
||||
uint32_t *xtensa_int_decode(uint32_t cpuints, uint32_t *regs);
|
||||
uint32_t *xtensa_int_decode(uint32_t *cpuints, uint32_t *regs);
|
||||
uint32_t *xtensa_irq_dispatch(int irq, uint32_t *regs);
|
||||
uint32_t xtensa_enable_cpuint(uint32_t *shadow, uint32_t intmask);
|
||||
uint32_t xtensa_disable_cpuint(uint32_t *shadow, uint32_t intmask);
|
||||
void xtensa_enable_cpuint(uint32_t *shadow, uint32_t intnum);
|
||||
void xtensa_disable_cpuint(uint32_t *shadow, uint32_t intnum);
|
||||
void xtensa_panic(int xptcode, uint32_t *regs) noreturn_function;
|
||||
void xtensa_user_panic(int exccause, uint32_t *regs) noreturn_function;
|
||||
uint32_t *xtensa_user(int exccause, uint32_t *regs);
|
||||
|
|
|
|||
|
|
@ -1,128 +0,0 @@
|
|||
/****************************************************************************
|
||||
* arch/xtensa/src/common/xtensa_cpuint.S
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
* SPDX-FileCopyrightText: 2016 Gregory Nutt. All rights reserved.
|
||||
* SPDX-FileCopyrightText: 2006-2015 Cadence Design Systems Inc.
|
||||
* SPDX-FileContributor: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
.file "xtensa_cpuint.S"
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <arch/chip/core-isa.h>
|
||||
|
||||
#include <arch/xtensa/xtensa_abi.h>
|
||||
|
||||
#if XCHAL_HAVE_INTERRUPTS
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: xtensa_enable_cpuint
|
||||
*
|
||||
* C Prototype:
|
||||
* uint32_t xtensa_enable_cpuint(uint32_t *shadow, unsigned int intmask)
|
||||
*
|
||||
* Description:
|
||||
* Enables a set of interrupts. Does not simply set INTENABLE directly,
|
||||
* but operates on a shadow copy of the CPU INTENABLE register then
|
||||
* writes that value to the hardware INTENABLE register. Can be called
|
||||
* from interrupt handlers.
|
||||
*
|
||||
* NOTE: It is possible only to enable interrupts on the current CPU
|
||||
* because there is an INTENABLE register implemented in each CPU.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
.text
|
||||
.global xtensa_enable_cpuint
|
||||
.type xtensa_enable_cpuint, @function
|
||||
.align 4
|
||||
|
||||
xtensa_enable_cpuint:
|
||||
ENTRY(16)
|
||||
|
||||
movi a4, 0
|
||||
xsr a4, INTENABLE /* Disables all interrupts */
|
||||
rsync
|
||||
|
||||
l32i a4, a2, 0 /* a4 = value of INTENABLE shadow */
|
||||
or a5, a4, a3 /* a5 = shadow | mask */
|
||||
s32i a5, a2, 0 /* shadow |= mask */
|
||||
|
||||
wsr a5, INTENABLE /* Set CPU INTENABLE to shadow */
|
||||
rsync
|
||||
mov a3, a4 /* Return previous shadow content */
|
||||
RET(16)
|
||||
|
||||
.size xtensa_enable_cpuint, . - xtensa_enable_cpuint
|
||||
|
||||
/****************************************************************************
|
||||
* Name: xtensa_disable_cpuint
|
||||
*
|
||||
* C Prototype:
|
||||
* uint32_t xtensa_disable_cpuint(uint32_t *shadow, unsigned int intmask)
|
||||
*
|
||||
* Description:
|
||||
* Disables a set of interrupts. Does not simply set INTENABLE directly,
|
||||
* but operates on a shadow copy of the CPU INTENABLE register then
|
||||
* writes that value to the hardware INTENABLE register. Can be called
|
||||
* from interrupt handlers.
|
||||
*
|
||||
* NOTE: It is possible only to disable interrupts on the current CPU
|
||||
* because there is an INTENABLE register implemented in each CPU.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
.text
|
||||
.global xtensa_disable_cpuint
|
||||
.type xtensa_disable_cpuint, @function
|
||||
.align 4
|
||||
|
||||
xtensa_disable_cpuint:
|
||||
ENTRY(16)
|
||||
|
||||
movi a4, 0
|
||||
xsr a4, INTENABLE /* Disables all interrupts */
|
||||
rsync
|
||||
|
||||
l32i a4, a2, 0 /* a4 = value of INTENABLE shadow */
|
||||
or a5, a4, a3 /* a5 = shadow | mask */
|
||||
xor a5, a5, a3 /* a5 = shadow & ~mask */
|
||||
s32i a5, a2, 0 /* shadow &= ~mask */
|
||||
|
||||
wsr a5, INTENABLE /* Set CPU INTENABLE to shadow */
|
||||
rsync
|
||||
mov a3, a4 /* Return previous shadow content */
|
||||
RET(16)
|
||||
|
||||
.size xtensa_disable_cpuint, . - xtensa_disable_cpuint
|
||||
|
||||
#endif /* XCHAL_HAVE_INTERRUPTS */
|
||||
183
arch/xtensa/src/common/xtensa_cpuint.c
Normal file
183
arch/xtensa/src/common/xtensa_cpuint.c
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
/****************************************************************************
|
||||
* arch/xtensa/src/common/xtensa_cpuint.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 <assert.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <arch/chip/core-isa.h>
|
||||
#include <arch/xtensa/xtensa_specregs.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: xtensa_enable_cpuint
|
||||
*
|
||||
* Description:
|
||||
* Enables an interrupts. Does not simply set INTENABLE directly,
|
||||
* but operates on a shadow copy of the CPU INTENABLE register then
|
||||
* writes that value to the hardware INTENABLE register. Can be called
|
||||
* from interrupt handlers.
|
||||
*
|
||||
* NOTE: It is possible only to enable interrupts on the current CPU
|
||||
* because there is an INTENABLE register implemented in each CPU.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void xtensa_enable_cpuint(uint32_t *shadow, uint32_t intnum)
|
||||
{
|
||||
DEBUGASSERT(intnum < XCHAL_NUM_INTERRUPTS);
|
||||
|
||||
if (intnum < 32)
|
||||
{
|
||||
shadow[0] |= (1 << intnum);
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"wsr %0, INTENABLE\n"
|
||||
"rsync\n"
|
||||
:
|
||||
: "r"(shadow[0])
|
||||
:
|
||||
);
|
||||
}
|
||||
#if XCHAL_NUM_INTERRUPTS > 32
|
||||
else if (intnum < 64)
|
||||
{
|
||||
shadow[1] |= (1 << (intnum - 32));
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"wsr %0, INTENABLE1\n"
|
||||
"rsync\n"
|
||||
:
|
||||
: "r"(shadow[1])
|
||||
:
|
||||
);
|
||||
}
|
||||
#endif
|
||||
#if XCHAL_NUM_INTERRUPTS > 64
|
||||
else if (intnum < 96)
|
||||
{
|
||||
shadow[2] |= (1 << (intnum - 64));
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"wsr %0, INTENABLE2\n"
|
||||
"rsync\n"
|
||||
:
|
||||
: "r"(shadow[2])
|
||||
:
|
||||
);
|
||||
}
|
||||
#endif
|
||||
#if XCHAL_NUM_INTERRUPTS > 96
|
||||
else if (intnum < 128)
|
||||
{
|
||||
shadow[3] |= (1 << (intnum - 96));
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"wsr %0, INTENABLE3\n"
|
||||
"rsync\n"
|
||||
:
|
||||
: "r"(shadow[3])
|
||||
:
|
||||
);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: xtensa_disable_cpuint
|
||||
*
|
||||
* Description:
|
||||
* Disables an interrupts. Does not simply clear INTENABLE directly,
|
||||
* but operates on a shadow copy of the CPU INTENABLE register then
|
||||
* writes that value to the hardware INTENABLE register. Can be called
|
||||
* from interrupt handlers.
|
||||
*
|
||||
* NOTE: It is possible only to disable interrupts on the current CPU
|
||||
* because there is an INTENABLE register implemented in each CPU.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void xtensa_disable_cpuint(uint32_t *shadow, uint32_t intnum)
|
||||
{
|
||||
DEBUGASSERT(intnum < XCHAL_NUM_INTERRUPTS);
|
||||
|
||||
if (intnum < 32)
|
||||
{
|
||||
shadow[0] &= ~(1 << intnum);
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"wsr %0, INTENABLE\n"
|
||||
"rsync\n"
|
||||
:
|
||||
: "r"(shadow[0])
|
||||
:
|
||||
);
|
||||
}
|
||||
#if XCHAL_NUM_INTERRUPTS > 32
|
||||
else if (intnum < 64)
|
||||
{
|
||||
shadow[1] &= ~(1 << (intnum - 32));
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"wsr %0, INTENABLE1\n"
|
||||
"rsync\n"
|
||||
:
|
||||
: "r"(shadow[1])
|
||||
:
|
||||
);
|
||||
}
|
||||
#endif
|
||||
#if XCHAL_NUM_INTERRUPTS > 64
|
||||
else if (intnum < 96)
|
||||
{
|
||||
shadow[2] &= ~(1 << (intnum - 64));
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"wsr %0, INTENABLE2\n"
|
||||
"rsync\n"
|
||||
:
|
||||
: "r"(shadow[2])
|
||||
:
|
||||
);
|
||||
}
|
||||
#endif
|
||||
#if XCHAL_NUM_INTERRUPTS > 96
|
||||
else if (intnum < 128)
|
||||
{
|
||||
shadow[3] &= ~(1 << (intnum - 96));
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"wsr %0, INTENABLE3\n"
|
||||
"rsync\n"
|
||||
:
|
||||
: "r"(shadow[3])
|
||||
:
|
||||
);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
@ -87,6 +87,68 @@ g_intstacktop:
|
|||
* Assembly Language Macros
|
||||
****************************************************************************/
|
||||
|
||||
.macro get_int_mask tmp level mask
|
||||
|
||||
.ifeq \mask
|
||||
.ifeq \level - 1
|
||||
movi \tmp, XCHAL_INTLEVEL1_MASK
|
||||
.elseif (\level - 2) == 0
|
||||
movi \tmp, XCHAL_INTLEVEL2_MASK
|
||||
.elseif (\level - 3) == 0
|
||||
movi \tmp, XCHAL_INTLEVEL3_MASK
|
||||
.elseif (\level - 4) == 0
|
||||
movi \tmp, XCHAL_INTLEVEL4_MASK
|
||||
.elseif (\level - 5) == 0
|
||||
movi \tmp, XCHAL_INTLEVEL5_MASK
|
||||
.elseif (\level - 6) == 0
|
||||
movi \tmp, XCHAL_INTLEVEL6_MASK
|
||||
.endif
|
||||
.elseif (\mask - 1) == 0
|
||||
.ifeq \level - 1
|
||||
movi \tmp, XCHAL_INTLEVEL1_MASK1
|
||||
.elseif (\level - 2) == 0
|
||||
movi \tmp, XCHAL_INTLEVEL2_MASK1
|
||||
.elseif (\level - 3) == 0
|
||||
movi \tmp, XCHAL_INTLEVEL3_MASK1
|
||||
.elseif (\level - 4) == 0
|
||||
movi \tmp, XCHAL_INTLEVEL4_MASK1
|
||||
.elseif (\level - 5) == 0
|
||||
movi \tmp, XCHAL_INTLEVEL5_MASK1
|
||||
.elseif (\level - 6) == 0
|
||||
movi \tmp, XCHAL_INTLEVEL6_MASK1
|
||||
.endif
|
||||
.elseif (\mask - 2) == 0
|
||||
.ifeq \level - 1
|
||||
movi \tmp, XCHAL_INTLEVEL1_MASK2
|
||||
.elseif (\level - 2) == 0
|
||||
movi \tmp, XCHAL_INTLEVEL2_MASK2
|
||||
.elseif (\level - 3) == 0
|
||||
movi \tmp, XCHAL_INTLEVEL3_MASK2
|
||||
.elseif (\level - 4) == 0
|
||||
movi \tmp, XCHAL_INTLEVEL4_MASK2
|
||||
.elseif (\level - 5) == 0
|
||||
movi \tmp, XCHAL_INTLEVEL5_MASK2
|
||||
.elseif (\level - 6) == 0
|
||||
movi \tmp, XCHAL_INTLEVEL6_MASK2
|
||||
.endif
|
||||
.elseif (\mask - 3) == 0
|
||||
.ifeq \level - 1
|
||||
movi \tmp, XCHAL_INTLEVEL1_MASK3
|
||||
.elseif (\level - 2) == 0
|
||||
movi \tmp, XCHAL_INTLEVEL2_MASK3
|
||||
.elseif (\level - 3) == 0
|
||||
movi \tmp, XCHAL_INTLEVEL3_MASK3
|
||||
.elseif (\level - 4) == 0
|
||||
movi \tmp, XCHAL_INTLEVEL4_MASK3
|
||||
.elseif (\level - 5) == 0
|
||||
movi \tmp, XCHAL_INTLEVEL5_MASK3
|
||||
.elseif (\level - 6) == 0
|
||||
movi \tmp, XCHAL_INTLEVEL6_MASK3
|
||||
.endif
|
||||
.endif
|
||||
|
||||
.endm
|
||||
|
||||
/****************************************************************************
|
||||
* Macro dispatch_c_isr level mask tmp
|
||||
*
|
||||
|
|
@ -102,7 +164,6 @@ g_intstacktop:
|
|||
*
|
||||
* Entry Conditions/Side Effects:
|
||||
* level - interrupt level
|
||||
* mask - interrupt bitmask for this level
|
||||
* a12 - register save area
|
||||
*
|
||||
* Exit Conditions:
|
||||
|
|
@ -111,7 +172,7 @@ g_intstacktop:
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
.macro dispatch_c_isr level mask tmp
|
||||
.macro dispatch_c_isr level tmp
|
||||
|
||||
/* If the interrupt stack is disabled, reserve xcpcontext to ensure
|
||||
* that signal processing can have a separate xcpcontext to handle
|
||||
|
|
@ -122,6 +183,15 @@ g_intstacktop:
|
|||
addi sp, sp, -XCPTCONTEXT_SIZE
|
||||
#endif
|
||||
|
||||
/* Reserve the area to save INTERRUPT[1|2|3] registers:
|
||||
* [sp + 0] = INTERRUPT
|
||||
* [sp + 4] = INTERRUPT1
|
||||
* [sp + 8] = INTERRUPT2
|
||||
* [sp + 12] = INTERRUPT3
|
||||
*/
|
||||
|
||||
addi sp, sp, -(XCHAL_NUM_INTERRUPTS / 8)
|
||||
|
||||
/* Set up PS for C, enable interrupts above this level and clear EXCM. */
|
||||
|
||||
ps_setup \level \tmp
|
||||
|
|
@ -130,10 +200,37 @@ g_intstacktop:
|
|||
|
||||
rsr ARG1, INTENABLE
|
||||
rsr a3, INTERRUPT
|
||||
movi a4, \mask
|
||||
get_int_mask a4, \level, 0
|
||||
and ARG1, ARG1, a3
|
||||
and ARG1, ARG1, a4 /* Set of pending, enabled interrupts for this level */
|
||||
s32i ARG1, sp, 0
|
||||
|
||||
#if XCHAL_NUM_INTERRUPTS <= 32
|
||||
beqz ARG1, 1f /* Nothing to do */
|
||||
#else
|
||||
rsr ARG1, INTENABLE1
|
||||
rsr a3, INTERRUPT1
|
||||
get_int_mask a4, \level, 1
|
||||
and ARG1, ARG1, a3
|
||||
and ARG1, ARG1, a4 /* Set of pending, enabled interrupts for this level */
|
||||
s32i ARG1, sp, 4
|
||||
# if XCHAL_NUM_INTERRUPTS > 64
|
||||
rsr ARG1, INTENABLE2
|
||||
rsr a3, INTERRUPT2
|
||||
get_int_mask a4, \level, 2
|
||||
and ARG1, ARG1, a3
|
||||
and ARG1, ARG1, a4 /* Set of pending, enabled interrupts for this level */
|
||||
s32i ARG1, sp, 8
|
||||
# if XCHAL_NUM_INTERRUPTS > 96
|
||||
rsr ARG1, INTENABLE3
|
||||
rsr a3, INTERRUPT3
|
||||
get_int_mask a4, \level, 3
|
||||
and ARG1, ARG1, a3
|
||||
and ARG1, ARG1, a4 /* Set of pending, enabled interrupts for this level */
|
||||
s32i ARG1, sp, 12
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Link the pre-exception frame for debugging. At this point, a12 points to the
|
||||
* allocated and filled exception stack frame (old value of SP in case of
|
||||
|
|
@ -142,6 +239,7 @@ g_intstacktop:
|
|||
|
||||
exception_backtrace a12 \level
|
||||
|
||||
mov ARG1, sp
|
||||
/* Argument 1: Set of CPU interrupt to dispatch */
|
||||
mov ARG2, a12 /* Argument 2: Top of stack = register save area */
|
||||
CALL xtensa_int_decode
|
||||
|
|
@ -164,6 +262,10 @@ g_intstacktop:
|
|||
|
||||
mov a2, a12
|
||||
2:
|
||||
/* Release the area saving INTERRUPT[1|2|3] registers. */
|
||||
|
||||
addi sp, sp, XCHAL_NUM_INTERRUPTS / 8
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK < 15
|
||||
addi sp, sp, XCPTCONTEXT_SIZE
|
||||
#endif
|
||||
|
|
@ -219,7 +321,7 @@ _xtensa_level1_handler:
|
|||
* area in a2.
|
||||
*/
|
||||
|
||||
dispatch_c_isr 1 XCHAL_INTLEVEL1_MASK a0
|
||||
dispatch_c_isr 1 a0
|
||||
|
||||
/* Set PS.EXCM to 1 */
|
||||
|
||||
|
|
@ -304,7 +406,7 @@ _xtensa_level2_handler:
|
|||
* area in a2.
|
||||
*/
|
||||
|
||||
dispatch_c_isr 2 XCHAL_INTLEVEL2_MASK a0
|
||||
dispatch_c_isr 2 a0
|
||||
|
||||
/* Restore registers in preparation to return from interrupt */
|
||||
|
||||
|
|
@ -357,7 +459,7 @@ _xtensa_level3_handler:
|
|||
* area in a2.
|
||||
*/
|
||||
|
||||
dispatch_c_isr 3 XCHAL_INTLEVEL3_MASK a0
|
||||
dispatch_c_isr 3 a0
|
||||
|
||||
/* Restore registers in preparation to return from interrupt */
|
||||
|
||||
|
|
@ -410,7 +512,7 @@ _xtensa_level4_handler:
|
|||
* area in a2.
|
||||
*/
|
||||
|
||||
dispatch_c_isr 4 XCHAL_INTLEVEL4_MASK a0
|
||||
dispatch_c_isr 4 a0
|
||||
|
||||
/* Restore registers in preparation to return from interrupt */
|
||||
|
||||
|
|
@ -463,7 +565,7 @@ _xtensa_level5_handler:
|
|||
* area in a2.
|
||||
*/
|
||||
|
||||
dispatch_c_isr 5 XCHAL_INTLEVEL5_MASK a0
|
||||
dispatch_c_isr 5 a0
|
||||
|
||||
/* Restore registers in preparation to return from interrupt */
|
||||
|
||||
|
|
@ -516,7 +618,7 @@ _xtensa_level6_handler:
|
|||
* area in a2.
|
||||
*/
|
||||
|
||||
dispatch_c_isr 6 XCHAL_INTLEVEL6_MASK a0
|
||||
dispatch_c_isr 6 a0
|
||||
|
||||
/* Restore registers in preparation to return from interrupt */
|
||||
|
||||
|
|
|
|||
|
|
@ -362,7 +362,7 @@ static int esp32_getcpuint(int cpu, uint32_t intmask)
|
|||
|
||||
if (ret >= 0)
|
||||
{
|
||||
xtensa_enable_cpuint(&g_intenable[cpu], 1ul << ret);
|
||||
xtensa_enable_cpuint(&g_intenable[cpu], ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
@ -538,16 +538,16 @@ void up_irqinitialize(void)
|
|||
|
||||
#ifdef CONFIG_ESPRESSIF_WIFI
|
||||
g_cpu0_intmap[ESP32_CPUINT_MAC] = CPUINT_ASSIGN(ESP32_IRQ_MAC);
|
||||
xtensa_enable_cpuint(&g_intenable[0], 1 << ESP32_CPUINT_MAC);
|
||||
xtensa_enable_cpuint(&g_intenable[0], ESP32_CPUINT_MAC);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ESPRESSIF_BLE
|
||||
g_cpu0_intmap[ESP32_PERIPH_BT_BB_NMI] = CPUINT_ASSIGN(ESP32_IRQ_BT_BB_NMI);
|
||||
g_cpu0_intmap[ESP32_PERIPH_RWBT_NMI] = CPUINT_ASSIGN(ESP32_IRQ_RWBT_NMI);
|
||||
g_cpu0_intmap[ESP32_PERIPH_RWBLE_IRQ] = CPUINT_ASSIGN(ESP32_IRQ_RWBLE_IRQ);
|
||||
xtensa_enable_cpuint(&g_intenable[0], 1 << ESP32_PERIPH_BT_BB_NMI);
|
||||
xtensa_enable_cpuint(&g_intenable[0], 1 << ESP32_PERIPH_RWBT_NMI);
|
||||
xtensa_enable_cpuint(&g_intenable[0], 1 << ESP32_PERIPH_RWBLE_IRQ);
|
||||
xtensa_enable_cpuint(&g_intenable[0], ESP32_PERIPH_BT_BB_NMI);
|
||||
xtensa_enable_cpuint(&g_intenable[0], ESP32_PERIPH_RWBT_NMI);
|
||||
xtensa_enable_cpuint(&g_intenable[0], ESP32_PERIPH_RWBLE_IRQ);
|
||||
#endif
|
||||
|
||||
/* Attach and enable internal interrupts */
|
||||
|
|
@ -620,7 +620,7 @@ void up_disable_irq(int irq)
|
|||
}
|
||||
#endif
|
||||
|
||||
xtensa_disable_cpuint(&g_intenable[cpu], 1ul << cpuint);
|
||||
xtensa_disable_cpuint(&g_intenable[cpu], cpuint);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -676,7 +676,7 @@ void up_enable_irq(int irq)
|
|||
|
||||
/* Enable the CPU interrupt now for internal CPU. */
|
||||
|
||||
xtensa_enable_cpuint(&g_intenable[cpu], (1ul << cpuint));
|
||||
xtensa_enable_cpuint(&g_intenable[cpu], cpuint);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1055,7 +1055,7 @@ int esp32_getcpuint_from_irq(int irq, int *cpu)
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
uint32_t *xtensa_int_decode(uint32_t cpuints, uint32_t *regs)
|
||||
uint32_t *xtensa_int_decode(uint32_t *cpuints, uint32_t *regs)
|
||||
{
|
||||
uint8_t *intmap;
|
||||
uint32_t mask;
|
||||
|
|
@ -1084,15 +1084,15 @@ uint32_t *xtensa_int_decode(uint32_t cpuints, uint32_t *regs)
|
|||
/* Skip over zero bits, eight at a time */
|
||||
|
||||
for (bit = 0, mask = 0xff;
|
||||
bit < ESP32_NCPUINTS && (cpuints & mask) == 0;
|
||||
bit < ESP32_NCPUINTS && (cpuints[0] & mask) == 0;
|
||||
bit += 8, mask <<= 8);
|
||||
|
||||
/* Process each pending CPU interrupt */
|
||||
|
||||
for (; bit < ESP32_NCPUINTS && cpuints != 0; bit++)
|
||||
for (; bit < ESP32_NCPUINTS && cpuints[0] != 0; bit++)
|
||||
{
|
||||
mask = 1 << bit;
|
||||
if ((cpuints & mask) != 0)
|
||||
if ((cpuints[0] & mask) != 0)
|
||||
{
|
||||
/* Extract the IRQ number from the mapping table */
|
||||
|
||||
|
|
@ -1114,7 +1114,7 @@ uint32_t *xtensa_int_decode(uint32_t cpuints, uint32_t *regs)
|
|||
|
||||
/* Clear software or edge-triggered interrupt */
|
||||
|
||||
xtensa_intclear(mask);
|
||||
xtensa_intclear(bit);
|
||||
|
||||
/* Dispatch the CPU interrupt.
|
||||
*
|
||||
|
|
@ -1128,7 +1128,7 @@ uint32_t *xtensa_int_decode(uint32_t cpuints, uint32_t *regs)
|
|||
* we can exit the look early.
|
||||
*/
|
||||
|
||||
cpuints &= ~mask;
|
||||
cpuints[0] &= ~mask;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1154,6 +1154,8 @@ uint32_t *xtensa_int_decode(uint32_t cpuints, uint32_t *regs)
|
|||
void esp32_irq_noniram_disable(void)
|
||||
{
|
||||
irqstate_t irqstate;
|
||||
uint32_t mask;
|
||||
int bit;
|
||||
int cpu;
|
||||
uint32_t oldint;
|
||||
uint32_t non_iram_ints;
|
||||
|
|
@ -1167,7 +1169,14 @@ void esp32_irq_noniram_disable(void)
|
|||
g_non_iram_int_disabled_flag[cpu] = true;
|
||||
oldint = g_intenable[cpu];
|
||||
|
||||
xtensa_disable_cpuint(&g_intenable[cpu], non_iram_ints);
|
||||
for (bit = 0; bit < ESP32_NCPUINTS; bit++)
|
||||
{
|
||||
mask = 1 << bit;
|
||||
if ((non_iram_ints & mask) != 0)
|
||||
{
|
||||
xtensa_disable_cpuint(&g_intenable[cpu], bit);
|
||||
}
|
||||
}
|
||||
|
||||
g_non_iram_int_disabled[cpu] = oldint & non_iram_ints;
|
||||
|
||||
|
|
@ -1191,6 +1200,8 @@ void esp32_irq_noniram_disable(void)
|
|||
void esp32_irq_noniram_enable(void)
|
||||
{
|
||||
irqstate_t irqstate;
|
||||
uint32_t mask;
|
||||
int bit;
|
||||
int cpu;
|
||||
uint32_t non_iram_ints;
|
||||
|
||||
|
|
@ -1202,7 +1213,14 @@ void esp32_irq_noniram_enable(void)
|
|||
|
||||
g_non_iram_int_disabled_flag[cpu] = false;
|
||||
|
||||
xtensa_enable_cpuint(&g_intenable[cpu], non_iram_ints);
|
||||
for (bit = 0; bit < ESP32_NCPUINTS; bit++)
|
||||
{
|
||||
mask = 1 << bit;
|
||||
if ((non_iram_ints & mask) != 0)
|
||||
{
|
||||
xtensa_enable_cpuint(&g_intenable[cpu], bit);
|
||||
}
|
||||
}
|
||||
|
||||
leave_critical_section(irqstate);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@ static int esp32s2_getcpuint(uint32_t intmask)
|
|||
|
||||
if (ret >= 0)
|
||||
{
|
||||
xtensa_enable_cpuint(&g_intenable, 1ul << ret);
|
||||
xtensa_enable_cpuint(&g_intenable, ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
@ -309,7 +309,7 @@ void up_irqinitialize(void)
|
|||
#ifdef CONFIG_ESPRESSIF_WIFI
|
||||
g_cpu_intmap[ESP32S2_CPUINT_MAC] = CPUINT_ASSIGN(ESP32S2_IRQ_MAC);
|
||||
g_cpu_intmap[ESP32S2_CPUINT_PWR] = CPUINT_ASSIGN(ESP32S2_IRQ_PWR);
|
||||
xtensa_enable_cpuint(&g_intenable, 1 << ESP32S2_CPUINT_MAC);
|
||||
xtensa_enable_cpuint(&g_intenable, ESP32S2_CPUINT_MAC);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ESP32S2_GPIO_IRQ
|
||||
|
|
@ -360,7 +360,7 @@ void up_disable_irq(int irq)
|
|||
* the Interrupt Matrix.
|
||||
*/
|
||||
|
||||
xtensa_disable_cpuint(&g_intenable, 1ul << cpuint);
|
||||
xtensa_disable_cpuint(&g_intenable, cpuint);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -394,7 +394,7 @@ void up_enable_irq(int irq)
|
|||
{
|
||||
/* Enable the CPU interrupt now for internal CPU. */
|
||||
|
||||
xtensa_enable_cpuint(&g_intenable, (1ul << cpuint));
|
||||
xtensa_enable_cpuint(&g_intenable, cpuint);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -597,7 +597,7 @@ void esp32s2_teardown_irq(int periphid, int cpuint)
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
uint32_t *xtensa_int_decode(uint32_t cpuints, uint32_t *regs)
|
||||
uint32_t *xtensa_int_decode(uint32_t *cpuints, uint32_t *regs)
|
||||
{
|
||||
uint32_t mask;
|
||||
int bit;
|
||||
|
|
@ -609,15 +609,15 @@ uint32_t *xtensa_int_decode(uint32_t cpuints, uint32_t *regs)
|
|||
/* Skip over zero bits, eight at a time */
|
||||
|
||||
for (bit = 0, mask = 0xff;
|
||||
bit < ESP32S2_NCPUINTS && (cpuints & mask) == 0;
|
||||
bit < ESP32S2_NCPUINTS && (cpuints[0] & mask) == 0;
|
||||
bit += 8, mask <<= 8);
|
||||
|
||||
/* Process each pending CPU interrupt */
|
||||
|
||||
for (; bit < ESP32S2_NCPUINTS && cpuints != 0; bit++)
|
||||
for (; bit < ESP32S2_NCPUINTS && cpuints[0] != 0; bit++)
|
||||
{
|
||||
mask = 1 << bit;
|
||||
if ((cpuints & mask) != 0)
|
||||
if ((cpuints[0] & mask) != 0)
|
||||
{
|
||||
/* Extract the IRQ number from the mapping table */
|
||||
|
||||
|
|
@ -628,7 +628,7 @@ uint32_t *xtensa_int_decode(uint32_t cpuints, uint32_t *regs)
|
|||
|
||||
/* Clear software or edge-triggered interrupt */
|
||||
|
||||
xtensa_intclear(mask);
|
||||
xtensa_intclear(bit);
|
||||
|
||||
/* Dispatch the CPU interrupt.
|
||||
*
|
||||
|
|
@ -642,7 +642,7 @@ uint32_t *xtensa_int_decode(uint32_t cpuints, uint32_t *regs)
|
|||
* we can exit the look early.
|
||||
*/
|
||||
|
||||
cpuints &= ~mask;
|
||||
cpuints[0] &= ~mask;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -343,7 +343,7 @@ static int esp32s3_getcpuint(int cpu, uint32_t intmask)
|
|||
|
||||
if (ret >= 0)
|
||||
{
|
||||
xtensa_enable_cpuint(&g_intenable[cpu], 1ul << ret);
|
||||
xtensa_enable_cpuint(&g_intenable[cpu], ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
@ -499,7 +499,7 @@ void up_irqinitialize(void)
|
|||
#ifdef CONFIG_ESPRESSIF_WIFI
|
||||
g_cpu0_intmap[ESP32S3_CPUINT_MAC] = CPUINT_ASSIGN(ESP32S3_IRQ_MAC);
|
||||
g_cpu0_intmap[ESP32S3_CPUINT_PWR] = CPUINT_ASSIGN(ESP32S3_IRQ_PWR);
|
||||
xtensa_enable_cpuint(&g_intenable[0], 1 << ESP32S3_CPUINT_MAC);
|
||||
xtensa_enable_cpuint(&g_intenable[0], ESP32S3_CPUINT_MAC);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
|
|
@ -570,7 +570,7 @@ void up_disable_irq(int irq)
|
|||
}
|
||||
#endif
|
||||
|
||||
xtensa_disable_cpuint(&g_intenable[cpu], 1ul << cpuint);
|
||||
xtensa_disable_cpuint(&g_intenable[cpu], cpuint);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -615,7 +615,7 @@ void up_enable_irq(int irq)
|
|||
|
||||
/* Enable the CPU interrupt now for internal CPU. */
|
||||
|
||||
xtensa_enable_cpuint(&g_intenable[cpu], (1ul << cpuint));
|
||||
xtensa_enable_cpuint(&g_intenable[cpu], cpuint);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -986,7 +986,7 @@ int esp32s3_getcpuint_from_irq(int irq, int *cpu)
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
uint32_t *xtensa_int_decode(uint32_t cpuints, uint32_t *regs)
|
||||
uint32_t *xtensa_int_decode(uint32_t *cpuints, uint32_t *regs)
|
||||
{
|
||||
uint8_t *intmap;
|
||||
uint32_t mask;
|
||||
|
|
@ -1014,15 +1014,15 @@ uint32_t *xtensa_int_decode(uint32_t cpuints, uint32_t *regs)
|
|||
/* Skip over zero bits, eight at a time */
|
||||
|
||||
for (bit = 0, mask = 0xff;
|
||||
bit < ESP32S3_NCPUINTS && (cpuints & mask) == 0;
|
||||
bit < ESP32S3_NCPUINTS && (cpuints[0] & mask) == 0;
|
||||
bit += 8, mask <<= 8);
|
||||
|
||||
/* Process each pending CPU interrupt */
|
||||
|
||||
for (; bit < ESP32S3_NCPUINTS && cpuints != 0; bit++)
|
||||
for (; bit < ESP32S3_NCPUINTS && cpuints[0] != 0; bit++)
|
||||
{
|
||||
mask = 1 << bit;
|
||||
if ((cpuints & mask) != 0)
|
||||
if ((cpuints[0] & mask) != 0)
|
||||
{
|
||||
/* Extract the IRQ number from the mapping table */
|
||||
|
||||
|
|
@ -1044,7 +1044,7 @@ uint32_t *xtensa_int_decode(uint32_t cpuints, uint32_t *regs)
|
|||
|
||||
/* Clear software or edge-triggered interrupt */
|
||||
|
||||
xtensa_intclear(mask);
|
||||
xtensa_intclear(bit);
|
||||
|
||||
/* Dispatch the CPU interrupt.
|
||||
*
|
||||
|
|
@ -1058,7 +1058,7 @@ uint32_t *xtensa_int_decode(uint32_t cpuints, uint32_t *regs)
|
|||
* we can exit the look early.
|
||||
*/
|
||||
|
||||
cpuints &= ~mask;
|
||||
cpuints[0] &= ~mask;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1084,6 +1084,8 @@ uint32_t *xtensa_int_decode(uint32_t cpuints, uint32_t *regs)
|
|||
void esp32s3_irq_noniram_disable(void)
|
||||
{
|
||||
irqstate_t irqstate;
|
||||
uint32_t mask;
|
||||
int bit;
|
||||
int cpu;
|
||||
uint32_t oldint;
|
||||
uint32_t non_iram_ints;
|
||||
|
|
@ -1097,7 +1099,14 @@ void esp32s3_irq_noniram_disable(void)
|
|||
g_non_iram_int_disabled_flag[cpu] = true;
|
||||
oldint = g_intenable[cpu];
|
||||
|
||||
xtensa_disable_cpuint(&g_intenable[cpu], non_iram_ints);
|
||||
for (bit = 0; bit < ESP32S3_NCPUINTS; bit++)
|
||||
{
|
||||
mask = 1 << bit;
|
||||
if ((non_iram_ints & mask) != 0)
|
||||
{
|
||||
xtensa_disable_cpuint(&g_intenable[cpu], bit);
|
||||
}
|
||||
}
|
||||
|
||||
g_non_iram_int_disabled[cpu] = oldint & non_iram_ints;
|
||||
|
||||
|
|
@ -1121,6 +1130,8 @@ void esp32s3_irq_noniram_disable(void)
|
|||
void esp32s3_irq_noniram_enable(void)
|
||||
{
|
||||
irqstate_t irqstate;
|
||||
uint32_t mask;
|
||||
int bit;
|
||||
int cpu;
|
||||
uint32_t non_iram_ints;
|
||||
|
||||
|
|
@ -1132,7 +1143,14 @@ void esp32s3_irq_noniram_enable(void)
|
|||
|
||||
g_non_iram_int_disabled_flag[cpu] = false;
|
||||
|
||||
xtensa_enable_cpuint(&g_intenable[cpu], non_iram_ints);
|
||||
for (bit = 0; bit < ESP32S3_NCPUINTS; bit++)
|
||||
{
|
||||
mask = 1 << bit;
|
||||
if ((non_iram_ints & mask) != 0)
|
||||
{
|
||||
xtensa_enable_cpuint(&g_intenable[cpu], bit);
|
||||
}
|
||||
}
|
||||
|
||||
leave_critical_section(irqstate);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue