一、中断控制器
GPIO产生的中断信号不会直接发给CPU,而是发给中断控制器
(一)中断控制器的必要性
1、4412中有160个硬件可以向CPU发送中断信号。
2、4412中有4个CPU,4个CPU都可以用来处理中断信号。
3、 中断信号产生后,不能所有的CPU都用来处理中断,需要对其进行管理。
4、中断处理信号有IRQ/RIQ信号。
5、不同外部设备发送的中断信号如果直接发送给cpu,CPU不能分辨是谁发送的。
(二)中断控制器
1、多个中断同时产生
在中断控制器内部会对中断进行排序,发送优先级最高的,处理完之后,在当前剩下的最高优先级的中断交给CPU处理。优先级高的先响应,但是高优先级的中断不能打断低优先级中断。
2、一个中断处理时,又产生一个中断
中断处理器挂起等待的中断。
3、选择CPU
4412含有4个CPU,中断处理器为每个中断分配合适的CPU处理。
4、中断触发类型FIQ/RIQ
中断处理器给每个中断分配合适的类型,在转发给中断类型去处理。
5、区分不同硬件的中断
帮助CPU区分不同硬件发来的不同中断。
6、中断开关
中断处理器可以打开或禁止一个中断。
二、Exynos4412下的中断控制器
实际开发时,在处理器安装大型操作系统,驱动开发和中断编程在操作系统内部是有的,直接写中断申请函数,不用管内部细节。
1、中断类型
SGI:中断控制器内部的软中断,用于多核通信,区分汇编。
PPI:私有外设中断,只能发送给一个特定的CPU
SPI:共享外设中断,可以发送给任意一个CPU
SPI在驱动开发中应用比较广,其他都是CPU内核用到。
2、中断状态
安全状态IRQ/FIQ,非安全IRQ。
3、中断挂起
4、中断处理器GIC管理中断的方式
中断号0~159,每个中断都有一个唯一的中断号,中断号和优先级无关。
SGIs[15:0]:分配给软中断
PPLs[31,16]:分配给了私有中断
SPI[159:32]:分配给了共享中断
5、GPX1_1产生的中断
6、中断控制器里的寄存器
寄存器有上千个,管理的终端多,功能多。
三、中断控制器寄存器详解(一)
(一)按键中断需要的寄存器1
1、ICDDCR-GIC的总开关
置0:不接收中断信号,也不会将中断信号挂起。
置1:接受外部产生的中断信号,挂起到CPU的接口。
2、ICDISER_CPU
用于设置每一个中断信号的打开和关闭,打开会被中断寄存器转发给CPU。否则不会转发。
160/32 = 5;需要5个寄存器来管理所有中断。0号寄存器管理0~31号中断,一次类推。
四、中断控制器寄存器详解(二)
(一)按键中断需要的寄存器2
1、给中断选择CPU
160*8bit /32 = 40个寄存器
每个中断用8位来标记选择的CPU(实际只用4个,因为4412是四核CPU)
第0个中断对应第0个寄存器的前8位,第57个中断(按键)对应偏移量为838的寄存器的8-15位。
若将57号中断交给CPU2处理,那么这8位应该设置为0000 0100。在裸机程序默认发给CPU0处理,设置多核其他核会比较复杂,装入操作系统后,直接发送中断请求即可。
2、ICCICR_CPUn
CPU和中断处理器之间不是直连的,有一个CPU接口,相当于开关,闭合接通,关闭断开。共有4个。
3、中断处理器默认设置中断为IRQ,因为后续不需要我们自己维护中断程序,所以使用默认即可。本次WDT实验用到了57号中断,所以也不涉及中断优先级的问题。
五、中断控制器编程
#include "exynos_4412.h"
void Delay(unsigned int Time)
{
while(Time--);
}
//IRQ异常处理
void do_irq(void)
{
unsigned int IrqNum = 0;
/*从中断控制器中获取当前中断的中断号*/
IrqNum = CPU0.ICCIAR & 0x3FF;
/*根据中断号处理不同的中断*/
switch(IrqNum)
{
case 0:
//0号中断的处理程序
break;
case 1:
//1号中断的处理程序
break;
/*
* ... ...
*/
case 57:
printf("Key2 Pressed\n");
/*清除GPIO控制器中GPX1_1的中断挂起标志位*/
EXT_INT41_PEND = (1 << 1);
/*将当前中断的中断号写回到中断控制器中,以这种方式来告知中断控制器当前的中断已经处理完成,可以发送其它中断*/
CPU0.ICCEOIR = CPU0.ICCEOIR & (~(0x3FF)) | (57);
break;
/*
* ... ...
*/
case 159:
//159号中断的处理程序
break;
default:
break;
}
}
int main()
{
/*外设层次 - 让外部的硬件控制器产生一个中断信号发送给中断控制器*/
/*将GPX1_1设置成中断功能*/
GPX1.CON = GPX1.CON | (0xF << 4);
/*设置GPX1_1的中断触发方式为下降沿触发*/
EXT_INT41_CON = EXT_INT41_CON & (~(0x7 << 4)) | (0x2 << 4);
/*使能GPX1_1的中断功能*/
EXT_INT41_MASK = EXT_INT41_MASK & (~(1 << 1));
/*中断控制器层次 - 让中断控制器接收外设产生的中断信号并对其进行管理然后再转发给CPU处理*/
/*全局使能中断控制器使其能接收外设产生的中断信号并转发到CPU接口*/
ICDDCR = ICDDCR | 1;
/*在中断控制器中使能57号中断,使中断控制器接收到57号中断后能将其转发到CPU接口*/
ICDISER.ICDISER1 = ICDISER.ICDISER1 | (1 << 25);
/*选择由CPU0来处理57号中断*/
ICDIPTR.ICDIPTR14 = ICDIPTR.ICDIPTR14 & (~(0xFF << 8)) | (0X01 << 8);
/*使能中断控制器和CPU0之间的接口,使中断控制器转发的中断信号能够到达CPU0*/
CPU0.ICCICR = CPU0.ICCICR | 1;
GPX2.CON = GPX2.CON & (~(0xF << 28)) | (0x1 << 28);
while(1)
{
/*点亮LED2*/
GPX2.DAT = GPX2.DAT | (1 << 7);
/*延时*/
Delay(1000000);
/*熄灭LED2*/
GPX2.DAT = GPX2.DAT & (~(1 << 7));
/*延时*/
Delay(1000000);
}
return 0;
}
六、作业
简述中断控制器的主要作用
1、多个中断同时产生
在中断控制器内部会对中断进行排序,发送优先级最高的,处理完之后,在当前剩下的最高优先级的中断交给CPU处理。优先级高的先响应,但是高优先级的中断不能打断低优先级中断。
2、一个中断处理时,又产生一个中断
中断处理器挂起等待的中断。
3、选择CPU
4412含有4个CPU,中断处理器为每个中断分配合适的CPU处理。
4、中断触发类型FIQ/RIQ
中断处理器给每个中断分配合适的类型,在转发给中断类型去处理。
5、区分不同硬件的中断
帮助CPU区分不同硬件发来的不同中断。
6、中断开关
中断处理器可以打开或禁止一个中断。