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

📄 hwi.h62

📁 SEED的VPM642测试程序-板级支持库
💻 H62
📖 第 1 页 / 共 2 页
字号:
;
;  Copyright 2003 by Texas Instruments Incorporated.
;  All rights reserved. Property of Texas Instruments Incorporated.
;  Restricted rights to use, duplicate or disclose this code are
;  granted through contract.
;  
;
; "@(#) DSP/BIOS 4.90.270 12-18-03 (barracuda-o04)"
;
;  ======== hwi.h62 ========
;  Assembly language HWI macros for C62
;
;

	.if ($isdefed("HWI_") = 0)      ; prevent multiple includes of this file
HWI_	.set	1

HWI_REGS	.set	019c0000h	; interrupt selector register base
HWI_SAT		.set	0200h		; bit position of SAT in CSR

	.include c62.h62
	.include chk.h62
	.include swi.h62
	.include trc.h62

;
;# ======== HWI_Obj ========
;
;#
;# Preconditions:
;#	none
;#
;# Postconditions:
;#	none
;#
;
	.asg    ":HWI_mkStub$regs:", HWI_Obj$regs
HWI_Obj	.macro	cflag, name, id, fxn, monitor, addr, type, operation, client, dispatch, arg, intrmask, ccmask
	CHK_nargs "HWI_Obj", client
	.if ($symcmp(":CHK_status:", "error") = 0)
	    .mexit
	.endif

	.global :name:, fxn

	.if (cflag != 0)
:name:		.set	:id:
	.endif
	
	.var	vector, clientcfg

	.asg hwi:id:, vector		; default vector = self branch

	; set clientcfg to 1 (or 0) according to whether the client module 
	; is configured (or not).
	.asg 0, clientcfg
	.if ($symcmp(client, "USER") != 0) 
	  .if ($symcmp(client, "CSL") == 0)
	    .asg 1, clientcfg
	  .else
	    .if (:client:$ = 1)
		.asg 1, clientcfg
	    .endif
	  .endif
	.endif

	; The following call to .mexit is to avoid generation of HWI objects
	; for interrupts greater that INT15.  This allows an HWI_UNUSED object
	; to be listed in the configuration.  This exit code was first put at
	; the start of the macro but this caused an error saying that USER$
	; was undefined.  The exit was put at this point in the macro to avoid
	; the build error. 
	.if (id > 15)
	    .mexit
	.endif

	.asg	:dispatch:, local_dispatch
	.asg	:fxn:, local_fxn

	; if this object is configured *and* is not "HWI_unused"
	.if ((cflag != 0) & ($symcmp(":local_fxn:", "HWI_unused") != 0))

	    ; if client is USER or another configured system module
	    .if (($symcmp(client, "USER") = 0) | (:clientcfg: = 1))

		; if no monitor, simply branch to user function directly
		.if ($symcmp(monitor, "Nothing") = 0)
		    .asg :local_fxn:, vector    ; vector = user specified fxn

		; else when need to monitor, create a function stub and call it
		.else
		    .if ( local_dispatch )
			.if ( $symcmp(":local_fxn:", "CLK_F_isr") = 0 )
			    HWI_mkStub :name:_stub, monitor, addr, operation, :name:_STS, CLK_F_isr
			.else
			    HWI_mkStub :name:_stub, monitor, addr, operation, :name:_STS, HWI_F_dispatch
			.endif
		    .else
			HWI_mkStub :name:_stub, monitor, addr, operation, :name:_STS, :local_fxn:
		    .endif
		    .asg :name:_stub, vector ; vector = HWI stub
		.endif
	    .endif
	.endif


	.if ($isdefed("HWI_GENERATE_RESET_VEC") = 0)
	    .asg	0, HWI_GENERATE_RESET_VEC
	.endif

	.if HWI_GENERATE_RESET_VEC = 1	; HWI_GENERATE_RESET_VEC is generated
	                              	; by the config tool
	    .sect ".hwi_reset"

	    .if ((id == 0))

		; For reset vector do not save/restore register used for 
		; branch, because b15 has not been initialized yet, and this 
		; causes an access to an indeterminate place in memory.

		mvkl :vector:,b0    ; load destination function address to b0
		mvkh :vector:,b0
		b b0		; start branch to destination function	
		nop		; fill delay slot, pad packet
		nop		; fill delay slot, pad packet
		nop		; fill delay slot, pad packet
		nop		; fill delay slot, pad packet
		nop		; fill delay slot, pad packet
	    .endif
	.endif

	; Now define ISFP.  Use a register for branching so can reach whole 
	; address space.

	.sect ".hwi_vec"
	.global hwi:id:
