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

📄 reentrant_irq.s

📁 T-Kernel下PCF8563的驱动程序开发
💻 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 + -