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

驱动开发硬核特训 · Day 17:深入掌握中断机制与驱动开发中的应用实战

🎥 视频教程请关注 B 站:“嵌入式 Jerry”


一、前言

在嵌入式驱动开发中,“中断”几乎无处不在。无论是 GPIO 按键、串口通信、网络设备,还是 SoC 上的各种控制器,中断都扮演着核心触发机制的角色。对中断机制掌握程度的高低,直接影响到你驱动开发水平的深度。

本篇将从以下结构展开:

  • 中断的基本概念与分类
  • Linux 内核中的中断框架
  • request_irq() 的实战用法与原理解析
  • 中断处理函数与上下半部机制
  • 中断在 DTS 中的描述与匹配方式
  • 实战:为一个 GPIO 按键注册中断
  • 调试技巧与常见误区

二、中断基础概念

2.1 什么是中断?

中断(Interrupt)是指处理器在运行过程中,外部设备或内部条件发生特定事件时,打断当前正在执行的任务,转而执行一个中断服务程序(ISR)的机制。

2.2 中断的分类

类型描述
外部中断外设发出的信号,如 GPIO、UART、定时器等
内部中断处理器内部事件触发,如异常、软中断等
边沿触发在电平变化的瞬间触发(如上升沿、下降沿)
电平触发在保持某一电平时持续触发(如高电平、低电平)

三、Linux 内核中的中断机制

Linux 内核为中断提供了统一的框架,通过 IRQ(Interrupt Request)编号管理设备之间的中断。
在这里插入图片描述

3.1 中断号(IRQ number)

每个硬件中断都被映射为一个唯一的 IRQ 号,Linux 内核使用这个编号来注册/处理中断。

可通过如下命令查看系统中断分配:

cat /proc/interrupts

3.2 request_irq() 的框架

int request_irq(unsigned int irq,irq_handler_t handler,unsigned long flags,const char *name,void *dev);
参数含义
irq要申请的中断号
handler中断服务函数
flags触发方式,如 IRQF_TRIGGER_FALLING 等
name中断名称,用于 /proc/interrupts 识别
dev通常为 pdev 或私有结构体指针,用于共享中断区分

四、中断处理函数与上下半部机制

中断处理时间越短越好,因此 Linux 提供 中断上下半部机制

部分描述
上半部(top half)中断刚发生时的 ISR(中断服务函数),需快速返回
下半部(bottom half)通过 tasklet、workqueue 等机制延迟处理

示例:使用 workqueue 实现下半部

static void my_work_handler(struct work_struct *work)
{pr_info("Bottom half executed.\n");
}static DECLARE_WORK(my_work, my_work_handler);static irqreturn_t my_irq_handler(int irq, void *dev)
{schedule_work(&my_work);return IRQ_HANDLED;
}

五、设备树中断描述与解析

5.1 DTS 中的中断定义

button@0 {compatible = "gpio-keys";gpios = <&gpio3 19 GPIO_ACTIVE_LOW>;linux,code = <KEY_ENTER>;label = "Enter Button";interrupt-parent = <&gpio3>;interrupts = <19 IRQ_TYPE_EDGE_FALLING>;
};

5.2 驱动中解析中断号

irq = of_irq_get(np, 0);
ret = request_irq(irq, handler, IRQF_TRIGGER_FALLING, "button", dev);

六、实战讲解:为 GPIO 按键注册中断

以下是一个完整的按键中断驱动代码片段:

static irqreturn_t button_isr(int irq, void *dev_id)
{pr_info("Button interrupt triggered!\n");return IRQ_HANDLED;
}static int btn_probe(struct platform_device *pdev)
{int irq;struct device_node *np = pdev->dev.of_node;irq = of_irq_get(np, 0);if (irq < 0)return irq;return devm_request_irq(&pdev->dev, irq, button_isr,IRQF_TRIGGER_FALLING, "button", NULL);
}

驱动匹配表

static const struct of_device_id btn_of_match[] = {{ .compatible = "myvendor,button" },{ }
};
MODULE_DEVICE_TABLE(of, btn_of_match);

七、调试技巧与排错建议

7.1 无法响应中断?

  • 检查 of_irq_get() 返回值
  • 确保设备树中 interrupt-parent 正确
  • 查看内核是否启用了相应的 GPIO 中断支持
  • 使用 cat /proc/interrupts 观察中断是否触发计数增加

7.2 中断多次触发?

  • 检查 IRQF_TRIGGER_* 设置是否与实际硬件匹配
  • 排查上拉/下拉电阻或信号抖动问题

八、问答环节总结

Q1:一个驱动中能注册多个中断吗?

可以。使用 request_irq() 多次注册不同 irq。

Q2:可以使用中断做耗时操作吗?

不建议。应放入下半部如 workqueue 中。

Q3:中断共享怎么办?

设置 IRQF_SHARED,并正确传入 dev_id 区分中断源。

Q4:中断服务函数可以被抢占吗?

在默认情况下,中断服务函数运行在中断上下文,不能被抢占,但可以被更高优先级中断打断。


九、总结提炼

关键点说明
中断是驱动中的基础机制几乎所有外设都依赖中断响应事件
request_irq() 是核心接口注册中断的入口函数
使用设备树描述中断资源通过 interrupts + interrupt-parent 精确匹配
上下半部机制非常重要把耗时操作放到 workqueue/tasklet
实战中注意调试利用 /proc/interrupts 和日志追踪触发行为

✅ 今日作业建议

  1. 在你的开发板上找一个 GPIO 按键,编写设备树 + 驱动注册中断。
  2. 使用 printk 或 dev_info() 输出中断触发信息,验证中断触发次数。
  3. 尝试通过 workqueue 延迟执行中断下半部逻辑,如点亮 LED。

🎥 视频教程请关注 B 站:“嵌入式 Jerry”


相关文章:

  • MYSQL的binlog
  • 《棒球规则》全明星比赛规则·棒球1号位
  • 爱普生FC1610BN晶体在健康监测手环的应用
  • 使用Python设置excel单元格的字体(font值)
  • JavaScript 扩展Array类方法实现数组求和
  • 【网络应用程序设计】实验一:本地机上的聊天室
  • 代码随想录训练营38天 || 322. 零钱兑换 279. 完全平方数 139. 单词拆分
  • 从零开始学习MySQL的系统学习大纲
  • HCIP(综合实验2)
  • 每日算法-哈希表(两数之和、)
  • el-table表格既出现横向滚动条,又出现纵向滚动条?
  • YOLOv8非常详细的模型的训练两种方式
  • 文件上传漏洞2
  • <四级英语词汇> 2025.4.22
  • Cursor Free VIP 重置进程错误,轻松恢复使用!
  • 三网通电玩城平台系统结构与源码工程详解(四):子游戏集成与服务器调度机制全解
  • Java学习手册:RESTful API 设计原则
  • MQ底层原理
  • 强化学习笔记(四)——SARSA、Q-learning
  • 伪谱法求解最优控制问题(附Python代码)
  • 广西一季度GDP为6833.92亿元,同比增长5.8%
  • 金发科技去年净利增160%,机器人等新领域催生材料新需求
  • 广电总局加快布局超高清视听产业链,多项成果亮相
  • 为什么要读书?——北京地铁春季书单(2025)
  • 万斯偕印裔妻子访问印度,4天行程能否推进美印贸易谈判?
  • 普京签署法律,诋毁俄军将面临最高7年监禁