📄 int2_medpri_dispatcher.s
字号:
// Medium-Priority Interrupt Dispatcher Template
// $Id: //depot/rel/BearValley/Xtensa/OS/xtos/int-medpri-dispatcher.S#1 $
// Customer ID=4654; Build=0x116b0; Copyright (c) 2004 by Tensilica Inc. ALL RIGHTS RESERVED.
// These coded instructions, statements, and computer programs are the
// copyrighted works and confidential proprietary information of Tensilica Inc.
// They may not be modified, copied, reproduced, distributed, or disclosed to
// third parties in any manner, medium, or form, in whole or in part, without
// the prior written consent of Tensilica Inc.
//
// By default, this file is included by inth-template.S .
// The default Makefile defines _INTERRUPT_LEVEL when assembling
// inth-template.S for each medium and high priority interrupt level.
//
// To use this template file, define a macro called _INTERRUPT_LEVEL
// to be the interrupt priority level of the vector, then include this file.
#include <xtensa/coreasm.h>
#include "internal.h"
#define _INTERRUPT_LEVEL 2
#define INTERRUPT_MASK XCHAL_INTLEVEL_MASK(_INTERRUPT_LEVEL)
#define SINGLE_INT_NUM XCHAL_INTLEVEL_NUM(_INTERRUPT_LEVEL)
#define STRUCT_BEGIN .pushsection .text; .struct 0
#define STRUCT_FIELD(ctype,size,pre,name) pre##name: .space size
#define STRUCT_AFIELD(ctype,size,pre,name,n) pre##name: .space (size)*(n)
#define STRUCT_END(sname) sname##Size:; .popsection
STRUCT_BEGIN
STRUCT_FIELD (long,4,UEXC_,pc)
STRUCT_FIELD (long,4,UEXC_,ps)
STRUCT_FIELD (long,4,UEXC_,sar)
STRUCT_FIELD (long,4,UEXC_,vpri)
/*STRUCT_AFIELD(long,4,UEXC_,areg, 4)*/ /* a2,a3,a4,a5 OR a2,a3,a8,a9 */
STRUCT_FIELD (long,4,UEXC_,a2)
STRUCT_FIELD (long,4,UEXC_,a3)
STRUCT_FIELD (long,4,UEXC_,a4_a8) /* a8 if call8-only configured */
STRUCT_FIELD (long,4,UEXC_,a5_a9) /* a9 if call8-only configured */
STRUCT_FIELD (long,4,UEXC_,exccause) /* NOTE: can probably rid of this one (pass direct) */
/*STRUCT_FIELD (long,4,UEXC_,excvaddr)*/
#if XCHAL_HAVE_LOOPS
STRUCT_FIELD (long,4,UEXC_,lcount)
STRUCT_FIELD (long,4,UEXC_,lbeg)
STRUCT_FIELD (long,4,UEXC_,lend)
#endif
#if XCHAL_HAVE_MAC16
STRUCT_FIELD (long,4,UEXC_,acclo)
STRUCT_FIELD (long,4,UEXC_,acchi)
STRUCT_AFIELD(long,4,UEXC_,mr, 4)
#endif
#define ALIGNPAD ((3 + XCHAL_HAVE_LOOPS + XCHAL_HAVE_MAC16*2) & 3) /* 16-byte alignment padding */
#if ALIGNPAD
STRUCT_AFIELD(long,4,UEXC_,pad, ALIGNPAD) /* 16-byte alignment padding */
#endif
/*STRUCT_AFIELD(char,1,UEXC_,ureg, (XCHAL_CPEXTRA_SA_SIZE_TOR2+3)&-4)*/ /* not used, and doesn't take alignment into account */
STRUCT_END(UserFrame)
// Strict non-preemptive prioritization
#if XCHAL_HAVE_CALL4AND12
# define A4 a4
# define A5 a5
#else
# define A4 a8
# define A5 a9
#endif
/* Check for UserFrameSize small enough not to require rounding...: */
/* Skip 16-byte save area, then 16-byte GCC nested func chaining area,
* then exception stack frame, then space for 8 regs for call12 below: */
.set UserFrameTotalSize, 16+16+UserFrameSize+32
/* Greater than 112 bytes? (max range of ADDI, both signs, when aligned to 16 bytes): */
.ifgt UserFrameTotalSize-112
/* Round up to 256-byte multiple to accelerate immediate adds: */
.set UserFrameTotalSize, ((UserFrameTotalSize+255) & 0xFFFFFF00)
.endif
# define ESF_TOTALSIZE UserFrameTotalSize
.text
.align 4
.global _Level2InterruptHandler
_Level2InterruptHandler:
/* Allocate an exception stack frame, save a2, a4, and a5, and fix PS as:
*
* - enable windowing for 'entry' (ps.woe=1, ps.excm=0)
* - setup ps.callinc to simulate call4
* - preserve user mode
* - mask all interrupts at EXCM_LEVEL and lower
*
* Then deallocate the stack, 'rsync' for the write to PS, then use
* 'entry' to re-allocate the stack frame and rotate the register
* window (like a call4, preserving a0..a3). */
rsr a2, EXCSAVE_2
addi a1, a1, -ESF_TOTALSIZE
s32i a2, a1, UEXC_a2
movi a2, PS_WOE|PS_CALLINC(1)|PS_UM|PS_INTLEVEL(XCHAL_EXCM_LEVEL)
s32i a4, a1, UEXC_a4_a8
s32i a5, a1, UEXC_a5_a9
wsr a2, PS
addi a1, a1, ESF_TOTALSIZE
rsync
movi a4, 0 /* terminate stack frames, overflow check */
_entry a1, ESF_TOTALSIZE
/* Reset the interrupt level to mask all interrupts at the current
* priority level and lower. Note the current priority level may be
* less than or equal to EXCM_LEVEL. */
rsil a15, _INTERRUPT_LEVEL
/* Preserve the SAR, loop, and MAC16 regs. Also, clear the interrupt. */
rsr a14, SAR
movi a12, INTERRUPT_MASK
s32i a14, a1, UEXC_sar
wsr a12, INTCLEAR // clear if edge-trig or s/w or wr/err (else no effect)
save_loops_mac16 a1, a13, a14
/* Load the handler from the table, initialize two args (interrupt
* number and exception stack frame), then call the interrupt handler.
* Note: The callx12 preserves the original user task's a4..a15.*/
movi a13, intHandlers
mov a15, a1
addx4 a13, a12, a13 /* Interrupt8*4 - index into dispatch table */
l32i a13, a13, 0
callx12 a13
/* Restore everything, and return. Raise the interrupt mask before
* returning to avoid a race condition where we deallocate the
* exception stack frame but still have more register values to
* restore from it. */
restore_loops_mac16 a1, a13, a14, a15
l32i a14, a1, UEXC_sar
spurious_int:
movi a0, return_from_exc
movi a13, 0xC0000000
wsr a14, SAR
or a0, a0, a13
addx2 a0, a13, a0
#if _INTERRUPT_LEVEL < XCHAL_EXCM_LEVEL
rsil a14, XCHAL_EXCM_LEVEL
#endif
retw
return_from_exc:
l32i a2, a5, UEXC_a2
l32i a4, a5, UEXC_a4_a8
l32i a5, a5, UEXC_a5_a9
rfi _INTERRUPT_LEVEL
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -