irq 涉及的概念
1. 硬件A : 异常向量表
2. 硬件A : irq硬件流程及建议的软件流程
3. 硬件B : 芯片实现的中断控制器
数据手册 12 VECTORED INTERRUPT CONTROLLERS P409
4. 软件A : linux中断处理的软件流程(irq部分)
5. 软件B : linux中断处理的软件流程(中断控制器部分)
6. 软件C : linux中断处理的软件流程(irq_desc部分)
硬件
2个VIC(Vectored Interrupt Controller, ARM PrimeCell
PL192)
2个TZIC(TrustZone Interrupt Controller, SP890)
1个VIC支持32个中断源
可编程的 interrupt priority levels 和 可编程的 interrupt priority level masking
可产生 FIQ IRQ 和 SWI 异常
可查询的 Raw interrupt status/Interrupt request status
start_kernel
local_irq_disable
// include/linux/irqflags.h
// 224 #define local_irq_disable() do { raw_local_irq_disable(); } while (0)
// 155 #define raw_local_irq_disable() arch_local_irq_disable()
// arch/arm/include/asm/irqflags.h
// 46 #define arch_local_irq_disable arch_local_irq_disable
// 47 static inline void arch_local_irq_disable(void)
// 48 {
// 49 asm volatile(
// 50 " cpsid i @ arch_local_irq_disable"
// 51 :
// 52 :
// 53 : "memory", "cc");
// 54 }
early_boot_irqs_disabled = true;
// init/main.c
// 124 bool early_boot_irqs_disabled __read_mostly;
early_irq_init
// kernel/irq/irqdesc.c
// 521 int __init early_irq_init(void)
// 打印信息
// NR_IRQS: 16, nr_irqs: 229, preallocated irqs: 229
// 流程:
// 1. 计算 NR_IRQS nr_irqs initcnt
// 2. 根据 initcnt 的数量(229),创建(229个) irq_desc ,并插入数据结构(radix_tree) 变量 irq_desc_tree 中
init_IRQ
// arch/arm/kernel/irq.c
// 78 void __init init_IRQ(void)
// 打印信息
/*
S3C6410 clocks: apll = 532000000, mpll = 532000000
epll = 96000000, arm_clk = 532000000
VIC @(ptrval): id 0x00041192, vendor 0x41
irq: Cannot allocate irq_descs @ IRQ32, assuming pre-allocated
VIC @(ptrval): id 0x00041192, vendor 0x41
irq: Cannot allocate irq_descs @ IRQ64, assuming pre-allocated
*/
// 流程:
// 1. 调用 machine_desc->init_irq/即s3c6410_init_irq 做 芯片的 irq 初始化(vic)
s3c6410_init_irq
s3c64xx_init_irq(~0 & ~(1 << 7), ~0);
s3c64xx_clk_init(NULL, xtal_f, xusbxti_f, soc_is_s3c6400(), S3C_VA_SYS);
// void __init vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources, u32 resume_sources);
/*
// map.pfn:71200,map.virtual:f6000000,map.length:4000,map.type:0 // S3C64XX_PA_VIC0
// map.pfn:71300,map.virtual:f6010000,map.length:4000,map.type:0 // S3C64XX_PA_VIC1
*/
/* VIC0 is missing IRQ7, VIC1 is fully populated. */
// 0xf6000000,0x20,0xffffff7f,0x4
// hwirq_max 编号 < 0x20 , 不等于 0x20
vic_init(VA_VIC0, IRQ_VIC0_BASE, vic0_valid, IRQ_VIC0_RESUME);
// 0xf6010000,0x40,0xffffffff,0x53020000
// hwirq_max 为0x40
vic_init(VA_VIC1, IRQ_VIC1_BASE, vic1_valid, IRQ_VIC1_RESUME);
__vic_init
vic_disable(base);
vic_clear_interrupts(base);
vic_init2(base);
vic_register(base, NULL, irq_start, vic_sources, resume_sources, NULL);
填充vic_devices[0,1]
set_handle_irq(vic_handle_irq);
handle_arch_irq = vic_handle_irq;
v->irq = IRQ_VICx_BASE;
// 建立 硬件中断号与软件中断号的映射
// 1.向系统注册一个irq domain
// 因为 一个硬件系统可能有多个 中断控制器
// A中断控制器的硬件中断号 无法与 B中断控制器的硬件中断号区分
// 所以加了一层 irq domain
// 目前 是 软件中断号 <-> domain <-> 硬件中断号
v->domain = irq_domain_add_simple(node, fls(valid_sources), irq, &vic_irqdomain_ops, v);
// 2. 建立 该 domain 内的硬件中断号与软件中断号的映射
// 建立HW interrupt ID和IRQ number的映射关系。
// 该接口函数以irq domain和HW interrupt ID为参数,返回IRQ number(这个IRQ number是动态分配的)
针对每一个 irq source ,irq_create_mapping(v->domain, i);
// vic_sources : 有效的中断源, bit 为 1 ,表示 有效
// resume_sources : 可以resume唤醒的中断源 , bit 为 1 , 表示 有效
其他
硬件中断号 <-> domain <-> 软件中断号 是 通过 什么结构体 关系到一起的
irq_create_mapping -> irq_create_mapping_affinity -> irq_domain_associate(domain, virq, hwirq)
int irq_domain_associate(struct irq_domain *domain, unsigned int virq, irq_hw_number_t hwirq)
struct irq_data *irq_data = irq_get_irq_data(virq);
struct irq_desc *desc = irq_to_desc(irq); // 通过 irq 找到 irq_desc , 这个关系被封印在了 数据结构 radix_tree 中
radix_tree_lookup(&irq_desc_tree, irq);
return desc ? &desc->irq_data : NULL;
irq_data->hwirq = hwirq; // irq_desc 中存在着 irq_data->hwirq
irq_data->domain = domain; // irq_desc 中存在着 irq_data->domain
相关代码
$ ls kernel/irq
autoprobe.c debug.h dummychip.c handle.c irqdesc.c Kconfig manage.c proc.c settings.h
chip.c devres.c generic-chip.c internals.h irqdomain.c Makefile pm.c resend.c spurious.c
$ ls drivers/irqchip/
irqchip.c irq-vic.c Kconfig Makefile
# cat /proc/interrupts
CPU0
软件中断号 次数 中断控制器 硬件中断号(有的是vic0上的,有的是vic1上的) 中断触发 中断名称
58: 0 VIC 26 Edge s3c2410-wdt
59: 757035 VIC 27 Edge samsung_time_irq
62: 478966 VIC 30 Edge s3c-lcd
69: 183 VIC 5 Edge s3c6400-uart
79: 25 VIC 15 Edge ohci_hcd:usb1
88: 35 VIC 24 Edge mmc0
108: 87366 s3c-eint Level eth0
Err: 0
驱动如何使用 中断
1. 根据 硬件中断号/或引脚id 找到 软件中断号
platform_get_resource(pdev, IORESOURCE_IRQ, 0); 等
2. 根据 软件中断号 申请 handler
request_threaded_irq/request_irq
上一篇:OK6410A 开发板 (八) 13 linux-5.11 OK6410A start_kernel 打印角度 第一阶段 console
下一篇:OK6410A 开发板 (八) 11 linux-5.11 OK6410A start_kernel 打印角度 第一阶段 mem
推荐阅读最新更新时间:2024-11-02 16:10