当前位置: 首页 > news >正文

Linux中断注册实战:从设备树到request_irq的完整流程解析(附GICv2示例)

Linux中断注册实战:从设备树到request_irq的完整流程解析(附GICv2示例)

在嵌入式Linux开发中,中断处理是驱动开发的核心技能之一。本文将深入探讨ARM架构下中断注册的完整流程,从设备树配置到最终的中断处理函数注册,结合GICv2中断控制器的具体实现,为开发者提供可直接落地的技术方案。

1. 设备树中的中断配置解析

现代ARM架构的嵌入式系统普遍采用设备树(Device Tree)来描述硬件资源,中断信息也不例外。一个典型的中断属性配置如下:

interrupt-parent = <&gic>; interrupts = <0 23 4>;

这里需要关注三个关键要素:

  • interrupt-parent:指向中断控制器节点,通常为GIC(Generic Interrupt Controller)
  • interrupts:包含三个参数:
    • 第一个参数:中断类型(0表示SPI共享外设中断,1表示PPI私有外设中断)
    • 第二个参数:硬件中断号
    • 第三个参数:中断触发类型(4表示高电平触发)

在驱动代码中,我们通常使用以下API获取中断号:

int irq = platform_get_irq(pdev, 0); if (irq < 0) { dev_err(&pdev->dev, "Failed to get IRQ\n"); return irq; }

注意:platform_get_irq()内部会调用irq_of_parse_and_map(),完成硬件中断号到Linux虚拟中断号的映射。

2. 中断号映射与irq_desc创建

当驱动通过设备树获取中断号时,内核会完成以下关键操作:

  1. 查找匹配的irq_domain(由中断控制器驱动初始化)
  2. 调用irq_domain_ops中的translate和map函数
  3. 为未映射的中断创建irq_desc结构体

以GICv2为例,主要完成以下工作:

static const struct irq_domain_ops gic_irq_domain_hierarchy_ops = { .translate = gic_irq_domain_translate, .alloc = gic_irq_domain_alloc, .free = irq_domain_free_irqs_top, .map = gic_irq_domain_map, };

关键数据结构关系如下:

结构体名称作用生命周期
irq_desc中断描述符,包含处理函数等核心信息从映射创建到系统关闭
irq_domain中断控制器域,负责硬件中断号到Linux中断号的转换中断控制器驱动初始化时创建
irqaction保存驱动注册的中断处理函数从request_irq()到free_irq()

3. 中断标志位深度解析

request_irq()的flags参数决定了中断的处理方式,以下是关键标志位的实际应用场景:

  • IRQF_SHARED:多个设备共享同一中断线时必需

    // 共享中断示例 ret = request_irq(irq, handler, IRQF_SHARED, "shared_dev", dev);
  • IRQF_ONESHOT:必须用于线程化中断,确保处理完成前不会触发新中断

    // 电源管理IC的中断通常需要此标志 ret = request_threaded_irq(irq, NULL, thread_fn, IRQF_ONESHOT, "pmic", dev);
  • IRQF_NO_SUSPEND:系统休眠时不关闭的中断(如唤醒源)

    // 唤醒中断配置示例 ret = request_irq(irq, wake_handler, IRQF_NO_SUSPEND, "wakeup", NULL);

提示:ARM平台应尽量避免使用IRQF_SHARED,现代SoC通常提供足够的中断线。

4. request_irq内部机制剖析

request_threaded_irq()是中断注册的核心函数,其执行流程如下:

  1. 参数检查(特别是共享中断的dev_id必须非空)
  2. 获取对应的irq_desc
  3. 分配并初始化irqaction结构
  4. 调用__setup_irq完成实际注册

关键代码路径:

request_threaded_irq() → __setup_irq() → irq_setup_forced_threading() // 强制线程化处理 → __irq_setup_trigger() // 设置触发方式 → irq_activate() // 激活中断

对于线程化中断,内核会为每个中断创建专属内核线程:

# 查看系统中断线程 ps -e | grep irq/

5. GICv2中断处理实战示例

以下是一个完整的GPIO中断驱动示例:

