控制/MCU
Startup中断向量表
;*******************************************************************************
; Exception vectors
;*******************************************************************************
LDR PC, Reset_Addr ; 地址为0x8000 0000
LDR PC, Undefined_Addr
LDR PC, SWI_Addr
LDR PC, Prefetch_Addr
LDR PC, Abort_Addr
NOP ; Reserved vector
LDR PC, IRQ_Addr
LDR PC, FIQ_Addr
; *******************************************************************************
; Exception handlers address table
;*******************************************************************************
Reset_Addr DCD __program_start ;地址为0x8000 0020
Undefined_Addr DCD UndefinedHandler
SWI_Addr DCD SWIHandler
Prefetch_Addr DCD PrefetchAbortHandler
Abort_Addr DCD DataAbortHandler
DCD 0 ; Reserved vector
IRQ_Addr DCD IRQHandler
FIQ_Addr DCD FIQHandler
;*******************************************************************************
; Peripherals IRQ handlers address table
;*******************************************************************************
PRCCUCMU_Addr DCD PRCCUCMUIRQHandler ;地址为0x8000 0040
对于嵌入式系统来说,一般将上面产生的代码放在flash中,地址0x8000 0000(该sector同时remap到0x0000 0000)。将__program_start,UndefinedHandler等地址放到指令缓冲池中。从而可以实现全局范围内跳转。根据ARM指令长度可知,上述__program_start的地址存放的物理地址是0x8000 0020,根据ARM流水线的情况,LDR PC, Reset_Addr产生汇编语言指令为LDR PC, [PC, #24]。
当IRQ中断发生时,程序跳转到IRQHandler处。
IRQHandler
IRQHandler
SUB lr,lr,#4 ; Update the link register
SaveContext r0,r12 ; Save the workspace plus the current
; return address lr_ irq and spsr_irq.
LDR lr, =ReturnAddress; Read the return address.
LDR r0, =EIC_base_addr
LDR r1, =IVR_off_addr
ADD pc,r0,r1 ; Branch to the IRQ handler.
ReturnAddress
; Clear pending bit in EIC (using the proper IPRx)
LDR r0, =EIC_base_addr
LDR r2, [r0, #CICR_off_addr] ; Get the IRQ channel number
CMP r2,#31
SUBHI r2, r2, #32
MOV r3,#1
MOV r3,r3,LSL r2
STRHI r3,[r0, #IPR1_off_addr] ; Clear the corresponding IPR bit.
STRLS r3,[r0, #IPR0_off_addr] ; Clear the corresponding IPR bit.
RestoreContext r0,r12 ; Restore the context and return to the.。。
; 。。.program execution.
其中,EIC_base_addr为0xFFFF FC00,IVR的地址是0xFFFF FC18,通过执行该寄存器中的指令可进入到相应的中断服务程序,该寄存器可在通过install中断向量服务程序时进行设置。例如该IVR寄存器的值为0xE59FF468,则表示LDR PC, [PC, #1128]。其实就是跳转到指令缓冲区中定义Timer2中断服务程序。
Interrupt Vector Register和Source Interrupt Registers的设置
extern u32 PRCCUCMU_Addr;
u8 Counter=0;
u32 Offset = (u32)&PRCCUCMU_Addr; //PRCCUCMU_Addr地址为0x8000 0040
u32 Tmp=0;
/* IVR = high half of load PC instruction (LDR PC,) */
EIC-》IVR = 0xE59F0000; //0xE59F0000,根据Instruction format表示一条无条
//件执行的语句,该指令向目的寄存器PC传递值,
//指令中的F,表示r15即PC
/* Read the offset of the interrupt vectors table address */
Offset = (Offset+0x3E0)《《16; //偏移地址问什么要加上0x3E0? 是因为
//0x8000 0040 + 0x3E0 《《 16 = 0x0420 0000,
//中断发生后,SIR的高16bits会传递到IVR的低
//16bit作为偏移地址,而IVR地址为0xFFFF FC18
//0xFFFF FC18 + 0x420 + 0x8(流水线影响)=
//0x1 0000 0040,由于ARM为32bits,故即为
//0x40(该地址同时映射到0x8000 0040处)
/* Initialize SIRn registers with the equivalent low half of load PC instruction */
for(Counter=64; Counter!=0; Counter--)
{
EIC-》SIRn[64-Counter] = Offset|0xF0000000; //为什么0xF000 0000,是因为LDR PC, [PC, #0ffset],
//源寄存器和目的寄存器都是PC
Offset += 0x00000004 《《 16;
}
上面的程序片断设置IVR和SIRn等。这样当IRQ中断发生时,PC首先跳转到0xFFFF FC18处,即执行IVR寄存器中的指令LDR PC, [PC, #offset],从指令缓冲池中取出中断服务程序的地址给PC,从而跳转到中断服务程序。
全部0条评论
快来发表一下你的评论吧 !