一个DataAbort异常的触发过程:

///////////////////////////

///xxxx.inc

_STACK_BASEADDRESS EQU 0x33ff8000

_MMUTT_STARTADDRESS EQU 0x33ff8000

_ISR_STARTADDRESS EQU 0x33ffff00


///xxx.s

         MACRO

$HandlerLabel HANDLER $HandleLabel


$HandlerLabel

    sub    sp,sp,#4    ;decrement sp(to store jump address)

    stmfd    sp!,{r0}    ;PUSH the work register to stack(lr does t push because it 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

HandlerPabort HANDLER HandlePabort


HandlerPabort HANDLER HandlePabort 展开:
{
HandlerPabort
sub sp,sp,#4       ;decrement sp(to store jump address)
stmfd sp!,{r0}      ;PUSH the work register to stack(lr does''t push because it return to original address)

ldr r0,=$HandlePabort  ;load the address of HandleXXX to r0
ldr r0,[r0]        ;load the contents(service routine start address) of Handler function
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)
}



///xxx.s

/* ^ 其实就是 MAP ,这段程序的意思是,从 _ISR_STARTADDRESS

开始,预留一个变量,每个变量一个标号,预留的空间为 4个字节,也就是 32BIT

,其实这里放的是真正的C写的处理函数的地址,说白了,就是函数指针*/

^ _ISR_STARTADDRESS ; _ISR_STARTADDRESS=0x33FF_FF00

HandleReset # 4

HandleUndef # 4

HandleSWI # 4

HandlePabort # 4

HandleDabort # 4

HandleReserved # 4

HandleIRQ # 4

HandleFIQ # 4

///////////////////////////

xxxx.c

#define _ISR_STARTADDRESS 0x33ffff00

#define pISR_PABORT (*(unsigned *)(_ISR_STARTADDRESS+0xc))

pISR_PABORT=(unsigned)HaltPabort; //给PABORT中断入口函数指针赋值。

【 *PABORTFUNC = HaltPabort 】

/////////////////////

中断触发时:

1 -- ldr r0,=HandlePabort

2 -- (*(unsigned *)HandlePabort) 即是pISR_PABORT

3 -- pISR_PABORT 即是异常处理函数HaltPabort

4 -- POP 出栈时弹出的是HandlePabort 到PC