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

📄 reentrant_irq.s

📁 一些典型的阿arm嵌入式应用程序集锦!
💻 S
字号:

#;********************************************************************************
#;*                                                                              *
#;*    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

#;   <<< 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
#; 

	.INCLUDE	"define.s"
	
.EQU	IRQSIZE,           32
.EQU	IRQ_BASE,          0x78000000

#;; definition of alias of registers
sp_IRQ               .req      sp /* r13 */
lr_IRQ               .req      lr /* r14 */
sp_USR               .req      sp /* r13 */
lr_USR               .req      lr /* r14 */
irq_handler_table    .req      r1 /* address of irq_handler_table is saved. */
cil_clear            .req      r2 /* value of this is set to CILCL register. */
address_of_handler   .req      r2 /* address of handler corresponding to */
                                /* intrrupt factor is sabed. */
cpsr_tmp             .req      r3 /* */
saved_spsr_irq       .req      r4 /* value of spsr_irq is saved. */
irq_base             .req      r5 /* base address of registers about IRQ is saved. */
irn                  .req      r6 /* value of IRN register is saved. */

        .extern  IRQ_HANDLER_TABLE
        .extern  SWI_irq_en
        .global  IRQ_Handler
        .global  irq_en
        .extern  irq_en
        .global  irq_dis
        .global  get_irq_state

#;**********************************************************************
#;*  IRQ Handler                                                       *
#;*  Function : void IRQ_Handler(void)                                 *
#;*      Parameters                                                    *
#;*          input  : nothing                                          * 
#;*          output : nothing                                          *
#;**********************************************************************
IRQ_Handler:
        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 r1-r6,lr_IRQ(r14).
        STMFD   sp_IRQ!, {r1-r6, 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

        #;; 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     irq_base, #IRQ_BASE     /* IRQ_BASE(0x78000000) is saved to irq_base(r5). */
        LDR     irn, [irq_base, #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     saved_spsr_irq, #F_Bit	/* FIQ is available ? */
        MOVEQ   cpsr_tmp, #Mode_SYS     /* available */
        MOVNE   cpsr_tmp, #Mode_SYS | 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 r1-r3 change.
        #;; registers which need to be saved are r0, r12 and lr_USR.
        STMFD   sp_USR!, {r0, r12, lr_USR}	/* 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     irq_handler_table, =IRQ_HANDLER_TABLE

        #;; branch to handler corresponding to interrupt's factor
        BL      BRANCH_TO_HANDLER

        LDMFD   sp_USR!, {r0, r12, lr_USR}	/* 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     saved_spsr_irq, #F_Bit					/* FIQ is available ? */
        MOVEQ   cpsr_tmp, #Mode_IRQ | I_Bit				/* available */
        MOVNE   cpsr_tmp, #Mode_IRQ | I_Bit | 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!, {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     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
        MOV     pc, 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
        MOV     pc, 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
        MOV     pc, lr
#; end of get_irq_state 

⌨️ 快捷键说明

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