?? reentrant_irq.s
字號:
;********************************************************************************
;* *
;* Copyright (C) 2001-2002 Oki Electric Industry Co., LTD. *
;* *
;* System Name : uPLAT series *
;* Module Name : Reentrant irq handler routine *
;* File Name : reentrant_irq_handler.s *
;* Revision : 01.10 *
;* Date : 2001/12/20 initial version *
;* 2002/12/02 add checking 'I' bit of spsr *
;* *
;********************************************************************************
AREA REENTRANT_IRQ, CODE, READONLY
; <<< bit field of status registers (CPSR, SPSR) >>>
; 31 30 29 28 7 6 5 4 3 2 1 0
; +---+---+---+---+-----+---+---+---+---+---+---+---+---+
; | N | Z | C | V | - - | I | F | T | M4| M3| M2| M1| M0|
; +---+---+---+---+-----+---+---+---+---+---+---+---+---+
; M0-M4 10010 : IRQ mode
; 11111 : SYSTEM mode
; T 0 : ARM mode
; 1 : THUMB mode
; F 0 : FIQ is allowed
; 1 : FIQ is not allowed
; I 0 : IRQ is allowed
; 1 : IRQ is not allowed
; N,Z,C,V : condition flags. flags change with the results of ALU.
;
;
; <<< use situation of registers >>>
; IRQ change to handler change to IRQ
; start SYS mode start end IRQ mode end
; --|--------------|-----------|-----|-----|--------|-->
; r0 +--+--+--W========R========R--X--+--+--+--+--+--+ r0
; r1 +--+--+--+--+--+--+--W=====R--X--+--+--+--+--+--+ r1
; r2 +--+--+--+--+--+--+--+--+--@--X--+--+--+--+--@--+ r2
; r3 +--+--+--+--+--@--+--+--+--+--X--+--+--@--+--+--+ r3
; r4 +--W========R=================O=====R=====R--+--+ r4
; r5 +--+--W==R====================O==============R--+ r5
; r6-r11 +--+--+--+--+--+--+--+--+--+--O--+--+--+--+--+--+ r6-r11
; r12 +--+--+--+--+--+--+--+--+--+--X--+--+--+--+--+--+ r12
; lr_IRQ @=============== = = = = = = = = = = = =========R lr_IRQ
; lr_USR - - - - - - - - --+--+--W=====O==R--+-- - - - - - lr_USR
;spsr_IRQ ================ = = = = = = = = = = = =========R spsr_IRQ
; |<------------>|<--------------------->|<------>|
; IRQ mode SYS mode IRQ mode
;
INCLUDE define.s ; common definitions
;; definition of alias of registers
sp_IRQ RN sp ; r13
lr_IRQ RN lr ; r14
sp_USR RN sp ; r13
lr_USR RN lr ; r14
irn RN r0 ; value of IRN register is saved.
irq_handler_table RN r1 ; address of irq_handler_table is saved.
cil_clear RN r2 ; value of this is set to CILCL register.
address_of_handler RN r2 ; address of handler corresponding to
; intrrupt factor is sabed.
cpsr_tmp RN r3 ;
saved_spsr_irq RN r4 ; value of spsr_irq is saved.
irq_base RN r5 ; base address of registers about IRQ is saved.
IMPORT IRQ_HANDLER_TABLE
IF :DEF: |ads$version|
IMPORT SWI
REQUIRE SWI ; SDT don't support "require" directive
ENDIF
EXPORT IRQ
EXPORT irq_en
EXPORT irq_dis
EXPORT get_irq_state
;**********************************************************************
;* IRQ Handler *
;* Function : void IRQ(void) *
;* Parameters *
;* input : nothing *
;* output : nothing *
;**********************************************************************
IRQ
ENTRY
SUB lr_IRQ, lr_IRQ, #4; construct the return address
;; registers which may be overwritten are saved.(IRQ mode)
;; r0-r5 : these are used in this handler.
;; lr_IRQ(r14) : if IRQ handler is reentered, this is overwritten.
;; registers which may be overwritten are r0-r5,lr_IRQ(r14).
STMFD sp_IRQ!, {r0-r5, lr_IRQ}
;; spsr_IRQ is saved to saved_spsr_irq(r4).
;; if IRQ handler is reentered, spsr_IRQ is overwritten.
MRS saved_spsr_irq, spsr
;; check 'I' bit of spsr
;; please refer to the following section of FAQ at the ARM website for details.
;; FAQ - ARM Cores
;; 4. Interrupt behaviour:
;; - What happens if an interrupt occurs as it is being disabled?
TST saved_spsr_irq, #I_Bit
LDMNEFD sp_IRQ!, {r0-r5, pc}^
;; IRQ number is got from IRN register. IRQ number is saved to irn(r0).
;; after the value of IRN register is read,
;; the bit of CIL register corresponding to interrupt level is set.
MOV irq_base, #IRQ_BASE ; IRQ_BASE(0x78000000) is saved to irq_base(r5).
LDR irn, [irq_base, #0x14] ; IRQ number is saved to irn(r0).
;; mode is changed into SYS mode. and IRQ is enabled.
;; if IRQ is enabled before a CIL register is set,
;; this program does not operate appropriately.
;; in SYS mode, USR mode registers are used.
TST saved_spsr_irq, #F_Bit; FIQ is available ?
MOVEQ cpsr_tmp, #Mode_SYS ; available
MOVNE cpsr_tmp, #Mode_SYS:OR:F_Bit; not abailable
MSR cpsr_c, cpsr_tmp ; change to SYS mode and enable IRQ
;; check IRQ number
;; if IRQ number is invalid(irn > IRQSIZE),
;; this routine doesn't branch to handler corresponding to interrupt's factor.
CMP irn, #IRQSIZE
BCS LABEL
;; USR mode registers which may be overwritten
;; and registers which are not saved by callee are saved.
;; -- USR mode registers which may be overwritten --
;; lr_USR(r14) : this is overwritten.
;; -- registers which is not saved by callee --
;; r0-r3,r12 : these aren't saved by callee.
;; but there is no influence even if values of r0-r3 change.
;; registers which need to be saved are r12 and lr_USR.
STMFD sp_USR!, {r12, lr_USR}; R12 and lr_USR(r14) are saved.
;; address of IRQ_HANDLER_TABLE is got.
;; address of IRQ_HANDLER_TABLE is saved to irq_handler_table(r1).
LDR irq_handler_table, =IRQ_HANDLER_TABLE
;; branch to handler corresponding to interrupt's factor
BL BRANCH_TO_HANDLER
LDMFD sp_USR!, {r12, lr_USR}; R12 and link register is restored.
LABEL
;; mode is changed to IRQ mode. and IRQ is disabled.
;; if IRQ is still being allowed after CIL register is cleared,
;; this program does not operate appropriately.
TST saved_spsr_irq, #F_Bit; FIQ is available ?
MOVEQ cpsr_tmp, #Mode_IRQ:OR:I_Bit; available
MOVNE cpsr_tmp, #Mode_IRQ:OR:I_Bit:OR:F_Bit; not abailable
MSR cpsr_c, cpsr_tmp ; change to IRQ mode and disable IRQ
MSR spsr_cf, saved_spsr_irq ; spsr_IRQ is restored.
;; the most significant '1' bit of CIL register is cleared.
;; if arbitrary value is written in CILCL register,
;; the most significant '1' bit of CIL register will be cleared.
STR cil_clear, [irq_base, #0x28]; arbitrary value is written to
; CILCL register.
;; saved registers are restored, and control is returned from IRQ.
LDMFD sp_IRQ!, {r0-r5, pc}^
; end of IRQ_Handler
;**********************************************************************
;* Branch to handler corresponding to interrupt's factor. *
;* Handler doesn't return to this function. *
;* Handler directry returns to IRQ_Handler. *
;* Function : void BRANCH_TO_HANDLER(void) *
;* Parameters *
;* input : nothing *
;* output : nothing(This function doesn't return.) *
;**********************************************************************
BRANCH_TO_HANDLER
;; address of handler and information that handler is ARM or THUMB
;; is saved at irq_handler_table + irn*4.
LDR address_of_handler, [irq_handler_table, irn, lsl #2];
BX address_of_handler ; branch to handler corresponding to
; interrupt's factor
; end of BRANCH_TO_HANDLER
;**********************************************************************
;* Enable IRQ *
;* Function : UWORD irq_en(void) *
;* Parameters *
;* input : nothing *
;* output : IRQ state before change *
;* 0 : Enable *
;* others : Disable *
;**********************************************************************
irq_en
SWI SWI_IRQ_EN
BX lr
; end of irq_en
;**********************************************************************
;* Disable IRQ *
;* Function : UWORD irq_dis(void) *
;* Parameters *
;* input : nothing *
;* output : IRQ state before change *
;* 0 : Enable *
;* others : Disable *
;**********************************************************************
irq_dis
SWI SWI_IRQ_DIS
BX lr
; end of irq_dis
;**********************************************************************
;* Get IRQ State *
;* Function : UWORD get_irq_state(void) *
;* Parameters *
;* input : nothing *
;* output : IRQ state *
;* 0 : Enable *
;* others : Disable *
;**********************************************************************
get_irq_state
MRS r0, CPSR ; get CPSR
AND r0, r0, #I_Bit
BX lr
; end of get_irq_state
END ; end of reentrant_irq_handler.s
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -