关于44b0的中断调用的问题

关于44b0的中断调用的问题:

我在网上下了一个源码,在阅读的过程中,我的理解来说。希望各位指教下,具体是这样的:

下面的代码因为44b0中的各个中断类型相似的,所以只是以timer为例。

在init.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 doest 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
然后有一个vector_branch
 ......
entry
 ......
VECTOR_BRANCH
 ......
 ldr pc,=HandlerTIMER1
 ......
IRQ_Handler
 IMPORT ISR_IrqHandler
 STMFD sp!, {r0-r12, lr}
 BL ISR_IrqHandler
 LDMFD sp!, {r0-r12, lr}
 SUBS pc, lr, #4

 EXPORT IRQ_Handler
 ......
HandlerTIMER1 HANDLER HandleTIMER1
 ......
 ;Setup IRQ handler
     ldr     r0,=HandleIRQ ;This routine is needed
     ldr     r1,=IRQ_Handler ;=IsrIRQ,if there isn't 'subs pc,lr,#4' at 0x18,

0x1c
     str     r1,[r0]

然后,在另外的文件isr_address.s中有下面的语句:
 
 AREA    ISR_STARTADDRESS, DATA, NOINIT
 ......
 EXPORT HandleTIMER1
 ......
 HandleTIMER1 SPACE 4
 ......
 END

另外,在scat_ram.scf中对存储空间的分配有:
RAM_LOAD 0x00008000
{
    RAM_EXEC 0x00008000
    {
        init.o (init, +First)
        * (+RO)
    }

    RAM 0x0x00100000
    {
        * (+RW,+ZI)
    }

    HEAP +0 UNINIT
    {
        heap.o (+ZI)
    }

    STACKS 0x0020000 UNINIT
    {
        stack.o (+ZI)
    }

    ISR_STARTADDRESS 0x0020000
    {
     isr_address.o (+ZI)
    }

}
在uHALr_InterruptRequestInit()中,有定义下面的东西
void uHALr_InterruptRequestInit()
{
 pISR_UNDEF= (unsigned) DebugUNDEF;
 pISR_SWI= (unsigned) DebugSWI;
 ......
 SetISR_Interrupt(INT_TIMER1_OFFSET,OSTimeTick,NULL);
 ......
 pISR_ADC= (unsigned) BreakPoint;
 pISR_RTC= (unsigned) BreakPoint;
}
然后,在文件isr.c和isr.h中定义下面的函数和数据结构。
void (*InterruptHandlers[MAXHNDLRS])(void)={NULL,};
有函数
void SetISR_Interrupt(int vector, void (*handler)(), int Exint)
{
 ......
 InterruptHandlers[vector] = handler;
 ......
}

在说的理解之前,要谨记44b0提供了两种向量和非向量的中断mode。
下面是我的理解:
(1)在向量中断时采取的操作
从scat_ram.scf和isr_address.s中,可以得到从0x0020000处开始的位置,为每一个中断留出了4个字节

的空间,其中包括timer1.这些空间应该是用来存储isr的地址(指针)的。

继续,从scat_ram.scf也可以得到,从0x00008000开始存放init.s的数据。
将HandlerTIMER1 HANDLER HandleTIMER1的宏展开,得到

HandlerTIMER1
    sub     sp,sp,#4    
    stmfd   sp!,{r0}   
    ldr     r0,=HandleTIMER1
    ldr     r0,[r0]    
    str     r0,[sp,#4]    
    ldmfd   sp!,{r0,pc}    
这里结合VECTOR_BRACH中的代码
ldr pc,=HandlerTIMER1
来看,假设现在timer1中断到来,那么执行该ldr命令,pc值指向sub处开始执行。ldr    

r0,=HandleTIMER1会将isr_address.s中export的HandleTIMER1加载到r0中,这里的r0中所放的实际上也

是一个地址,指向相应isr指针的指针,执行ldr r0,[r0]后,r0中才是指向isr的指针(地址),通过

堆栈的巧妙操作,pc指向了isr,开始执行相应的isr。这个isr怎样是怎样和相应的Handle对应的呢?在

函数uHALr_InterruptRequestInit()中,有pISR_UNDEF= (unsigned) DebugUNDEF等,这些的意思是在

pISR_UNDEF所代表的地址处放置指向DebugUNDEF的指针(地址)。
(2)非向量中断下的操作

回到init.s中,有语句
;Setup IRQ handler
     ldr     r0,=HandleIRQ ;This routine is needed
     ldr     r1,=IRQ_Handler ;=IsrIRQ,if there isn't 'subs pc,lr,#4' at 0x18,

0x1c
     str     r1,[r0]
这里要注意了,HandleIRQ也是isr_address.s中的那个,只是这里将IRQ_Handler的地址放到HandleIRQ预

留的空间中。
同样,如果在这种mode下,有一个irq中断到来,那么首先系统也会像(1)那样找到HandleIRQ,但是现在

那里放置的是IRQ_Handle的地址,所以转向IRQ_Handle,继而转向ISR_IrqHandler。在ISR_IrqHandler中

,利用I_ISPC寄存器找到中断源,然后调用相应源的处理函数。
借用linux的概念,这个执行的isr应该在系统初始化的时候被注册。这个任务应该是由函数
SetISR_Interrupt完成的,在SetISR_Interrupt中,调用了(*InterruptHandlers[MAXHNDLRS])(void),

有InterruptHandlers[vector] = handler;这个vector明显是44b0定义的若干irq中断的相对偏移。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值