hwi:id::
	.if ((id == 0))

	    ; For reset vector do not save/restore register used for branch,
	    ; because b15 has not been initialized yet, and this causes an 
	    ; access to an indeterminate place in memory.

	    mvkl :vector:,b0	; load destination function address to b0
	    mvkh :vector:,b0
	    b b0		; start branch to destination function	
	    zero b0		; disable interrupts by clearing 'IER'
	    mvc b0,ier
	    nop			; fill delay slot, pad packet
	    nop			; fill delay slot, pad packet
	    nop			; fill delay slot, pad packet

	.elseif (id == 2)
	    .if (RTDX_USERTEXECUTION)

		.ref RTEMU_exe

		stw b0,*b15--[2]	; temp save b0 on stack 
		mvkl RTEMU_exe,b0	; load destination function address
		mvkh RTEMU_exe,b0
		b b0			; start branch to destination function	
		ldw *++b15[2],b0	; restore b0 register
		nop 2			; fill 2 b0 restore/branch delay slots
		nop			; fill delay slot, pad packet
		nop			; fill delay slot, pad packet

	    .else

spin?
		b spin?		; nested branches to block interrupts
		nop 4
		b spin?
		nop
		nop
		nop
		nop
		nop

	    .endif

	.elseif (($symcmp(local_fxn, "HWI_unused") == 0) & (!local_dispatch))

	    ; plug inifinite loop -- with nested branches to
	    ; disable interrupts -- for all undefined vectors that
	    ; aren't checked to "Use HWI Dispatcher"

spin?
	    b spin?		; nested branches to block interrupts
	    nop 4
	    b spin?
	    nop
	    nop
	    nop
	    nop
	    nop

	.else
	    .if ( local_dispatch )
		.global	_HWI_dispatchTab
		.var	dispatch_fxn
		.var	vec_fxn

		.if ( $symcmp(":local_fxn:", "CLK_F_isr") = 0 )

		    .global	CLK_F_isr
		    .global	FXN_F_run

		    .if ($symcmp(monitor, "Nothing") = 0)
			.asg	CLK_F_isr, vec_fxn
		    .else
			.asg	:name:_stub, vec_fxn
		    .endif
		    .asg	FXN_F_run, dispatch_fxn

		.else
		    .global	HWI_F_dispatch
		    ;
		    ; We allow dispatcher to be selected even for HWIs that
		    ; are HWI_unused.  Call FXN_F_nop in this case.
		    ; The assumption is that the user will subsequently call
		    ; IRQ_config to set the function to something real.
		    ;
		    .if ($symcmp(local_fxn, "HWI_unused") == 0)
			.asg	FXN_F_nop, local_fxn
		    .endif

		    .if ($symcmp(monitor, "Nothing") = 0)
			.asg	HWI_F_dispatch, vec_fxn
		    .else
			; HWI_F_dispatch will be called by monitor
			.asg	:name:_stub, vec_fxn
		    .endif
		    .asg	:local_fxn:, dispatch_fxn

		.endif
		
		stw	b0, *b15--[2]
		mvk	:id:, b0
		stw	b0, *+b15[1]
		mvkl	:vec_fxn:, b0
		mvkh	:vec_fxn:, b0
		b	b0
		ldw	*+b15[2], b0
		nop	4

		.sect	".cinit"
	    	.align	8
		.field	4 * STD_TARGWORDMAUS
		.field	_HWI_dispatchTab + (4 * :id: * STD_TARGWORDMAUS)
		.field	:dispatch_fxn:
		.field	:intrmask:
		.field	:ccmask:
		.field	:arg:

	    .else
	        ; For all vectors besides reset use a common packet format. This
	        ; packet can be used for self branches as well as branches to
	        ; HWI stubs.

	        stw b0,*b15--[2]	; temp save b0 on stack
	        mvkl :vector:,b0	; load destination function address to b0
	        mvkh :vector:,b0
	        b b0			; start branch to destination function
	        ldw *++b15[2],b0	; restore b0 register
	        nop 2			; fill 2 of b0 restore and branch delay slots
	        nop			; fill delay slot, pad packet
	        nop			; fill delay slot, pad packet
	    .endif

	.endif
	
	.endm


