关于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相应
偏移处指向的函数。它们中间是怎样联系的呢?
我知道或许我还有些东西不明了,希望各位大侠点化我下。呵呵。多谢了。 |