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

📄 interrup.s

📁 VRTX操作系统
💻 S
字号:
;*************************************************************************
;
;
;  IMPORTANT - USE OF THIS SOFTWARE IS SUBJECT TO LICENSE RESTRICTIONS
;  CAREFULLY READ THE LICENSE AGREEMENT BEFORE USING THE SOFTWARE
;
;
;*************************************************************************
; ORIGIN UK 35-0450.05-400
;******************************************************************
;
;       ARM VRTRmc
;
;******************************************************************
;
;       Description
;       ===========
;
;       INTERRUP.S - Interrupt Handler
;
;
;       Revision History
;       ================
;
;       Version    Date       Author               Reason for Change
;       1.0        14/03/96   Samsung & P.Cumming  Initial Version
;                                                  Derived from Samsung
;	1.1        18/04/96   P.Cumming            ui_enter/exit & interrupt
;	                                           en/disable separate segments
;	1.2	   10/05/96   P.Cumming            VMC_PROBE_INTERRUPT added
;	1.3        30/07/96   P.Cumming            int enable/disable removed
;	1.4        11/09/96   P.Cumming            ui_enter check IRQ/FIQ race
;*******************************************************************
;****************************************************************************
;			ARM Constants
;****************************************************************************

ResetV			EQU	0
UndefInstrV		EQU	4
SWIV			EQU	8
PrefAbortV		EQU	&c
DataAbortV		EQU	&10
AddrExceptV		EQU	&14
IRQV			EQU	&18
FIQV			EQU	&1c
ErrorV			EQU	&20
LastV			EQU	&24

UserMode		EQU	&10
FIQMode			EQU	&11
IRQMode			EQU	&12
SVCMode			EQU	&13
AbortMode		EQU	&17
UndefMode		EQU	&1b
MaskMode		EQU	&1f

PSR_32Bit		EQU	&10
ModeMask		EQU	&0000001f 
SubModeMask		EQU	&0000000f 
NoInt			EQU	&000000c0
NoIRQInt		EQU	&00000080
NoFIQInt		EQU	&00000040
ThumbMode		EQU	&00000020
IFConfig		EQU	&000000d0
CCMask			EQU	&f0000000


;****************************************************************************
;	External Symbols Declaration
;****************************************************************************

	IMPORT	vmc_intr_count
	IMPORT	vmc_timer_ticks
	IMPORT	vmc_ticker
	IMPORT	vmc_sched_needed
	IMPORT	vmc_tresched
	IMPORT	vmc_keep_FIQ_enabled
 IF :DEF:VMC_PROBE_INTERRUPT
	IMPORT	vmc_intr_disable_start
	IMPORT	vmc_intr_disable_stop
 ENDIF

	EXPORT	|ui_enter|
	EXPORT	|ui_exit|

	AREA	|C$$code$$interrupt|, CODE, READONLY, INTERWORK
	
	IF Thumb = {TRUE}
	CODE32
	ENDIF
	
c_intr_count	DCD	vmc_intr_count
c_timer_ticks	DCD	vmc_timer_ticks
c_sched_needed	DCD	vmc_sched_needed
c_keep_FIQ_enabled DCD  vmc_keep_FIQ_enabled


;****************************************************************************
;		ui_enter : Interrupt Enter Routine
;****************************************************************************
;
;	extern	void	ui_enter(void);
;
|ui_enter|
;
;	ui_enter stack frame
;
;	+---------------+
;	|    v1 - v4	| <---- sp
;	+---------------+
;	|	lr	|
;	+---------------+
;	|	spsr	| <---- ui_enter start part sp
;	+---------------+
;	|    r0 - r3	|
;	+---------------+
;	|	ip	|
;	+---------------+
;	|	lr	|
;	+---------------+
;
	stmfd	sp!,{v1-v4,lr}		;save local variable & return address

	ldr	v1,c_keep_FIQ_enabled	;load address of vmc_keep_FIQ_enabled
	ldrb	v2,[v1]			;get vmc_keep_FIQ_enables
	cmp	v2,#0			;check if we keep FIQ enabled

;	interrupt disable --> IRQ & FIQ
	mrs	v1,cpsr			;get CPSR		
	orreq	v2,v1,#NoInt		;IRQ & FIQ interrupt disable bit set
	orrne	v2,v1,#NoIRQInt		;IRQ disable bit set
	msr	cpsr,v2			;interrupt disable

;	interrupt count inc & first interrupt check
	ldr	v4,c_intr_count		;initial value = 0
	ldrb	v3,[v4]			;get interrupt count
	add	v3,v3,#1		;increment interrupt count
	strb	v3,[v4]			;save interrupt count

;	if not first interrupt, restore status & return
	cmp	v3,#1			;first interrupt ?
	beq	check_race
	msr	cpsr,v1			;restore saved CPSR
	ldmfd	sp!,{v1-v4,pc}		;return ui_enter

check_race
;	check race condition
	mrs	v4,spsr			;get interrupted task's status
	and	lr,v4,#ModeMask
	cmp	lr,#SVCMode
	beq	first_interrupt
	msr	cpsr,v1
	ldmfd sp!,{v1-v4,pc}		;return ui_enter