;
;# ======== HWI_config ========
;
;#
;# Preconditions:
;#	none
;#
;# Postconditions:
;#	none
;#
	.asg	"", HWI_config$regs
HWI_config	.macro _zerotab, _generate_reset_vec, _polaritymask, _intrmultlow, intrmulthigh

	.endm


;
;# ======== HWI_disable ========
;  Clears the GIE bit, returns the previous
;  CSR register value.
;#
;# Preconditions:
;#      none
;#
;# Postconditions:
;#	GIE = 0
;#      a4 = CSR when HWI_disable was invoked.
;
;  Note: The modified register list indicates a4.  If another register is 
;  specified as a parameter to the macro then it will not be listed in the 
;  modified register list, but a4 will because it is the default.
;
	.asg "a4,b0,csr",HWI_disable$regs
HWI_disable .macro regname 
	.if ($symlen(regname) = 0)	; if no register as parameter use a4
	    .asg "a4",regname
	.endif

	b hwid?
	mvc csr,b0
	mv b0,:regname:
	and ~GIE,b0,b0
	mvc b0,csr	
	nop 
hwid?:
	.endm


;
;# ======== HWI_enable ========
;  Sets the GIE bit.
;#
;# Preconditions:
;#      none
;#
;# Postconditions:
;#      GIE = 1
;#
;
	.asg "b0,csr",HWI_enable$regs
HWI_enable .macro dummy
	b hwie?
	mvc csr,b0
	or GIE,b0,b0
	mvc b0,csr	
	nop 2
hwie?:
	.endm


;
;# ======== HWI_mkStub ========
;
;#
;# Preconditions:
;#      none
;#
;# Postconditions:
;#      none
;#
;
        .asg    "", HWI_mkStub$regs
HWI_mkStub .macro name, monitor, addr, operation, stsName, fxn

	.sect ".hwi"

        ; first look at passed parameters and figure out what is to be done 
	.var firstChar, unaryop, stsop, len, monreg
      	.eval 0, monreg   	

	; compute stsop; the STS operation to perform
	.eval $firstch(operation, '(') - 1, len
	.asg ":operation(1, len):", stsop

	; compute unary operation to perform (if any).  
	.asg "; no unary operation specified", unaryop
	.if ($symcmp(":operation(len + 2):", "-") = 0)
	    .asg "neg", unaryop
	.endif
	.if ($symcmp(":operation(len + 2):", "|") = 0)
		.asg "abs", unaryop
	.endif

	; determine if a register is to be monitored
	.if ($isreg(monitor) = 1)
	    .eval 1, monreg   	; set flag saying are monitoring a register
	.elseif ($symcmp("Stack Pointer",monitor) = 0)
	    .eval 1, monreg	; set flag saying are monitoring a register
	    .asg "b15", monitor
	.endif

	; convert addr to a suitable constant 
	.asg ":addr(1):", firstChar
	.if ($iscons(firstChar) = 5)
				    ; if first char is 0-9, addr's a number
	.elseif ($isname(addr) & ($isdefed(addr) = 0))
	    .global addr	    ; must be external user defined symbol
	.endif

	; now generate the stub function
	.global :stsName:
:name::
	; check if TRC_STSHWI is enabled
	stw a2,*b15--[2]	; push registers used by TRC_query
	stw a4,*b15--[2]	
	stw DP,*b15--[2]
||	mvkl $bss, DP		; TRC_query needs b14 (DP) set to .bss
	mvkh $bss, DP

	TRC_query TRC_STSHWI	; TRC_query modifies a2 and a4
	mv a4,a2	
||	ldw *++b15[2], DP	; done with b14 (DP)


	; if TRC_STSHWI not enabled simply branch to interrupt function
 [a2]	mvkl :fxn:,a4		; form address of function to branch to
 [a2]	mvkh :fxn:,a4
 [a2]	b a4			; branch to interrupt function
 ||	ldw *++b15[2],a4	; pop registers used by TRC_query
 	ldw *++b15[2],a2	

	nop 4 			; pad delay slots of ldw instruction

	; Put value to be monitored into a temp register.  If a unary
	; operation is specified then do it.

	stw b1,*b15--[2]	; push registers used as temps
	stw b0,*b15--[2]

	.if(monreg = 1)			; if monitoring register

	    ; When monitoring register values and get to this point all
	    ; registers are intact except b15.   
	    ; b15 has been modified for the two registers that were
	    ; pushed on the stack.  

	    ; When b15 is to be monitored we adjust the value to correspond
	    ; to the b15 value when the ISR was taken.

	    .asg 0,monitor_b15		; test if monitoring b15
	    .if $symcmp(monitor,"b15") == 0
		.eval 1,monitor_b15 
	    .elseif $symcmp(monitor,"B15") == 0
		.eval 1,monitor_b15 
	    .endif  

	    .if(monitor_b15 = 1)	; indeed, monitor b15 ...
		mvk 16,b1		; 2 regs * 8 bytes/reg = 16 bytes
		addu b15,b1,b1:b0	; set b0 = b15 + 16

	    .else			; all other registers
	        mv monitor,b0		; put register value into temp register
	    .endif

            unaryop b0,b0		; do NEG or ABS on value 

	.else				; else if monitoring memory
	    mvkl addr,b1		; get address of memory value
	    mvkh addr,b1
	    ldw *b1,b0			; get memory value to temp register
	    nop 4			; wait for value to arrive
	    unaryop b0,b0	        ; do NEG or ABS on value 
	.endif

        ; save registers used for STS operation:
        ;    STS_add uses: a1, a3, b1, b2, b3
        ;    STS_delta uses: b1, b3, b4, b5
	;    the address of the STS object will be put in a4
   	;    b1 has already been saved as a temp register
	;
	.if .TMS320C6400
            .eval C64_A1|C64_A3|C64_A4, STSAREGS
            .eval C64_B2|C64_B3|C64_B4|C64_B5, STSBREGS
	    C64_save STSAREGS, STSBREGS, 0
	.else
            .eval C62_A1|C62_A3|C62_A4|C62_B2|C62_B3|C62_B4|C62_B5, STSREGS
	    C62_save STSREGS, 0
	.endif

	; ensure linear addressing for STS operation
	mvc amr,b4			; note: direct AMR save/restore is more
  ||	zero b1				; efficient than C62_save/C62_restore
	stw b4,*b15--[2]		; save current AMR onto stack
  ||	mvc b1,amr			; set AMR=0

	; invoke specified STS macro
	mvkl stsName,a4			; put address of STS object in a4
	mvkh stsName,a4			; put address of STS object in a4
	mv b0,b4			; put monitor value (b0) in b4
	stsop				; invoke STS macro 

	ldw *++b15[2],b0		; get saved AMR into temp reg b0;
					; C62_restore takes care of delay slots
        ; restore registers used for STS operation:
	.if .TMS320C6400
	    C64_restore STSAREGS, STSBREGS, 0
	.else
	    C62_restore STSREGS, 0
	.endif
	mvc b0,amr			; restore saved AMR

	; branch to interrupt function
	mvkl :fxn:,b0		; form address of function to branch to
	mvkh :fxn:,b0
	b b0			; branch to interrupt function
 || 	ldw *++b15[2],b0	; pop b0 register
 	ldw *++b15[2],b1	; pop b1 register
	nop 4 			; pad delay slots

	.endm

;
;# ======== HWI_restore ========
;  Conditionally sets the GIE bit.
;#
;# Preconditions:
;#      a4 = mask (GIE will be set to the value of bit 0) 
;#	GIE = 0
;#
;# Postconditions:
;#      none
;#
;# Constraints and Calling Environment:
;#      This macro must be invoked from an atomic context. i.e., the
;#	instructions of this macro should not be interrupted.
;
	.asg "a1,b0,csr",HWI_restore$regs
HWI_restore .macro regname 
	.if ($symlen(regname) = 0)	; if no register as parameter use a4
	    .asg "a4",regname
	.endif

	; NOTE: the following four instructions may not be interrupted.
	;       This macro must be invoked from an atomic context.
  	and :regname:,GIE,a1
 [a1] 	mvc csr,b0
 [a1] 	or GIE,b0,b0
 [a1] 	mvc b0,csr	

	.endm


;
;#  ======== HWI_end ========
;  Invoked by confend.s62 at the end of all other configuration
;  declarations.
;
;#
;# Preconditions:
;#      none
;#
;# Postconditions:
;#      none
;#
	.asg	"", HWI_end$regs
HWI_end .macro
	.endm

;
;# ======== HWI_init ========

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -