Xtensa/ESP32: Add Level1 handler, panic handler, remove EXECHOOKS.
This commit is contained in:
parent
eaa5968a22
commit
fdede8099b
@ -50,6 +50,19 @@
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Exception Codes */
|
||||
|
||||
#define XTENSA_NMI_EXCEPTION 0
|
||||
#define XTENSA_DEBUG_EXCEPTION 1
|
||||
#define XTENSA_DOUBLE_EXCEPTION 2
|
||||
#define XTENSA_KERNEL_EXCEPTION 3
|
||||
#define XTENSA_COPROC_EXCEPTION 4
|
||||
#define XTENSA_LEVEL2_EXCEPTION 5
|
||||
#define XTENSA_LEVEL3_EXCEPTION 6
|
||||
#define XTENSA_LEVEL4_EXCEPTION 7
|
||||
#define XTENSA_LEVEL5_EXCEPTION 8
|
||||
#define XTENSA_LEVEL6_EXCEPTION 9
|
||||
|
||||
/* Interrupt Matrix
|
||||
*
|
||||
* The Interrupt Matrix embedded in the ESP32 independently allocates
|
||||
|
@ -249,6 +249,7 @@ uint32_t *xtensa_int_decode(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_panic(int xptcode, uint32_t *regs) noreturn_function;
|
||||
|
||||
/* Software interrupt handler */
|
||||
|
||||
|
@ -158,3 +158,38 @@ void up_assert(const uint8_t *filename, int lineno)
|
||||
|
||||
xtensa_assert(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: xtensa_panic
|
||||
****************************************************************************/
|
||||
|
||||
void xtensa_panic(int xptcode, uint32_t *regs)
|
||||
{
|
||||
#if CONFIG_TASK_NAME_SIZE > 0 && defined(CONFIG_DEBUG_ALERT)
|
||||
struct tcb_s *rtcb = this_task();
|
||||
#endif
|
||||
|
||||
/* We get here when a un-dispatch-able, irrecoverable excpetion occurs */
|
||||
|
||||
board_autoled_on(LED_ASSERTION);
|
||||
|
||||
#if CONFIG_TASK_NAME_SIZE > 0
|
||||
_alert("Unhandled Exception %d task: %s\n", xptcode, rtcb->name);
|
||||
#else
|
||||
_alert("Unhandled Exception %d\n", xptcode);
|
||||
#endif
|
||||
|
||||
xtensa_dumpstate();
|
||||
|
||||
#ifdef CONFIG_ARCH_USBDUMP
|
||||
/* Dump USB trace data */
|
||||
|
||||
(void)usbtrace_enumerate(assert_tracecallback, NULL);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BOARD_CRASHDUMP
|
||||
board_crashdump(up_getsp(), this_task(), filename, lineno);
|
||||
#endif
|
||||
|
||||
xtensa_assert(EXIT_FAILURE);
|
||||
}
|
||||
|
@ -127,25 +127,6 @@
|
||||
and a2, a2, a4
|
||||
beqz a2, 5f /* Nothing to do */
|
||||
|
||||
#ifdef XT_INTEXC_HOOKS
|
||||
/* Call interrupt hook if present to (pre)handle interrupts. */
|
||||
|
||||
movi a4, _xt_intexc_hooks
|
||||
l32i a4, a4, \level << 2
|
||||
beqz a4, 2f
|
||||
|
||||
#ifdef __XTENSA_CALL0_ABI__
|
||||
callx0 a4
|
||||
beqz a2, 5f
|
||||
#else
|
||||
mov a6, a2
|
||||
callx4 a4
|
||||
beqz a6, 5f
|
||||
mov a2, a6
|
||||
#endif
|
||||
2:
|
||||
#endif
|
||||
|
||||
/* If multiple bits are set then MSB has highest priority. */
|
||||
|
||||
extract_msb a4, a2 /* a4 = MSB of a2, a2 trashed */
|
||||
@ -259,10 +240,63 @@
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* LOW PRIORITY (LEVEL 1) LOW LEVEL HANDLER.
|
||||
* LEVEL 1 INTERRUPT HANDLER
|
||||
****************************************************************************/
|
||||
/* The level1 interrupt vector is invoked via the User exception vector. */
|
||||
|
||||
#warning REVISIT level 1 interrupt handlers
|
||||
.section HANDLER_SECTION, "ax"
|
||||
.type _xtensa_level1_handler, @function
|
||||
.align 4
|
||||
|
||||
_xtensa_level1_handler:
|
||||
|
||||
mov a0, sp /* sp == a1 */
|
||||
addi sp, sp, -(4 * XCPTCONTEXT_SIZE) /* Allocate interrupt stack frame */
|
||||
s32i a0, sp, (4 * REG_A1) /* Save pre-interrupt SP */
|
||||
rsr a0, PS /* Save interruptee's PS */
|
||||
s32i a0, sp, (4 * REG_PS)
|
||||
rsr a0, EPC_1 /* Save interruptee's PC */
|
||||
s32i a0, sp, (4 * REG_PC)
|
||||
rsr a0, EXCSAVE_1 /* Save interruptee's a0 */
|
||||
s32i a0, sp, (4 * REG_A0)
|
||||
|
||||
/* Save rest of interrupt context. */
|
||||
|
||||
s32i a2, sp, (4 * REG_A2)
|
||||
mov a2, sp /* Address of state save on stack */
|
||||
call0 _xtensa_context_save /* Save full register state */
|
||||
|
||||
/* Set up PS for C, enable interrupts above this level and clear EXCM. */
|
||||
|
||||
ps_setup 1 a0
|
||||
|
||||
/* Decode and dispatch the interrupt. In the event of an interrupt
|
||||
* level context dispatch_c_isr() will switch stacks to the new task's
|
||||
* context save area.
|
||||
*/
|
||||
|
||||
dispatch_c_isr 1 XCHAL_INTLEVEL1_MASK
|
||||
|
||||
/* Restore registers in preparation to return from interrupt */
|
||||
|
||||
call0 _xtensa_context_restore
|
||||
|
||||
/* Restore only level-specific regs (the rest were already restored) */
|
||||
|
||||
l32i a0, sp, (4 * REG_PS) /* Retrieve interruptee's PS */
|
||||
wsr a0, EPS_1
|
||||
l32i a0, sp, (4 * REG_PC) /* Retrieve interruptee's PC */
|
||||
wsr a0, EPC_1
|
||||
l32i a0, sp, (4 * REG_A0) /* Retrieve interruptee's A0 */
|
||||
l32i a2, sp, (4 * REG_A2) /* Retrieve interruptee's A2 */
|
||||
l32i sp, sp, (4 * REG_A1) /* Remove interrupt stack frame */
|
||||
rsync /* Ensure EPS and EPC written */
|
||||
|
||||
/* Return from interrupt. RFI restores the PS from EPS_1 and jumps to
|
||||
* the address in EPC_1.
|
||||
*/
|
||||
|
||||
rfi 1
|
||||
|
||||
/****************************************************************************
|
||||
* MEDIUM PRIORITY (LEVEL 2+) INTERRUPT LOW LEVEL HANDLERS.
|
||||
@ -310,7 +344,7 @@ _xtensa_level2_handler:
|
||||
/* Save rest of interrupt context. */
|
||||
|
||||
s32i a2, sp, (4 * REG_A2)
|
||||
movi a2, sp /* Address of state save on stack */
|
||||
mov a2, sp /* Address of state save on stack */
|
||||
call0 _xtensa_context_save /* Save full register state */
|
||||
|
||||
/* Set up PS for C, enable interrupts above this level and clear EXCM. */
|
||||
@ -367,7 +401,7 @@ _xtensa_level3_handler:
|
||||
/* Save rest of interrupt context. */
|
||||
|
||||
s32i a2, sp, (4 * REG_A2)
|
||||
movi a2, sp /* Address of state save on stack */
|
||||
mov a2, sp /* Address of state save on stack */
|
||||
call0 _xtensa_context_save /* Save full register state */
|
||||
|
||||
/* Set up PS for C, enable interrupts above this level and clear EXCM. */
|
||||
@ -424,7 +458,7 @@ _xtensa_level4_handler:
|
||||
/* Save rest of interrupt context. */
|
||||
|
||||
s32i a2, sp, (4 * REG_A2)
|
||||
movi a2, sp /* Address of state save on stack */
|
||||
mov a2, sp /* Address of state save on stack */
|
||||
call0 _xtensa_context_save /* Save full register state */
|
||||
|
||||
/* Set up PS for C, enable interrupts above this level and clear EXCM. */
|
||||
@ -481,7 +515,7 @@ _xtensa_level5_handler:
|
||||
/* Save rest of interrupt context. */
|
||||
|
||||
s32i a2, sp, (4 * REG_A2)
|
||||
movi a2, sp /* Address of state save on stack */
|
||||
mov a2, sp /* Address of state save on stack */
|
||||
call0 _xtensa_context_save /* Save full register state */
|
||||
|
||||
/* Set up PS for C, enable interrupts above this level and clear EXCM. */
|
||||
@ -538,7 +572,7 @@ _xtensa_level6_handler:
|
||||
/* Save rest of interrupt context. */
|
||||
|
||||
s32i a2, sp, (4 * REG_A2)
|
||||
movi a2, sp /* Address of state save on stack */
|
||||
mov a2, sp /* Address of state save on stack */
|
||||
call0 _xtensa_context_save /* Save full register state */
|
||||
|
||||
/* Set up PS for C, enable interrupts above this level and clear EXCM. */
|
||||
@ -618,29 +652,30 @@ _xtensa_level6_handler:
|
||||
|
||||
_xtensa_level2_handler:
|
||||
|
||||
#ifdef XT_INTEXC_HOOKS
|
||||
/* Call interrupt hook if present to (pre)handle interrupts. */
|
||||
#if 1
|
||||
/* For now, just panic */
|
||||
|
||||
movi a0, _xt_intexc_hooks
|
||||
l32i a0, a0, 2 << 2
|
||||
beqz a0, 1f
|
||||
mov a0, sp /* sp == a1 */
|
||||
addi sp, sp, -(4 * XCPTCONTEXT_SIZE) /* Allocate interrupt stack frame */
|
||||
s32i a0, sp, (4 * REG_A1) /* Save pre-interrupt SP */
|
||||
rsr a0, EPS_2 /* Save interruptee's PS */
|
||||
s32i a0, sp, (4 * REG_PS)
|
||||
rsr a0, EPC_2 /* Save interruptee's PC */
|
||||
s32i a0, sp, (4 * REG_PC)
|
||||
rsr a0, EXCSAVE_2 /* Save interruptee's a0 */
|
||||
s32i a0, sp, (4 * REG_A0)
|
||||
|
||||
.Ln_xtensa_level2_handler_call_hook:
|
||||
s32i a2, sp, (4 * REG_A2)
|
||||
movi a2, XTENSA_LEVEL2_EXCEPTION /* Address of state save on stack */
|
||||
call0 _xtensa_panic /* Does not return */
|
||||
|
||||
callx0 a0 /* Must NOT disturb stack! */
|
||||
|
||||
1:
|
||||
#endif
|
||||
|
||||
/* USER_EDIT:
|
||||
* ADD HIGH PRIORITY LEVEL 2 INTERRUPT HANDLER CODE HERE.
|
||||
*/
|
||||
|
||||
.align 4
|
||||
#else
|
||||
/* Add high priority level 2 interrupt handler code here. */
|
||||
|
||||
rsr a0, EXCSAVE_2 /* Restore a0 */
|
||||
rfi 2
|
||||
|
||||
#endif
|
||||
#endif /* XCHAL_INT_NLEVELS >=2 && XCHAL_EXCM_LEVEL < 2 && XCHAL_DEBUGLEVEL !=2 */
|
||||
|
||||
#if XCHAL_INT_NLEVELS >=3 && XCHAL_EXCM_LEVEL < 3 && XCHAL_DEBUGLEVEL !=3
|
||||
@ -650,28 +685,32 @@ _xtensa_level2_handler:
|
||||
|
||||
_xtensa_level3_handler:
|
||||
|
||||
#ifdef XT_INTEXC_HOOKS
|
||||
/* Call interrupt hook if present to (pre)handle interrupts. */
|
||||
#if 1
|
||||
/* For now, just panic */
|
||||
|
||||
movi a0, _xt_intexc_hooks
|
||||
l32i a0, a0, 3 << 2
|
||||
beqz a0, 1f
|
||||
mov a0, sp /* sp == a1 */
|
||||
addi sp, sp, -(4 * XCPTCONTEXT_SIZE) /* Allocate interrupt stack frame */
|
||||
s32i a0, sp, (4 * REG_A1) /* Save pre-interrupt SP */
|
||||
rsr a0, EPS_3 /* Save interruptee's PS */
|
||||
s32i a0, sp, (4 * REG_PS)
|
||||
rsr a0, EPC_3 /* Save interruptee's PC */
|
||||
s32i a0, sp, (4 * REG_PC)
|
||||
rsr a0, EXCSAVE_3 /* Save interruptee's a0 */
|
||||
s32i a0, sp, (4 * REG_A0)
|
||||
|
||||
.Ln_xtensa_level3_handler_call_hook:
|
||||
s32i a2, sp, (4 * REG_A2)
|
||||
movi a2, XTENSA_LEVEL3_EXCEPTION /* Address of state save on stack */
|
||||
call0 _xtensa_panic /* Does not return */
|
||||
|
||||
callx0 a0 /* Must NOT disturb stack! */
|
||||
1:
|
||||
#endif
|
||||
#else
|
||||
wsr a0, EXCSAVE_3 /* Save a0 */
|
||||
|
||||
/* USER_EDIT:
|
||||
* ADD HIGH PRIORITY LEVEL 3 INTERRUPT HANDLER CODE HERE.
|
||||
*/
|
||||
|
||||
.align 4
|
||||
/* Add high priority level 2 interrupt handler code here. */
|
||||
|
||||
rsr a0, EXCSAVE_3 /* Restore a0 */
|
||||
rfi 3
|
||||
|
||||
#endif
|
||||
#endif /* XCHAL_INT_NLEVELS >=3 && XCHAL_EXCM_LEVEL < 3 && XCHAL_DEBUGLEVEL !=3 */
|
||||
|
||||
#if XCHAL_INT_NLEVELS >=4 && XCHAL_EXCM_LEVEL < 4 && XCHAL_DEBUGLEVEL !=4
|
||||
@ -681,28 +720,32 @@ _xtensa_level3_handler:
|
||||
|
||||
_xtensa_level4_handler:
|
||||
|
||||
#ifdef XT_INTEXC_HOOKS
|
||||
/* Call interrupt hook if present to (pre)handle interrupts. */
|
||||
#if 1
|
||||
/* For now, just panic */
|
||||
|
||||
movi a0, _xt_intexc_hooks
|
||||
l32i a0, a0, 4 << 2
|
||||
beqz a0, 1f
|
||||
mov a0, sp /* sp == a1 */
|
||||
addi sp, sp, -(4 * XCPTCONTEXT_SIZE) /* Allocate interrupt stack frame */
|
||||
s32i a0, sp, (4 * REG_A1) /* Save pre-interrupt SP */
|
||||
rsr a0, EPS_4 /* Save interruptee's PS */
|
||||
s32i a0, sp, (4 * REG_PS)
|
||||
rsr a0, EPC_4 /* Save interruptee's PC */
|
||||
s32i a0, sp, (4 * REG_PC)
|
||||
rsr a0, EXCSAVE_4 /* Save interruptee's a0 */
|
||||
s32i a0, sp, (4 * REG_A0)
|
||||
|
||||
.Ln_xtensa_level4_handler_call_hook:
|
||||
s32i a2, sp, (4 * REG_A2)
|
||||
movi a2, XTENSA_LEVEL4_EXCEPTION /* Address of state save on stack */
|
||||
call0 _xtensa_panic /* Does not return */
|
||||
|
||||
callx0 a0 /* Must NOT disturb stack! */
|
||||
1:
|
||||
#endif
|
||||
#else
|
||||
wsr a0, EXCSAVE_4 /* Save a0 */
|
||||
|
||||
/* USER_EDIT:
|
||||
* ADD HIGH PRIORITY LEVEL 4 INTERRUPT HANDLER CODE HERE.
|
||||
*/
|
||||
|
||||
.align 4
|
||||
/* Add high priority level 2 interrupt handler code here. */
|
||||
|
||||
rsr a0, EXCSAVE_4 /* Restore a0 */
|
||||
rfi 4
|
||||
|
||||
#endif
|
||||
#endif /* XCHAL_INT_NLEVELS >=4 && XCHAL_EXCM_LEVEL < 4 && XCHAL_DEBUGLEVEL !=4 */
|
||||
|
||||
#if XCHAL_INT_NLEVELS >=5 && XCHAL_EXCM_LEVEL < 5 && XCHAL_DEBUGLEVEL !=5
|
||||
@ -712,26 +755,32 @@ _xtensa_level4_handler:
|
||||
|
||||
_xtensa_level5_handler:
|
||||
|
||||
#ifdef XT_INTEXC_HOOKS
|
||||
/* Call interrupt hook if present to (pre)handle interrupts. */
|
||||
#if 1
|
||||
/* For now, just panic */
|
||||
|
||||
movi a0, _xt_intexc_hooks
|
||||
l32i a0, a0, 5 << 2
|
||||
beqz a0, 1f
|
||||
mov a0, sp /* sp == a1 */
|
||||
addi sp, sp, -(4 * XCPTCONTEXT_SIZE) /* Allocate interrupt stack frame */
|
||||
s32i a0, sp, (4 * REG_A1) /* Save pre-interrupt SP */
|
||||
rsr a0, EPS_5 /* Save interruptee's PS */
|
||||
s32i a0, sp, (4 * REG_PS)
|
||||
rsr a0, EPC_5 /* Save interruptee's PC */
|
||||
s32i a0, sp, (4 * REG_PC)
|
||||
rsr a0, EXCSAVE_5 /* Save interruptee's a0 */
|
||||
s32i a0, sp, (4 * REG_A0)
|
||||
|
||||
.Ln_xtensa_level5_handler_call_hook:
|
||||
s32i a2, sp, (4 * REG_A2)
|
||||
movi a2, XTENSA_LEVEL5_EXCEPTION /* Address of state save on stack */
|
||||
call0 _xtensa_panic /* Does not return */
|
||||
|
||||
callx0 a0 /* Must NOT disturb stack! */
|
||||
1:
|
||||
#endif
|
||||
#else
|
||||
wsr a0, EXCSAVE_5 /* Save a0 */
|
||||
|
||||
/* USER_EDIT:
|
||||
* ADD HIGH PRIORITY LEVEL 5 INTERRUPT HANDLER CODE HERE.
|
||||
*/
|
||||
/* Add high priority level 2 interrupt handler code here. */
|
||||
|
||||
rsr a0, EXCSAVE_5 /* Restore a0 */
|
||||
rfi 5
|
||||
|
||||
#endif
|
||||
#endif /* XCHAL_INT_NLEVELS >=5 && XCHAL_EXCM_LEVEL < 5 && XCHAL_DEBUGLEVEL !=5 */
|
||||
|
||||
#if XCHAL_INT_NLEVELS >=6 && XCHAL_EXCM_LEVEL < 6 && XCHAL_DEBUGLEVEL !=6
|
||||
@ -741,24 +790,30 @@ _xtensa_level5_handler:
|
||||
|
||||
_xtensa_level6_handler:
|
||||
|
||||
#ifdef XT_INTEXC_HOOKS
|
||||
/* Call interrupt hook if present to (pre)handle interrupts. */
|
||||
#if 1
|
||||
/* For now, just panic */
|
||||
|
||||
movi a0, _xt_intexc_hooks
|
||||
l32i a0, a0, 6 << 2
|
||||
beqz a0, 1f
|
||||
mov a0, sp /* sp == a1 */
|
||||
addi sp, sp, -(4 * XCPTCONTEXT_SIZE) /* Allocate interrupt stack frame */
|
||||
s32i a0, sp, (4 * REG_A1) /* Save pre-interrupt SP */
|
||||
rsr a0, EPS_6 /* Save interruptee's PS */
|
||||
s32i a0, sp, (4 * REG_PS)
|
||||
rsr a0, EPC_6 /* Save interruptee's PC */
|
||||
s32i a0, sp, (4 * REG_PC)
|
||||
rsr a0, EXCSAVE_6 /* Save interruptee's a0 */
|
||||
s32i a0, sp, (4 * REG_A0)
|
||||
|
||||
.Ln_xtensa_level6_handler_call_hook:
|
||||
s32i a2, sp, (4 * REG_A2)
|
||||
movi a2, XTENSA_LEVEL6_EXCEPTION /* Address of state save on stack */
|
||||
call0 _xtensa_panic /* Does not return */
|
||||
|
||||
callx0 a0 /* Must NOT disturb stack! */
|
||||
1:
|
||||
#endif
|
||||
#else
|
||||
wsr a0, EXCSAVE_6 /* Save a0 */
|
||||
|
||||
/* USER_EDIT:
|
||||
* ADD HIGH PRIORITY LEVEL 6 INTERRUPT HANDLER CODE HERE.
|
||||
*/
|
||||
/* Add high priority level 2 interrupt handler code here. */
|
||||
|
||||
rsr a0, EXCSAVE_6 /* Restore a0 */
|
||||
rfi 6
|
||||
|
||||
#endif
|
||||
#endif /* XCHAL_INT_NLEVELS >=6 && XCHAL_EXCM_LEVEL < 6 && XCHAL_DEBUGLEVEL !=6 */
|
||||
|
@ -59,6 +59,7 @@
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <arch/irq.h>
|
||||
#include <arch/chip/core-isa.h>
|
||||
#include <arch/xtensa/xtensa_specregs.h>
|
||||
|
||||
@ -103,23 +104,33 @@
|
||||
|
||||
#if XCHAL_HAVE_NMI
|
||||
.section HANDLER_SECTION, "ax"
|
||||
.type _xt_nmi, @function
|
||||
.type _xtensa_nmi, @function
|
||||
.align 4
|
||||
_xt_nmi:
|
||||
|
||||
#ifdef XT_INTEXC_HOOKS
|
||||
/* Call interrupt hook if present to (pre)handle interrupts. */
|
||||
_xtensa_nmi:
|
||||
|
||||
movi a0, _xt_intexc_hooks
|
||||
l32i a0, a0, XCHAL_NMILEVEL << 2
|
||||
beqz a0, 1f
|
||||
callx0 a0 /* Must NOT disturb stack! */
|
||||
1:
|
||||
#endif
|
||||
#if 1
|
||||
/* For now, just panic */
|
||||
|
||||
mov a0, sp /* sp == a1 */
|
||||
addi sp, sp, -(4 * XCPTCONTEXT_SIZE) /* Allocate interrupt stack frame */
|
||||
s32i a0, sp, (4 * REG_A1) /* Save pre-interrupt SP */
|
||||
rsr a0, EPS_2 /* Save interruptee's PS */
|
||||
s32i a0, sp, (4 * REG_PS)
|
||||
rsr a0, EPC_2 /* Save interruptee's PC */
|
||||
s32i a0, sp, (4 * REG_PC)
|
||||
rsr a0, EXCSAVE_2 /* Save interruptee's a0 */
|
||||
s32i a0, sp, (4 * REG_A0)
|
||||
|
||||
s32i a2, sp, (4 * REG_A2)
|
||||
movi a2, XTENSA_NMI_EXCEPTION /* Address of state save on stack */
|
||||
call0 _xtensa_panic /* Does not return */
|
||||
|
||||
#else
|
||||
/* Add high priority non-maskable interrupt (NMI) handler code here. */
|
||||
|
||||
rsr a0, EXCSAVE + XCHAL_NMILEVEL /* Restore a0 */
|
||||
rfi XCHAL_NMILEVEL
|
||||
|
||||
#endif
|
||||
#endif /* XCHAL_HAVE_NMI */
|
||||
|
129
arch/xtensa/src/common/xtensa_panic.S
Normal file
129
arch/xtensa/src/common/xtensa_panic.S
Normal file
@ -0,0 +1,129 @@
|
||||
/****************************************************************************
|
||||
* arch/xtensa/src/common/xtensa_panic.S
|
||||
*
|
||||
* Adapted from use in NuttX by:
|
||||
*
|
||||
* Copyright (C) 2016 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Derives from logic originally provided by Cadence Design Systems Inc.
|
||||
*
|
||||
* Copyright (c) 2006-2015 Cadence Design Systems Inc.
|
||||
*
|
||||
* 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_panic.S"
|
||||
|
||||
/* NOTES on the use of 'call0' for long jumps instead of 'j':
|
||||
*
|
||||
* 1. This file should be assembled with the -mlongcalls option to xt-xcc.
|
||||
*
|
||||
* 2. The -mlongcalls compiler option causes 'call0 dest' to be expanded to
|
||||
* a sequence 'l32r a0, dest' 'callx0 a0' which works regardless of the
|
||||
* distance from the call to the destination. The linker then relaxes
|
||||
* it back to 'call0 dest' if it determines that dest is within range.
|
||||
* This allows more flexibility in locating code without the performance
|
||||
* overhead of the 'l32r' literal data load in cases where the destination
|
||||
* is in range of 'call0'. There is an additional benefit in that 'call0'
|
||||
* has a longer range than 'j' due to the target being word-aligned, so
|
||||
* the 'l32r' sequence is less likely needed.
|
||||
*
|
||||
* 3. The use of 'call0' with -mlongcalls requires that register a0 not be
|
||||
* live at the time of the call, which is always the case for a function
|
||||
* call but needs to be ensured if 'call0' is used as a jump in lieu of 'j'.
|
||||
*
|
||||
* 4. This use of 'call0' is independent of the C function call ABI.
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <arch/irq.h>
|
||||
#include <arch/xtensa/core.h>
|
||||
#include <arch/xtensa/xtensa_specregs.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Assembly Language Marcros
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: _xtensa_panic
|
||||
*
|
||||
* Description:
|
||||
* Should be reached by call0 (preferable) or jump only. If call0, a0 says
|
||||
* where from. If on simulator, display panic message and abort, else loop
|
||||
* indefinitely.
|
||||
*
|
||||
* Entry Conditions:
|
||||
* - A1 = Stack frame already allocated. SP points to beginning of the
|
||||
* register frame.
|
||||
* - A0, A1, A2, PC and PS = Already saved in the stack frame
|
||||
* - A2 = Exception code
|
||||
*
|
||||
* Exit conditions:
|
||||
* Does not return.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
.section HANDLER_SECTION, "ax"
|
||||
.global _xtensa_panic
|
||||
.type _xtensa_panic, @function
|
||||
|
||||
.align 4
|
||||
.literal_position
|
||||
.align 4
|
||||
|
||||
_xtensa_panic:
|
||||
/* Save rest of interrupt context (A2=address of state save area on
|
||||
* stack.
|
||||
*/
|
||||
|
||||
mov a2, sp /* Address of state save on stack */
|
||||
call0 _xtensa_context_save /* Save full register state */
|
||||
|
||||
/* Save exc cause and vaddr into exception frame */
|
||||
|
||||
rsr a0, EXCCAUSE
|
||||
s32i a0, sp, (4 * REG_EXCCAUSE)
|
||||
rsr a0, EXCVADDR
|
||||
s32i a0, sp, (4 * REG_EXCVADDR)
|
||||
|
||||
/* Set up PS for C, reenable hi-pri interrupts, and clear EXCM. */
|
||||
|
||||
mov a0, PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM | PS_WOE
|
||||
wsr a0, PS
|
||||
|
||||
/* Call C panic handler: Arg1 (A2) = Exception code; Arg 2 (A3) = start
|
||||
* of the register save area.
|
||||
*/
|
||||
|
||||
mov a3, sp
|
||||
#ifdef __XTENSA_CALL0_ABI__
|
||||
call0 xtensa_panic /* Call xtensa_panic. Should not return */
|
||||
#else
|
||||
call4 xtensa_panic /* Call xtensa_panic. Should not return */
|
||||
#endif
|
||||
|
||||
1: j 1b /* loop infinitely */
|
||||
retw
|
@ -175,8 +175,8 @@ _xtensa_level6_vector:
|
||||
|
||||
_xtensa_nmi_vector:
|
||||
|
||||
wsr a0, EXCSAVE + XCHAL_NMILEVEL _ /* preserve a0 */
|
||||
call0 _xt_nmi /* load interrupt handler */
|
||||
wsr a0, EXCSAVE + XCHAL_NMILEVEL /* Preserve a0 */
|
||||
call0 _xtensa_nmi /* Load interrupt handler */
|
||||
|
||||
/* Never returns here - call0 is used as a jump */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user