first_interrupt
;	first interrupt --> make task's interrupt stack frame
	ldr	v3,[sp,#(11*4)]		;get interrupted task's return address
	bic	v2,v2,#ModeMask
	orr	v2,v2,lr
	msr	cpsr,v2			;change before interrupt mode

;	make task's interrupt stack frame
;
;	+---------------+
;	|	cpsr	|
;	+---------------+
;	|    r0 - r3	|
;	+---------------+
;	|	ip	|
;	+---------------+
;	|	lr	|
;	+---------------+
;	|	pc	|
;	+---------------+
;
	stmfd	sp!,{v3}		;save interrupted task's return address
	stmfd	sp!,{r0-r3,ip,lr}	;save scratch register to task's stack
	stmfd	sp!,{v4}		;save interrupted task's status

;	return to ui_enter start mode
	msr	cpsr,v1			;return to interrupt mode
	ldmfd	sp!,{v1-v4,pc}		;return ui_enter

 IF Thumb = {TRUE}
	CODE16
;****************************************************************************
;		ui_exit : Interrupt Exit Routine
;****************************************************************************
;
;	extern	void	ui_exit(void);
;
|ui_exit|
	ldr r2,=ui_exit_32
	bx r2
;
;	ui_exit stack frame
;
;	+---------------+
;	|	spsr	| <---- Interrupted task processor status
;	+---------------+
;	|    r0 - r3	|
;	+---------------+
;	|	ip	|
;	+---------------+
;	|	lr	| <---- Interrupted task program count
;	+---------------+
;
	CODE32
	ALIGN
ui_exit_32
 ELSE
|ui_exit|
 ENDIF
;
	ldr	r0,c_keep_FIQ_enabled	;load address of vmc_keep_FIQ_enabled
	ldrb	r1,[r0]			;get vmc_keep_FIQ_enables
	cmp	r1,#0			;check if we keep FIQ enabled

;	interrupt disable --> IRQ & FIQ
	mrs	r2,cpsr			;get CPSR
	orreq	lr,r2,#NoInt		;IRQ & FIQ interrupt disable bit set
	orrne	lr,r2,#NoIRQInt		;IRQ disable bit set
	msr	cpsr,lr			;interrupt disable
	
;	interrupt count decrement & final interrupt exit check
	ldr	r1,c_intr_count		;initial value = 0
	ldrb	r3,[r1]			;get interrupt count
	subs	r3,r3,#1		;check final interrupt exit
	strb	r3,[r1]			;save interrupt count

;	if not the outermost interrupt exit, return
	ldmfd	sp!,{lr}		;get SPSR
	and	r0,lr,#ModeMask		;
	teqeq	r0,#SVCMode		;if outermost, check race condition
  
	msrne	spsr,lr			;if not the outermost interrupt, 
	ldmnefd	sp!,{r0-r3,ip,pc}^	;then return to interrupted mode
 

;
continue_interrupt
	stmfd	sp!,{v1,v2,lr}		;save SPSR & v1-v2
	ldr	v1,c_timer_ticks
	ldr	r0,[v1]			;get vmc_timer_ticks -> vmc_ticker arg.
	cmp	r0,#0			;timer tick interrupt issue ?
	beq	timer_check_done	;if vmc_timer_ticks = 0, done
	mov	v2,r2			;copy CPSR before interrupt disabling
	add	r3,r3,#1		;vmc_intr_count++
	strb	r3,[r1]			;
	mov	r1,#0			;clear vmc_timer_ticks
	str	r1,[v1]			;

handle_timeout
;	interrupt enable ?
	msr	cpsr,v2			;interrupt enable 
	bl	vmc_ticker		;void vmc_ticker(int ticks)
;	interrupt disable ?
	ldr	r0,c_keep_FIQ_enabled	;load address of vmc_keep_FIQ_enabled
	ldrb	r1,[r0]			;get vmc_keep_FIQ_enables
	cmp	r1,#0			;check if we keep FIQ enabled

	orreq	lr,v2,#NoInt		;IRQ & FIQ interrupt disable bit set
	orrne	lr,v2,#NoIRQInt		;IRQ disable bit set

	msr	cpsr,lr			;interrupt disable
;	check timer ticks
	mov	r1,#0			;
	swp	r0,r1,[v1]		;get & clear vmc_timer_ticks
	cmp	r0,#0			;timer tick interrupt issue ?
	bne	handle_timeout
	ldr	r1,c_intr_count		;initial value = 0
	ldrb	r3,[r1]			;get interrupt count
	sub	r3,r3,#1		;check final interrupt exit
	strb	r3,[r1]			;save interrupt count
	
timer_check_done
	ldr	v1,c_keep_FIQ_enabled	;load address of vmc_keep_FIQ_enabled
	ldrb	v2,[v1]			;get vmc_keep_FIQ_enables
	cmp	v2,#0			;check if we keep FIQ enabled

	ldmfd	sp!,{v1,v2,lr}		;get SPSR & v1-v2
	orreq	lr,lr,#NoInt		;FIQ & IRQ interrupt disable
	orrne	lr,lr,#NoIRQInt		;IRQ disable bit set


 IF Thumb = {TRUE}
	bic lr,lr,#ThumbMode		;disable thumb mode if enabled
 ENDIF
	msr	spsr,lr			;
	ldmfd	sp!,{r0-r3,ip,lr}
	subs	pc,pc,#0		;change to task mode & 
	nop				;interrupt disable
	nop
;	Changed to task mode
	ldr	r2,c_sched_needed	;get rescheduling flag
	ldrb	r0,[r2]			;
	cmp	r0,#0			;check rescheduling task
	blne	vmc_tresched		;call rescheduling procedure

;	return to the interrupted task - interrupted task stack frame
;
;	+---------------+
;	|	cpsr	|
;	+---------------+
;	|    r0 - r3	|
;	+---------------+
;	|	ip	|
;	+---------------+
;	|	lr	|
;	+---------------+
;	|	pc	|
;	+---------------+
;
	ldmfd	sp!,{lr}		;recover the CPSR when the task was
;	return to interrupted task will return if ARM or Thumb
	msr	spsr, lr
	ldmfd	sp!, {r0-r3,ip,lr,pc}^
  

	END

⌨️ 快捷键说明

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