iar_reentrant_irq.s
来自「最新版IAR FOR ARM(EWARM)5.11中的代码例子」· S 代码 · 共 173 行
S
173 行
;********************************************************************************
;* *
;* Copyright (C) 2002 Oki Electric Industry Co., LTD. *
;* *
;* System Name : ML674000 *
;* Module Name : Reentrant irq handler routine *
;* File Name : reentrant_irq_handler.s *
;* Revision : 01.00 *
;* Date : 2001/12/20 initial version *
;* *
;********************************************************************************
; AREA REENTRANT_IRQ, CODE, READONLY
SECTION ICODE:CODE(2)
ARM
; <<< 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 +--+--+--@========@========@--X--+--+--+--+--+--+ r0
; r1 +--+--+--+--+--+--+--@=====@--X--+--+--+--+--+--+ r1
; r2 +--+--+--+--+--+--+--+--+--@--X--+--+--+--+--@--+ r2
; r3 +--+--+--+--+--@--+--+--+--+--X--+--+--@--+--+--+ r3
; r4 +--@========@=================O=====@=====@--+--+ r4
; r5 +--+--@=======================O==============@--+ r5
; r6-r11 +--+--+--+--+--+--+--+--+--+--O--+--+--+--+--+--+ r6-r11
; r12 +--+--+--+--+--+--+--+--+--+--X--+--+--+--+--+--+ r12
; lr_IRQ @=============== = = = = = = = = = = = =========@ lr_IRQ
; lr_USR - - - - - - - - --+--+--@=====O==@--+-- - - - - - lr_USR
;spsr_IRQ @=============== = = = = = = = = = = = =========@ spsr_IRQ
; |<------------>|<--------------------->|<------>|
; IRQ mode SYS mode IRQ mode
;
; now some standard definitions...
Mode_USR EQU 0x10
Mode_IRQ EQU 0x12
Mode_SVC EQU 0x13
Mode_SYS EQU 0x1F
I_Bit EQU 0x80
F_Bit EQU 0x40
GPCTL EQU 0xb7000000; address of GPCTL
IRQSIZE EQU 32 ; number of IRQ interrupt factor.
IRQ_BASE EQU 0x78000000; base address of registers about IRQ.
IMPORT IRQ_HANDLER_TABLE
EXPORT irq_handler
;**********************************************************************
;* IRQ Handler *
;* Function : void IRQ_Handler(void) *
;* Parameters *
;* input : nothing *
;* output : nothing *
;**********************************************************************
irq_handler
SUB lr, lr, #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 r1-r6,lr_IRQ(r14).
STMFD sp!, {r1-r6, lr}
;; spsr_IRQ is saved to saved_spsr_irq(r4).
;; if IRQ handler is reentered, spsr_IRQ is overwritten.
MRS r4, 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 r4, #I_Bit
LDMNEFD sp!, {r0-r5, pc}^
;; IRQ number is got from IRN register. IRQ number is saved to irn(r6).
;; after the value of IRN register is read,
;; the bit of CIL register corresponding to interrupt level is set.
MOV r5, #IRQ_BASE ; IRQ_BASE(0x78000000) is saved to irq_base(r5).
LDR r6, [r5, #0x14] ; IRQ number is saved to irn(r6).
;; 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 r4, #F_Bit ; FIQ is available ?
MOVEQ r3, #Mode_SVC ; available
MOVNE r3, #Mode_SVC|F_Bit; not abailable
MSR cpsr_c, r3 ; 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 r6, #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 r1-r3 change.
;; registers which need to be saved are r0, r12 and lr_USR.
STMFD sp!, {r0, r12, lr}; R0, 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 r1, =IRQ_HANDLER_TABLE
;; branch to handler corresponding to interrupt's factor
BL BRANCH_TO_HANDLER
LDMFD sp!, {r0, r12, lr}; R0, 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 r4, #F_Bit; FIQ is available ?
MOVEQ r3, #Mode_IRQ|I_Bit; available
MOVNE r3, #Mode_IRQ|I_Bit|F_Bit; not abailable
MSR cpsr_c, r3 ; change to IRQ mode and disable IRQ
MSR spsr_cf, r4 ; 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 r2, [r5, #0x28]; arbitrary value is written to
; CILCL register.
;; saved registers are restored, and control is returned from IRQ.
LDMFD sp!, {r1-r6, 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 r2, [r1, r6, lsl #2];
BX r2 ; branch to handler corresponding to
; interrupt's factor
; end of BRANCH_TO_HANDLER
END
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?