⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 int2_medpri_dispatcher.s

📁 uCOS-II ports on Tensilica HiFi330 core.
💻 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 + -