中断 /proc/interrupts 解析
linux_4.0/kernel/irq/proc.c
show_interrupts
/proc/interrupts列出当前所以系统注册的中断,记录中断号,中断发生次数,中断设备名称 // 仅适用于 arm32
如下图:从右至右:中断号 中断次数 中断设备名称
cat /proc/interrupts
读取到的内容从左到右,分别为:
1、逻辑中断号(软件中断号,linux分配的中断号),
2、中断在各CPU发生的次数,
3、中断所属设备类名称,
4、硬件中断号,
5、中断名称。
硬件中断号(GIC)
0-15 SGI // arch/arm/kernel/smp.c ipi_types
0 : IPI0 // sgi是通过写入软件生成的中断寄存器(GICD_SGIR)来生成的。
1 : IPI1 // 每个处理器接口最多可生成16个SGI,即ID0-ID15。
... // SGI具有边缘触发属性。https://blog.csdn.net/u011011827/article/details/106010573
7 : IPI7 // https://blog.csdn.net/u011011827/article/details/124474507
SGI8-15 can be reserved by secure firmware , thus may not be usable by the kernel
16-31 PPI
16 : TODO
...
25 : PPI6
26 : PPI5
27 : PPI4
28 : PPI0
29 : Secure Physical Timer event PPI1
30 : Non-secure Physical Timer event PPI2 重要
31 : Legacy nIRQ signal PPI3
32-number+32 SPI
32 : node_platform
...
36 : rtc-pl031
# cat interrupts
CPU0
16: 31414 GIC 34 timer 这个不是 "Non-secure Physical Timer event"
29: 955 GIC 47 eth0
32: 0 GIC 41 mmci-pl18x (cmd)
33: 0 GIC 42 mmci-pl18x (pio)
34: 8 GIC 44 kmi-pl050
35: 100 GIC 45 kmi-pl050
36: 13147 GIC 37 uart-pl011 // 硬件中断号为 GIC-37
40: 0 GIC 32 node_platform
42: 0 GIC 36 rtc-pl031
IPI0: 0 CPU wakeup interrupts // 从这一行开始就是核间中断
IPI1: 0 Timer broadcast interrupts
IPI2: 0 Rescheduling interrupts
IPI3: 0 Function call interrupts
IPI4: 0 Single function call interrupts
IPI5: 0 CPU stop interrupts
IPI6: 0 IRQ work interrupts
IPI7: 0 completion interrupts
Err: 0
wit@vexpress:/proc/irq/40 # ls -l -R
.:
total 0
-r--r--r-- 1 0 0 0 Jan 15 15:51 affinity_hint
-r--r--r-- 1 0 0 0 Jan 15 15:51 node
dr-xr-xr-x 2 0 0 0 Jan 15 15:51 node_platform
-rw-r--r-- 1 0 0 0 Jan 15 15:51 smp_affinity
-rw-r--r-- 1 0 0 0 Jan 15 15:51 smp_affinity_list
-r--r--r-- 1 0 0 0 Jan 15 15:51 spurious
./node_platform:
total 0
中断号实例
wit@vexpress:/ # cat /proc/interrupts
CPU0
16: 8106 GIC 34 timer
17: 0 GIC 87 node_platform
29: 585 GIC 47 eth0
32: 0 GIC 41 mmci-pl18x (cmd)
33: 0 GIC 42 mmci-pl18x (pio)
34: 8 GIC 44 kmi-pl050
35: 100 GIC 45 kmi-pl050
36: 116 GIC 37 uart-pl011
42: 0 GIC 36 rtc-pl031
81 node-platform {
82 compatible = "vendor-name", "chip-name", "chip-name2","chip-name3";
83 prop_bool = <1>;
84 prop_string = "value_string";
85 prop_int = <36>;
86
87 interrupts = <0 55 4>; // 55 + 32 = 87
239 rtc@17000 {
240 compatible = "arm,pl031", "arm,primecell";
241 reg = <0x17000 0x1000>;
242 interrupts = <4>; // 4+32 = 46
164 v2m_serial0: uart@09000 {
165 compatible = "arm,pl011", "arm,primecell";
166 reg = <0x09000 0x1000>;
167 interrupts = <5>; // 5+32 = 37 , 软件中断号 是 36
10009000.uart: ttyAMA0 at MMIO 0x10009000 (irq = 36, base_baud = 0) is a PL011 rev1
中断api
中断的获取
platform_get_irq(pdev,0); // 返回的是 软件中断号 , 被用作 request_irq的参数
内存的获取
struct resource *res = platform_get_resource(pdev,IORESOURCE_MEM,0);
// res 中 start 的是物理内存 , 可以在 cat /proc/iomem 中看到
devm_ioremap_resource(&pdev->dev,res);
// 建立虚拟地址和物理地址的映射
// 之后的 res->mapbase 是 映射过后的虚拟内存的起始位置
中断流程
- 请参考 gic400_r0p1_trm.pdf P53 , 或者 随便一个 gic trm 的 “Interrupt Signaling”
第一种可能流程
硬件
没有中断
// GIC 中断线中段状态 : inactive
中断来临
//GIC 中断线中段状态 : pending
软件
ARM架构相关代码:保存现场 // 软件关于中断的第一个动作
GIC代码:读 GICC_IAR寄存器,得到中断的硬件中断号,即软件响应中断
// 中断线的中断状态 : pending->active
驱动工程师的软件:中断服务程序
将中断的硬件ID号写入GICC_EOIR
// 中断线的中断状态 : active->inactive
ARM架构相关代码:恢复现场
第二种可能的流程
硬件
没有中断
// GIC 中断线中段状态 : inactive
中断来临
//GIC 中断线中段状态 : pending
软件
ARM架构相关代码:保存现场 // 软件关于中断的第一个动作
b1:
GIC代码:读 GICC_IAR寄存器,得到中断的硬件中断号,即软件响应中断
// 中断线的中断状态 : pending->active
驱动工程师的软件:中断服务程序
// 此时又来了一个中断 : active-> active and pending
将中断的硬件ID号写入GICC_EOIR
// 中断线的中断状态 : active and pending -> pending
转到 b1
ARM架构相关代码:恢复现场
版权声明:本文为u011011827原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。