#include <linux/interrupt.h> #include <linux/gpio.h> static irqreturn_t gpio_irq_handler(int irq, void *dev_id) { struct my_device *dev = dev_id; // 读取GPIO状态确认中断源 if (!gpio_get_value(dev->gpio_num)) return IRQ_NONE; // 非本设备中断 // 实际中断处理逻辑 ... return IRQ_HANDLED; } static int probe(struct platform_device *pdev) { struct my_device *dev; int irq, ret; // 获取GPIO和中断号 dev->gpio_num = of_get_named_gpio(pdev->dev.of_node, "gpios", 0); irq = gpio_to_irq(dev->gpio_num); // 注册中断处理函数 ret = request_irq(irq, gpio_irq_handler, IRQF_TRIGGER_RISING | IRQF_ONESHOT, "my_gpio_irq", dev); if (ret) { dev_err(&pdev->dev, "Failed to request IRQ\n"); return ret; } return 0; }

常见问题处理技巧:

  1. 中断风暴防护:在handler开始时添加延迟检查

    if (time_before(jiffies, dev->last_irq + HZ/100)) return IRQ_HANDLED; dev->last_irq = jiffies;
  2. 共享中断优化:尽早判断中断源

    if (!(readl(reg) & INTR_FLAG)) return IRQ_NONE;
  3. 线程化中断优先级设置:

    struct task_struct *task = irq_desc_get_task(irq_to_desc(irq)); sched_set_fifo(task);

在实际项目中,我们发现GICv2的中断延迟主要来自以下几个方面:

  • 中断控制器本身的响应时间
  • 内核调度延迟(特别是非实时内核)
  • 共享中断的串行处理开销 通过perf工具可以精确测量各部分耗时:
perf stat -e irq:irq_handler_entry,irq:irq_handler_exit
http://www.jsqmd.com/news/546871/

相关文章:

  • PhysX帧分配器:一帧一擦的高效艺术
  • 小白程序员必备:收藏这份大模型技术栈入门指南(含RAG、AI Agent实战)
  • 2026卷帘门行业优质产品推荐榜聚焦抗风性能与口碑:钢制抗风卷帘门/铝合金卷帘门/银行防盗卷帘门/镂空卷帘门/选择指南 - 优质品牌商家
  • 提升开发效率与编码体验:开源字体LxgwWenKai跨平台配置全指南
  • 收藏!7种主流提示优化策略,小白也能轻松驾驭大模型,提升AI响应精准度与效率
  • 图结构AI Agent记忆机制深度解析:小白/程序员必备,收藏学习大模型前沿技术!
  • 【AI】AI安全高阶:生成式AI的安全风险与防御体系
  • MtSense07嵌入式磁传感器驱动库深度解析
  • ST7565SPI嵌入式LCD驱动库:轻量、可移植、零内存分配
  • 在WSL2 Ubuntu 22.04上搞定RK3568 SDK编译:我遇到的8个坑和填坑方法
  • PCS双向储能变流器Buck - Boost闭环控制仿真复现之旅
  • 大模型小白必看:收藏这份极简AI-Agent学习指南,开启高薪职业新赛道!
  • 2026 AI决战:小白也能抓住大模型红利,速收藏!
  • 2026市政交通标志牌优质厂家推荐榜 - 优质品牌商家
  • 保姆级教程:用Python和pyrealsense2一键获取D435深度相机的内参矩阵
  • 例子-子网划分问题
  • EtherCAT模块化实战:如何为你的设备设计可热插拔的IO模块(基于SSC与0x4711示例)
  • 200元最好用的头戴式耳机是哪款?2026平价头戴式耳机排行榜10强品牌
  • Gemini 3 实战手册:从新手到高手的进阶之路
  • 2026年家用电器淘宝代运营公司排名前五权威深度测评 - 电商资讯
  • C++的std--ranges集合操作
  • Spring-AI大模型集成指南:轻松上手,收藏必备,小白也能玩转AI!
  • PowerShell网络管理实战:从基础配置到高级路由优化
  • 浒浦潮汐表查询2026-03-28
  • 高温寻北MEMS陀螺,为极端钻井打造精准指向
  • 嵌入式轻量级四元数姿态运算库:纯数学、零依赖、高实时
  • ngx_http_init_locations
  • 从零开始刷力扣1(9.回文数)
  • Qwen3.5-2B微调保姆级教程(非常详细),LoRA实战从入门到精通,收藏这一篇就够了!
  • 小白必看!收藏这份Agent思维链技术指南,轻松入门大模型世界