文档库 最新最全的文档下载
当前位置:文档库 › 中断机制

中断机制

如果是使用SD卡或NandFlash,将会使用到ROMCode,中断向量在0x14000开始,依次为“Reset”“Undef”“SWI”“Prefetch Abort”“Data Abort”“保留”“IRQ”“FIQ”。例如: IRQ中断出现当程序会自动跳转至0x14018。
下面以IRQ为例说明:
(1) 当出现IRQ中断,程序计数器PC先跳转到0x14018;
(2) ROMCode又马上让PC跳转到从0x0x4020FFC8开始的RAM中断向量处,注意Reset中断直接执行ROMCode不需要RAM中断向量,所以RAM中断向量从Undef开始,IRQ为0x4020FFDC
(3) 在上述所有RAM中断向量中都存放一条PC=[RAM中断向量地址+0x1C]指令(注意中括号含义是取地址中的内容),这个工作是由ROMCode正常启动时完成的,但是我在写代码时还是又重新弄了一边,对于IRQ,RAM中断向量地址+0x1C=0x4020FFDC+0x1C=0x4020FFF8
(4) 因此只需要在0x4020FFF8处存入你的IRQ函数的地址就可以了,在我的OclO中,cpu/omap-3/start.S中有段代码:

awSRAMVectorBase:
.word SRAM_VECTORS_BASE

SRAM_VECTORS_BASE在 include/asm/arch-omap3/omap35xx.h 中定义为
#define SRAM_VECTORS_BASE 0x4020FFC8 //由Rom Code指定的中断表地址

ldr r1, awSRAMVectorBase /* build vect addr */
Next:
ldmia r0!, {r3-r9} /* copy from source address [r0] */
stmia r1!, {r3-r9} /* copy to target address [r1] */
cmp r0, r2 /* until source end address [r2] */
bne Next /* loop until equal */

上面这个循环就是将所有的中断的响应函数首地址放入响应的地址,当执行PC=[RAM中断向量地址+0x1C]时,就能跳进响应的函数去了。每个函数由两部份组成:汇编+C,汇编部分在start.S中
IRQ为
IRQVectorA:
stmfd sp!, {r0 - r12,lr}
bl IRQVectorC
ldmfd sp!, {r0 - r12,lr}
subs pc, lr, #4 //当目的寄存器为pc,s位表示同时从spsr返回cpsr

其中IRQVectorC为C语言函数在 board/Octagram/Ocsom3530/interrupts.c中定义。
(5) 此时已经从汇编到C了,下面的就差从寄存器中把到底是啥IRQ中断分出来,然后switch语句也好,函数指针也好,调用对应的响应函数;
(6) 那堆寄存器在《OMAP35x Technical Reference Manual》第10章,应该好好看看
表10-4(1042页)列出了所有中断的IRQ形式,0~95共96个,当然它们还可以走FIR通道。

寄存器在每章的最后一节,中断这章也不例外。
有几个比较重要
INTCPS_PROTECTION:这是个讨厌的寄存器,因为你不先设置它以关闭保护机制,它就不让你设置其他寄存器。
INTCPS_SIR_IRQ:如果中断走的是IRQ形式,当出现这种中断时,低7位就将自动标示出是哪个中断,因此这个可以作为IRQ中断函数中判断具体中断的依据之一
INTCPS_SIR_FIQ:如果中断走的是FIQ形式,当出现这种中断时,低7位就将自动标示出是哪个中断,因此这个可以作为FIQ中断

函数中判断具体中断的依据之一
INTCPS_MIRn:这里n=0~2,刚好3个寄存器,共96位,刚好以此对应96个中断形式,注意INTCPS_MIR0的bit0对应0号中断,当对中断的相应位写0,才可开启中断,因此别在初始化时忘了设置这几个寄存器
INTCPS_ITRn、INTCPS_PENDING_IRQn、INTCPS_PENDING_FIQn:这三组寄存器(共9个,n都=0~2)在手册中有一句描述得很清楚:
The current incoming interrupt status before masking is readable from the MPU_INTC.INTCPS_ITRn register. After masking and IRQ/FIQ selection, and before priority sorting is done, the interrupt status is readable from the MPU_INTC.INTCPS_PENDING_IRQn and MPU_INTC.INTCPS_PENDING_FIQn registers.
INTCPS_ILRm:m=0~95,刚好每个中断对应一个,这组寄存器的bit0用于决定是IRQ通道还是FIR通道,2~7位用于设置优先级,
INTCPS_THRESHOLD:用于设置一个优先级门槛,当上面这个寄存器设置的优先级低于或等于这个优先级,不管INTCPS_MIRn是什么都被屏蔽的,具体看10.4.1.2.2 Priority Masking
INTCPS_SYSCONFIG:用于设置中断控制模块的时钟情况(节能考虑),还可以进行模块的软复位
INTCPS_SYSSTATUS:指示软复位是否完成的寄存器

