打印

关于44b0中的中断调用问题,(有点长,各位见谅)

[复制链接]
2235|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
luocolor|  楼主 | 2007-1-13 01:25 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
关于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
    ......

HandlerTIMER1    HANDLER HandleTIMER1

然后,在另外的文件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)
    }

}
然后,在文件isr.c和isr.h中定义下面的函数和数据结构。
void (*InterruptHandlers[MAXHNDLRS])(void)={NULL,};
有函数
void SetISR_Interrupt(int vector, void (*handler)(), int Exint)
{
    ......
    InterruptHandlers[vector] = handler;
    ......
}
最后,在整个系统的初始化时,用到了下面的语句:

SetISR_Interrupt(INT_TIMER1_OFFSET,OSTimeTick,NULL);

下面是我的理解:
从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。

借用linux的概念,这个执行的isr应该在系统初始化的时候被注册。这个任务应该是由函数
SetISR_Interrupt完成的,在SetISR_Interrupt中,调用了(*InterruptHandlers[MAXHNDLRS])(void),

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

但是让我很很很困惑的是:这个InterruptHandlers是在函数里面自己(程序员)定义的,可以说它并不与

系统的相硬件有什么关系。我的意思是,在pc指向isr后,为什么相应的isr就是InterruptHandlers相应

偏移处指向的函数。它们中间是怎样联系的呢?

我知道或许我还有些东西不明了,希望各位大侠点化我下。呵呵。多谢了。

相关帖子

沙发
luocolor|  楼主 | 2007-1-14 16:55 | 只看该作者

现在明白了。

原来我没有将向量中断和非向量中断理解清楚。呵呵

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

40

主题

105

帖子

0

粉丝