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

📄 intirqsk.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
;       ===========
;
;       INTIRQSK.S - Interrupt Handler for IRQs with sw stack checking
;
;
;       Revision History
;       ================
;
;       Version    Date       Author               Reason for Change
;       1.0        14/03/96   Samsung & P.Cumming  Initial Version
;                                                  Derived from beta
;                                                  INTERRUP.S.  
;	1.1        03/06/96   P.Cumming            vmc_keep_FIQ_enable added
;	1.2        30/09/96   P.Cumming            ui_enter_i check IRQ/FIQ race
;
;	This file contains modified versions of the ui_enter & ui_exit
;	procedures ui_enter_i & ui_exit_i for IRQs with sw stack checking
;	on.  This change is required because the stack limit register
;	r10 needs to be loaded at the start of the interrupt with the 
;	correct IRQ stack limit.  This needs to be pushed and popped of
;	the stack. 
;	This is not required for FIQs as r10 (stack limit) is banked.
;                                                
;*******************************************************************
;****************************************************************************
;			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

	EXPORT	|ui_enter_i|
	EXPORT	|ui_exit_i|

	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_i : Interrupt Enter Routine
;****************************************************************************
;
;	extern	void	ui_enter_i(void);
;
|ui_enter_i|
;
;	ui_enter stack frame
;
;	+---------------+
;	|    v1 - v5	| <---- sp
;	+---------------+
;	|	lr	|
;	+---------------+
;	|	spsr	| <---- ui_enter start part sp
;	+---------------+
;	|    r0 - r3	|
;	+---------------+
;	|	sl	|
;	+---------------+
;	|	ip	|
;	+---------------+
;	|	lr	|
;	+---------------+
;
	stmfd	sp!,{v1-v5,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-v5,pc}		;return ui_enter_i

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-v5,pc}		;return ui_enter_i

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

	
;	make task's interrupt stack frame
;
;	+---------------+
;	|	cpsr	|
;	+---------------+
;	|    r0 - r3	|
;	+---------------+
;	|	sl	|
;	+---------------+
;	|	ip	|
;	+---------------+
;	|	lr	|
;	+---------------+
;	|	pc	|
;	+---------------+
;
	stmfd	sp!,{v3}		;save interrupted task's return address
	stmfd	sp!,{r0-r3, v5, 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-v5,pc}		;return ui_enter

 IF Thumb = {TRUE}
	CODE16
;****************************************************************************
;		ui_exit_i : Interrupt Exit Routine
;****************************************************************************
;
;	extern	void	ui_exit(void);
;
|ui_exit_i|
	ldr r2,=ui_exit_32
	bx r2
;
;	ui_exit stack frame
;
;	+---------------+
;	|	spsr	| <---- Interrupted task processor status
;	+---------------+
;	|    r0 - r3	|
;	+---------------+
;	|	sl	|
;	+---------------+
;	|	ip	|
;	+---------------+
;	|	lr	| <---- Interrupted task program count
;	+---------------+
;
	CODE32
	ALIGN
ui_exit_32
 ELSE
|ui_exit_i|
 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,r10,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,r10,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	|
;	+---------------+
;	|	sl	|
;	+---------------+
;	|	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,r10,ip,lr,pc}^ ;return to the interrupted task

  

	END

⌨️ 快捷键说明

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