cortex-a8裸机系列:第十二章 中断控制器与外部中断
0赞一、 异常处理的2个阶段
1、 异常向量表跳转
依赖于CPU设计时自动提供的异常向量表的机制,也就是当异常发生时,硬件能自动的跳转到异常向量表执行。
该阶段主要任务是产生异常前后的现场保存/恢复现场,跳转到真正的异常处理程序。
2、 进入了真正的异常处理程序
通过判断寄存器,得知是哪一类的中断产生,然后再检查子类中断寄存器,查看具体是哪一个中断产生,然后跳转到对应的程序执行。
二、 210的中断控制器
210包括4个VIC(vectored interrupt controller)。
当要清除中断挂起,需要往VICADDRESS寄存器(VIC0ADDRESS,VIC1ADDRESS,VIC2ADDRESS,VIC3ADDRESS)写入0。
210支持的中断源很多,所以直接设计了4个中断寄存器,每个32位,每位对应一个中断源,(理论上210最多支持128个中断源,但是实际上只有93个,有些位是空的);210没有子中断寄存器,每个中断源都是并列的。当中断发生时,在中断处理程序中依次查询4个中断源寄存器,看哪一个的哪一位置1,则这个位对应的寄存器就发生了中断,即找到了中断编号。
于是计算中断编号就比较麻烦了,很耗费时间,就影响了实时性。(实时性就是中断发生到响应的时间,这个时间越短越好)。
所以210开拓了一种全新的寻找isr的机制。210提供了很多寄存器来解决每个中断源对应isr的寻找问题。这些都是硬件来实现的。
210的中断号有两种,一个是VIC port no,表示的是在寄存器中的偏移,另外一个是No,这个是中断的物理号,每个中断对应一个。应用层使用的是中断的物理号,所以底层代码需要处理,将中断的物理号转换为对应寄存器的对应位。
寄存器
1. VICIRQSTATUS
中断源在屏蔽之后的状态。为1,说明中断有效。
2. VICFIQSTATUS
快速中断源在屏蔽之后的状态
3. VICRAWINTR
中断源未屏蔽之前的状态,这个寄存器,表明中断源的原始状态,但是CPU是否响应该中断,还需要后续的一些设置(需要看VINCINTENABLE和VICINESELECT寄存器)才行。
4. VINCINTSELECT
中断的选择,是选择普通中断还是快中断。
210支持两种中断,irq和fiq。Irq是普通中断,fiq是快速中断。快速中断提供了一种更快响应处理的中断通道,用于对实时性要求很高的中断源。Fiq在CPU设计时预先提供了一些机制保证fiq可以被快速处理,从而保证实时性。Fiq的限制就是只能有一个中断源被设置为fiq,其他都是irq。
CPU是如何保证fiq比irq快?一、fiq模式有专用的r8-r12寄存器,因此在fiq的isr中可以直接使用r8-r12而不用保存,这就能节省时间。二、异常向量表中fiq是最后一个异常向量入口,因此fiq的isr不需要跳转,这样就比其他异常少跳转了一次,省了函数跳转的时间。
5. VICINTENABLE
中断使能寄存器,负责相应的中断的使能,也就是当中断产生时,CPU是否要响应该中断。只要在这个中断编号对应的VICINTENABLE响应位写1即可。
这个寄存器写1才有效果,写0没有效果。
该寄存器可读可写,读的话,是得到中断是否使能的状态,1是使能,0是不使能。
6. VICINTENCLEAR
中断除能寄存器,负责相应的中断的除能,往相应寄存器相应的位写入1,就对该中断禁止了。
7. VICSOFTINT
软中断寄存器,产生软中断,也就是软件往这个寄存器的某些位写1,那么就会触发软件中断,CPU会执行该位对应的中断处理函数。
8. VICSOFTINTCLEAR
软中断除能寄存器。将对应的软中断给除能。使用软中断,CPU执行完中断后,因为软中断没有被清除,所以又会执行中断。所以要在中断处理程序中,将软中断给清除掉,避免再次进入中断。
9. VICPROTECTION
中断保护模式寄存器。开启保护模式后,中断中只有特权模式才能访问中断控制器寄存器,用户模式下是不能访问中断控制器寄存器的。如果没有开启的话,用户模式和特权模式都是可以访问中断控制器寄存器的。
10. VICADDRESS
中断地址寄存器,当对应中断产生的时候,硬件会将中断处理函数地址赋值给这个寄存器。
在中断处理函数结束后,要往中断地址寄存器写入任意值,以清除中断挂起。
11. VICSWPRIORITYMASK
屏蔽优先级中断寄存器。设置这个寄存器,可以屏蔽某些优先级的中断,使CPU不响应这些优先级的中断。
12. VICVECTADDR[0-31]
中断异常程序地址寄存器,这个是一个寄存器组,共有32个,每一个对应一个中断的中断处理函数的地址。当对应中断产生的时候,硬件会从该中断号对应的中断地址寄存器,取出该执行的中断处理函数的地址,然后赋值给PC,就执行中断处理函数了。
VICVECTADD0-31这32个寄存器分别用来存放真正的各个中断对应的isr的函数地址。相当于每一个中断源都有一个VECTADDR寄存器,设置中断的时候,把这个中断的isr地址直接放入到这个中断对应的VECTADDR寄存器即可。
13. VICVECTPRIORITY[0-31]
中断优先级寄存器,设置中断的优先级,有效值是0-15。
设置多个中断同时发生时先处理谁后处理谁的问题。一般来说高优先级的中断可以打断低优先级的中断,从而嵌套处理中断。
三、 中断设置流程
1. 绑定异常向量表到异常处理程序,禁止所有中断源,选择所有中断类型为IRQ,清除VICADDR寄存器为0
2. 中断的使能和禁止:根据终端号判断这个中断属于VIC几,然后再中断源减去这个VIC的偏移量,得到这个中断号在本VIC中的偏移量,然后1<<x位,写入相应的VIC的INTENABLE/INTENCLEAR寄存器即可
3. 绑定实现的ISE到VICnVECTADDR:VICVECTADDR寄存器共有4*32个,每个中断源都有一个VECTADDR寄存器,我们应该将为这个中断源写的isr地址写入到这个中断源对应的VECTADDR寄存器中即可
4. 发生中断时,硬件会自动把相应中断源的isr地址从VICnVECTADDR寄存器中保存在VICnADDR寄存器中,所以第二阶段的中断处理程序中,判断是哪一个VIC发生中断,只需要判断哪一个VIC的VICnIRQSTATUS不为0,就说明该VIC发生了中断。然后将该VIC的VICADDR赋值给函数指针,然后去执行该函数。
中断的工作分为2部分:
第一部分是我们为中断响应而做的预备工作:
初始化中断控制器
绑定写好的isr到中断控制器
相应中断的使能
第二部分是硬件产生中断后自动执行isr
第一步:经过异常向量表跳转入IRQ/FIQ的入口
第二步:做中断现场保护(在start.S)中,然后跳入isr_handler
第三步:在isr_handler中先找到哪个VIC中断了,然后直接去这个VIC的VICADDR寄存器中取出isr地址执行
第四步:Isr执行完,中断现场恢复,直接返回继续做常规任务。
四、 外部中断
外部中断属于VIC0。
外部中断0-15是各自单独占有一个中断源,中断16-31是公用一个中断源,EINT 16_31。
关键寄存器, CON,PEND, MASK
1. GPxnCON
配置GPIO管脚为外部中断,GPHn为外部中断源。
2. EXT_CON
配置外部中断的触发方式。触发方式就是外部中断产生的条件。
触发方式有两种:电平触发和边沿触发。
3. EXT_PEND
中断挂起寄存器,每一位对应一个外部中断,没有中断产生值为0。发生中断后,硬件会自动将这个寄存器该中断对应的位置为1。
4. EXT_MASK
中断屏蔽寄存器。用来屏蔽中断的,如果对应位设置为1,那么该位对应的中断是被屏蔽的。
5. EXT_FILTER
中断滤波寄存器
有两种滤波方式,一种是Delay filter,一种是Digital filter。
Delay filter是固定延时(和时钟没有关系),35ns,也就是当中断第一次检测到后,35ns后会再次检测一下,如果第二次检测中断确实产生,就认为中断产生,然后CPU执行中断。这个可以用在电平中断中,滤除电平毛刺。
Digital filter,数字滤波,和时钟是有关系的。滤波时间是时钟的周期*滤波周期数,每隔滤波周期数时间去检测一个中断,这里的时钟应该用的是PCLK,也就是GPIO的CLK。这个可以用在边沿触发的中断中,滤除抖动。
五、 外部中断编程实践
1. 外部中断对应的GPIO模式设置
2. 中断触发模式设置
3. 中断允许、清挂起
4. 中断处理程序isr编写