如何将所有中断控制器的寄存器定义成变量,以便好在C语言下使用?如果经常进行底层开发下面代码应该不会陌生:
//寄存器的定义
#define INTCPS_BASE 0x48200000
#define INTCPS_REVISION (*(volatile unsigned int *)(INTCPS_BASE + 0x0))
#define INTCPS_SYSCONFIG (*(volatile unsigned int *)(INTCPS_BASE + 0x10))
#define INTCPS_SYSSTATUS (*(volatile unsigned int *)(INTCPS_BASE + 0x14))
#define INTCPS_SIR_IRQ (*(volatile unsigned int *)(INTCPS_BASE + 0x40))
#define INTCPS_SIR_FIQ (*(volatile unsigned int *)(INTCPS_BASE + 0x44))
#define INTCPS_CONTROL (*(volatile unsigned int *)(INTCPS_BASE + 0x48))
#define INTCPS_PROTECTION (*(volatile unsigned int *)(INTCPS_BASE + 0x4C))
#define INTCPS_IDLE (*(volatile unsigned int *)(INTCPS_BASE + 0x50))
#define INTCPS_IRQ_PRIORITY (*(volatile unsigned int *)(INTCPS_BASE + 0x60))
#define INTCPS_FIQ_PRIORITY (*(volatile unsigned int *)(INTCPS_BASE + 0x64))
#define INTCPS_THRESHOLD (*(volatile unsigned int *)(INTCPS_BASE + 0x68))
#define INTCPS_ITR(n) (*(volatile unsigned int *)(INTCPS_BASE + 0x80 + (0x20*n)))
#define INTCPS_MIR(n) (*(volatile unsigned int *)(INTCPS_BASE + 0x84 + (0x20*n)))
#define INTCPS_MIR_CLEAR(n) (*(volatile unsigned int *)(INTCPS_BASE + 0x88 + (0x20*n)))
#define INTCPS_MIR_SET(n) (*(volatile unsigned int *)(INTCPS_BASE + 0x8C + (0x20*n)))
#define INTCPS_ISR_SET(n) (*(volatile unsigned int *)(INTCPS_BASE + 0x90 + (0x20*n)))
#define INTCPS_ISR_CLEAR(n) (*(volatile unsigned int *)(INTCPS_BASE + 0x94 + (0x20*n)))
#define INTCPS_PENDING_IRQ(n) (*(volatile unsigned int *)(INTCPS_BASE + 0x98 + (0x20*n)))
#define INTCPS_PENDING_FIQ(n) (*(volatile unsigne

d int *)(INTCPS_BASE + 0x9C + (0x20*n)))
#define INTCPS_ILR(m) (*(volatile unsigned int *)(INTCPS_BASE + 0x100 + (0x4*m)))

到此,只是介绍了中断机制,对于不同的中断还有不同的寄存器要设置,以GPIO上的外部中断为例,还要将对应引脚设置成输入状态,设置是什么电平或边沿触发中断,触发的死区时间等等,又是一堆寄存器。
这个就需要参考24章了,最后一节还是寄存器,这是个规律,此外还要注意这堆寄存器中是否也有一个有“保护”这样的字样,GPIO如果有,优先处理之,这个同样也是规律,好多模块都出现这个该死的寄存器,不过GPIO这章没有。
同样是规律的,你会发现好多模块的第一个寄存器总是REVISION,可以读出寄存器的版本;第二个是SYSCONFIG,不是拿来设置时钟运行与否就是软复位,第三个是SYSSTATUS,标识复位是否完成了。



相关文档
相关文档 最新文档