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

📄 interrupt.s

📁 AT91所有开发板的资料 AT91所有开发板的资料
💻 S
字号:
        TTL     Angel assembler support routines                    > suppasm.s        ; ---------------------------------------------------------------------        ; This source files holds the general assembler routines        ; needed by Angel.        ;        ; $Revision: 1.2 $        ;   $Author: mwelsh $        ;     $Date: 1999/06/15 14:13:40 $        ;        ; Copyright Advanced RISC Machines Limited, 1995, 1997, 1998.        ; All Rights Reserved        ;        ; ---------------------------------------------------------------------        GET     listopts.s              ; standard listing control        GET     lolevel.s               ; generic ARM definitions        GET     macros.s                ; standard assembler support        GET     target.s                ; target specific definitions        GET     taskmacs.s              ; exception/task mgmt support        ; ---------------------------------------------------------------------        AREA    |C$$Code$$InterruptSupport|,CODE,READONLY        KEEP        [       ({CONFIG} = 26)        ASSERT  (1 = 0) ; This code has been written for 32bit mode only        ]        ; ---------------------------------------------------------------------        IMPORT  angel_IntHandler        ; Table of Interrupt handlers        IMPORT  Angel_GlobalRegBlock        IMPORT  angel_GhostCount	IF DEBUG = 1	    IMPORT  angel_InterruptCount	ENDIF        IMPORT  angel_CurrentTask        IMPORT  HandlerSWI        IMPORT  Angel_StackBase        IMPORT  __rt_asm_fatalerror        IMPORT  Angel_Needschedule        IMPORT  angel_SelectNextTask        IMPORT  angel_QueueTask	        EXPORT  angel_FIQInterruptHandler        EXPORT  angel_IRQInterruptHandler                IMPORT  HandlerUndef	; to disable the ability to use Angel_Signal from within an ISR, and speed	; up interrupt response very slightly, set this to 0.SIGNAL_FROM_ISR	EQU	1        ; ---------------------------------------------------------------------        ; The following is a word which gets set to either ADP_CPU_LE or        ; ADP_CPU_BE at assemble time.  It can then be used by Angel to        ; tell the host what the endianess of the system is.        EXPORT  angel_Endianessangel_Endianess        IF {ENDIAN} = "big"          DCD ADP_CPU_BE          DCD ADP_CPU_BigEndian        ELSE          IF {ENDIAN} = "little"            DCD ADP_CPU_LE            DCD 0          ELSE            ! ERROR - could not detect endianess          ENDIF        ENDIF                ; ---------------------------------------------------------------------        angel_FIQInterruptHandler      IF HANDLE_INTERRUPTS_ON_FIQ = 0                ;; we're not supposed to be handling this, so don't        SUBS  pc, lr, #4              ELSE        ; Nasty case code - check to see if we have interrupted the first        ; few instructions of the SWI handler or UND handler!!!        ; which includes the vectors themselves !!!  This is necessary        ; because on entry to SWI and UNDEF handlers FIQ is still enabled.        ; It is therefore highly recommendsed that FIQ is not used to        ; handle Angel Device interrupts, as this is a significant overhead        ; and is also really quite unpleasant!        STMFD sp!, {r0}       ; need r0 as temp -- save it.                CMP   lr, #0x1c       ; 0x1c is the last vector. If LR is less than                                ; this, we're in trouble...        BCC   ReallyNastyCase ; taken if FIQ from Reset, Und, Swi, Pre/Dat Abort                                ; but not from IRQ/FIQ        LDR   r0, =HandlerSWI        CMP   lr, r0        BCC   CheckUNDHandler ; interrupted pc < HandlerSWI        ADD   r0, r0, #60        CMP   lr, r0        BHI   CheckUNDHandler ; interrupted pc >> HandlerSWI        B     ReallyNastyCaseCheckUNDHandler       IF MINIMAL_ANGEL <> 0        B     ContinueFIQHandler   ; don't worry about UND on Minimal                                   ; as we don't manage breakpoints here.       ELSE                LDR   r0, =HandlerUndef        CMP   lr, r0        BCC   ContinueFIQHandler   ; interrupted pc < HandlerUndef        ADD   r0, r0, #60        CMP   lr, r0        BHI   ContinueFIQHandler   ; interrupted pc >> HandlerUndef               ENDIFReallyNastyCase        ; This is the nasty case - ignore the interrupt        ; and resume the SWI Handler with IRQ and FIQ disabled.        EnsureFIQDisabled spsr, r3                LDMFD sp!, {r0}       ; restore our temp register,        SUBS  pc, lr, #4      ;  and return...ContinueFIQHandler        LDMFD sp!, {r0}       ; restore our temp register,        EXCEPTENTRY FIQmode, Angel_GlobalRegBlock + \                        (RB_Interrupted * Angel_RegBlockSize)              IF :DEF: R10_IS_SL        ; Set up sl for the appropriate stack (depends on mode). This is        ; NOT a banked register, so it won't be remembered anyway.        LDR     sl, =Angel_StackBase        LDR     sl, [sl]        ADD     sl, sl, #Angel_FIQStackLimitOffset      ENDIF        B       AngelInterruptHandler              ENDIF   ; HANDLE_INTERRUPTS_ON_FIQ <> 0        ; ---------------------------------------------------------------------              IF :DEF: R10_IS_SLirqstackoverflow        FatalError "IRQ: Stack Overflow."      ENDIF                        angel_IRQInterruptHandler      IF HANDLE_INTERRUPTS_ON_IRQ = 0        ;; we're not supposed to be handling this, so don't        SUBS  pc, lr, #4              ELSE                EXCEPTENTRY IRQmode, Angel_GlobalRegBlock + \                        (RB_Interrupted * Angel_RegBlockSize)      IF :DEF: R10_IS_SL        ; The stack limit is not used in standard Angel: this code is here to        ; show where and how to set up SL.        ;        ; Set up sl for the appropriate stack (depends on mode). This is        ; NOT a banked register, so it won't be remembered anyway.        LDR     sl, =Angel_StackBase        LDR     sl, [sl]        ADD     sl, sl, #Angel_IRQStackLimitOffset      ENDIF        ;; fall through...        ;B      AngelInterruptHandler              ENDIF   ; HANDLE_INTERRUPTS_ON_IRQ <> 0        ; ---------------------------------------------------------------------AngelInterruptHandler      IF DEBUG <> 0        IMPORT  Angel_DebugLog        MOV     r1, #0        MOV     r2, #3        BL      Angel_DebugLog      ENDIF           IF :DEF: R10_IS_SL        ; standard overflow check         CMP     sp, sl        BLLO    irqstackoverflow      ENDIF      IF DEBUG = 1        LDR     r1, =angel_InterruptCount        LDR     r0, [r1]        ADD     r0, r0, #1        STR     r0, [r1]      ENDIF        GetSrc      IF :DEF: THREE_ARG_GETSOURCE	GETSOURCE r0, r1, r2              ; Get the interrupt vector index in r0      ELSE	GETSOURCE r0, r1                  ; Get the interrupt vector index in r0      ENDIF        CMN     r0, #1                    ; Check for Ghost Interrupt        BEQ     GhostInterrupt            ; It's a Ghost        CMP     r0, #DE_NUM_INT_HANDLERS  ; Check if a valid source index        BGE     UnrecognisedSource        ; Unrecognised source        ; The array angel_IntHandler contains pairs (fn, dat) of function        ; addresses and data values to pass to those functions. Calculate        ; the offset into the table and load the values into r1 (data) and        ; r4 (function addr).        ; The function will be called as:        ;         ;   (void) handler(vector_num, data, empty_stack)        ;             r4     r0         r1      r2        ;                 LDR     r2, =angel_IntHandler     ; Reference the handlers vector        ADD     r2, r2, r0, LSL #3        ; r2 = angel_IntHandler + r0 * 8                LDMIA   r2, {r4, r5}              ; load the required func pointer ...        MOV     r1, r5                    ;   and data into r4 and r1        ; r2, r5 are now dead.                TEQ     r4, #0        BEQ     UnrecognisedSource        ; No handler attached for source        ; We can now call the APCS-3 handler for this source:                MOV     r2, sp                    ; return this mode's stack here                                          ; when we're finished.              IF DEBUG <> 0        MOV     fp, #0                    ; start of call-frame -- for debug backtrace      ENDIF                ; r0 = interrupt vector index, set up above        ; r1 = data from table, set up above        ; r2 = empty_stack (stack is [assumed to be] currently empty)        ; r3 = 0 [not used]        ;        ; r4 = address of Interrupt handler, which may return but        ;      WON'T return if it calls the serialiser.        ; r5 - r9 undefined.        ;         ; fp(r11) = 0 => base of frame set        ; sl = Limit for IRQ/FIQ stack -- calculated above        ; sp = [probably at base of IRQ/FIQ stack]        ; It is assumed that the handler function called will execute        ; within the interrupt handler stack allocation, and the code        ; will not manipulate the interrupt mask status, or the SPSR        ; register:        LDR     lr, =ReturnFromIntHandler  ; generate return address        MOV     pc, r4                     ; call handler function      IF ASSERT_ENABLED <> 0badintmode        FatalError "Interrupt return in USR mode!\n"      ENDIF                UnrecognisedSource        NOP                             ; this way we get two labels in the debugger!        ;; fall through to...        ReturnFromIntHandler        ; We will only get here if the interrupt handler did not call        ; SerialiseTask to perform some 'hard' work.                      IF ASSERT_ENABLED <> 0        MRS     r0, CPSR        AND     r0, r0, #ModeMaskUFIS        CMP     r0, #USRmode :AND: ModeMaskUFIS        BEQ     badintmode      ENDIF      IF SIGNAL_FROM_ISR <> 0 :LAND: MINIMAL_ANGEL = 0        LDR	r0, =Angel_Needschedule	LDR	r0, [r0]	CMP	r0, #0	BNE	Angel_ScheduleFromISR      ENDIF        	; We are returning to interrupted code, fetch interrupted regblock.        LDR     r0, =Angel_GlobalRegBlock + \                        (RB_Interrupted * Angel_RegBlockSize)      IF MINIMAL_ANGEL = 0        IMPORT  angel_StartTask        B       angel_StartTask      ELSE        IMPORT  R13ContextLookuptable        EXCEPTEXIT      ENDIF        ; And now the interuptee executes in whatever mode it was in ..        ; ****************************************************************        ;        ; void Angel_ScheduleFromISR()        ;	; Called at the tail end of the ISR when it has been determined that	; we must enter the scheduler to reschedule the tasks, rather than	; simply return to the interrupted task.	;         ; -------------------------------------------	;        ; On Entry:        ;    r0 - pointer to the Angel_Needschedule flag	;    CPSR in IRQ or FIQ mode, Angel interrupts disabled.	;    	; On Exit:	;    << this code exits via the scheduler >>        ; 	;    The 'need schedule' flag is reset; the processor in SVC mode	; with interrupts disabled.	;        ; -------------------------------------------              IF SIGNAL_FROM_ISR <> 0 :LAND: MINIMAL_ANGEL = 0Angel_ScheduleFromISR	; get us out of IRQ/FIQ into SVC mode        MRS     r0, CPSR	BIC	r0, r0, #ModeMask	ORR	r0, r0, #SVCmode + AngelInterruptMask	MSR	cpsr_c, r0	; Push the interrupted regblock into the task save area        LDR     r0, =Angel_GlobalRegBlock + \                        (RB_Interrupted * Angel_RegBlockSize)	LDR	r1, =angel_CurrentTask	LDR	r1, [r1]	BL	angel_QueueTask	; Enter the scheduler.	B	angel_SelectNextTask      ENDIF                ; ****************************************************************        ;	; void GhostInterrupt(void) 	; -------------------------	;        ; It is possible to get ghost interrupts - ignore these, unless        ; too many of them stack up, in which case we fatal error it.        ;        ; -------------------------------------------	;	; On Entry:        ;    r1 = &angel_GhostInterrupt        ;	; On Exit:	;    ghost count incremented; return via normal ISR return unless	; count >= 5, in which case invoke a fatal error.	;         ; -------------------------------------------        ;GhostInterrupt        LDR     r1, =angel_GhostCount        LDR     r0, [r1]        ADD     r0, r0, #1        CMP     r0, #5        STR     r0, [r1]        BLT     ReturnFromIntHandlerTooManyGhosts        FatalError "Too Many Ghost Interrupts\n"                                        END     ; EOF suppasm.s

⌨️ 快捷键说明

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