First, some definitions are given:
2440addr.inc
Intoffset EQU 0x4a000014 ; Interruot Request Source Offset
Option.inc
_isr_startaddress 0x33ffff00
2440init.s
macro$handlerlabel HANDLER $HandleLabel $handlerlabel Sub sp,sp,#4 ; Decrement sp (to store jump address) stmfd sp!,{r0} return to original address) Ldr r0,=$HandleLabel ; load the address of handlexxx to R0 ldr r0,[r0] ; load the Contents (Service routine start address) of handlexxx str r0,[sp,#4] ; Store the Contents (ISR) of handlexxx to stack ldmfd sp!, {r0,pc} ; POP the Work register and PC (jump to ISR) MEND
Below to get to the chase:
2440init.s
PRESERVE8 area reset,code,readonly ENTRY EXPORT __entry__entryresetentry b resethandler; /c0>0x0b handlerundef; handler forUndefined mode b handlerswi; handler forSWI interrupt b handlerpabort; handler forPabort b handlerdabort; handler forDabort B. ; reserved b HANDLERIRQ; handler forIRQ interrupt b Handlerfiq; handler forFIQ interrupt B enterpwdn; Must be @0x20.... Handlerirq HANDLER Handleirq........; Setup IRQ Handler//Create an interrupt tableLDR R0,=handleirq; This routine isneeded LDR R1,=ISRIRQ;ifthere isn t'Subs PC,LR, #4'At0x18,0x1cstr r1,[r0] ... .... .....^ _isr_startaddress;0x33ffff00Handlereset #4Handleundef #4HANDLESWI #4Handlepabort #4Handledabort #4handlereserved #4HANDLEIRQ #4Handlefiq #4;0x33ffff1c; intvectortable;@0x33ff_ff20handleeint0 #4;0x33ffff20HandleEINT1 #4HandleEINT2 #4.................................
HandleUART1 # 4; 0x33ffff7c
.................................
The UART is an external interrupt that goes fiq.
External Interrupt--B Handlerfiq;
See Code discovery HANDLERFIQ the macro definition in Init.s, and then get:
// expand macro Handlerirq HANDLER HANDLEIRQ handlerirq Sub sp,sp,# 4 ;d Ecrement sp (to the store jump address) Stmfd sp !,{r0};P USH the work register to stack (LR does t push because it return to original address) Ldr R0, = $HandleIRQ; load the address of Handl Exxx to R0 Ldr r0,[r0]; load the contents (service routine start address) of Handlexxx str r0,[sp,# "; Store the contents (ISR) of handlexxx to Stack ldmfd sp !,{r0,pc}; POP the Work register and PC (jump to ISR)
You can see that the HANDLERIRQ is a standard interrupt handling process (which is being encapsulated by using macros): Save the scene first, and then jump to handleirq , from handleirq returns to the scene after returning.
HANDLEIRQ is actually a function pointer that we can point to a handler function in the program. Here we point to isrirq , we read handleeint0 , so that we get the interrupt entry HandleUART1 for the century. by ldmfd sp !,{r8-r9,pc} , we jump into the handleuart1 The corresponding actual interrupt handler function (see the following analysis).
2440init.s
ISRIRQ Sub sp,sp,#4 for PC stmfd sp!,{r8- R9} ldr r9,=intoffset ldr r9,[r9] ldr r8,=HandleEINT0 Add R8,R8,R9,LSL #2 ; r8=r8+ (r9*4) Ldr r8,[r8] Str r8,[sp,#8 ldmfd sp!,{r8-r9,pc}
It says, " through ldmfd sp!,{r8-r9,pc}, we jump into the actual interrupt handler for the HandleUART1." How to jump, in the code, we implemented and bound the HandleUART1 processing function uart1_txrxint:
//2440addr.h#definePisr_uart1 (* (unsigned *) (_isr_startaddress+0x7c))
//2440LIB.Cpisr_uart1=(unsigned) uart1_txrxint;externUnsignedCharuartbuf1[ the];void__IRQ Uart0_txrxint (void)//only receive interrupts are handled here{unsignedChar*pbuf =UartBuf1; if(RSUBSRCPND & Bit_sub_rxd0)//Receive interrupts{Rintsubmsk|=bit_sub_rxd0; while((rufstat0&0x3f)) { *pbuf++ =rURXH0; } *pbuf =' /'; Rintsubmsk&= ~bit_sub_rxd0; RSRCPND|=bit_uart0; RINTPND|=bit_uart0; Rintsubmsk&= ~(BIT_SUB_TXD0); }}
Arm exception---A UART interrupt triggering process: