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

Linux 中断驱动程序--按键中断驱动

一、为什么需要中断驱动?

在嵌入式 Linux 开发中,按键是最常见的输入设备之一。如果使用轮询(Polling)方式检测按键状态,CPU 需要不停地读取 GPIO 电平,这会极大地浪费系统资源,导致 CPU 无法处理其他任务。
中断(Interrupt)机制则是解决这一问题的完美方案:

  • 被动响应:CPU 仅在按键按下(或抬起)时才收到通知并进行处理。
  • 高实时性:硬件电平变化触发中断,系统能立即响应。
  • 低功耗:CPU 大部分时间处于空闲或处理其他任务的状态,无需忙等。

二、驱动核心结构

1.代码结构分析

  • 内核驱动 :负责 GPIO 初始化、中断申请、数据读取逻辑。
  • 应用测试 :负责打开设备节点并调用 read() 函数获取按键状态。
  • 设备树节点:描述硬件资源(GPIO 编号、中断触发方式)。

2. 工作流程图

  1. 初始化:驱动加载,解析设备树,申请 GPIO 和中断。
  2. 阻塞等待:用户程序调用 read(),驱动将其加入等待队列并休眠。
  3. 中断触发:按键按下,硬件产生中断,执行中断处理函数。
  4. 唤醒进程:中断处理函数唤醒等待队列中的进程,read() 返回按键值。

三、代码实现详解

1.中断处理函数 (key_irq_handler)
static irqreturn_t key_irq_handler(int irq, void * dev) { int arg = *(int *)dev; // 获取传入的参数 if(100 != arg) return IRQ_NONE; // 简单的参数校验 condition = 1; // 核心逻辑:设置条件为真 wake_up_interruptible(&wq); // 唤醒在 wq 队列上睡眠的进程 printk("irq = %d dev = %d\n", irq, arg); return IRQ_HANDLED; }
  • 中断上下文原则:ISR 必须快速执行。它只做最必要的事情——设置标志位和唤醒进程,避免任何可能引起休眠的操作(如copy_to_user)。
  • 唤醒机制wake_up_interruptible是与wait_event_interruptible完美配对的函数,它能将处于可中断睡眠状态的进程标记为可运行,由调度器决定何时恢复其执行。
2.. 文件操作:读取函数 (read)

这是驱动与应用交互的接口。

static ssize_t read(struct file * file, char __user * buf, size_t size, loff_t * loff) { int ret = 0; int status = 0; condition = 0; // 1. 重置条件标志 wait_event_interruptible(wq, condition); // 2. 进程在此处睡眠,直到 condition != 0 status = 1; // 3. 被唤醒后执行 ret = copy_to_user(buf, &status, sizeof(status)); // 4. 将数据传回用户空间 return sizeof(status); }
  • 阻塞式设计:wait_event_interruptible 宏实现了优雅的阻塞逻辑。当条件不满足时,进程主动让出 CPU;一旦被唤醒,它会自动重新检查条件并继续执行。
  • 2. 用户/内核空间隔离:必须使用 copy_to_user 将内核数据安全地拷贝到用户空间缓冲区,直接赋值会导致内核崩溃(Oops)。
3.平台驱动探针 (probe)
static int probe(struct platform_device * pdev) { // 1. 查找设备树节点 pdts = of_find_node_by_path("/ptkey"); // 2. 获取 GPIO 和 中断号 key_gpio = of_get_named_gpio(pdts, "ptkey-gpio", 0); key_irq = irq_of_parse_and_map(pdts, 0); // 3. 申请中断 request_irq(key_irq, key_irq_handler, IRQF_TRIGGER_FALLING, "key0_irq", &arg); // 4. 初始化等待队列 init_waitqueue_head(&wq); return 0; }
  • 设备树驱动模型:通过 of_find_node_by_path 和 of_get_named_gpio 等 API,驱动代码与具体的硬件地址解耦,使得同一份驱动可以适配不同的硬件平台。
  • 资源生命周期管理:在 probe 中申请的资源(GPIO、IRQ),必须在对应的 remove 函数中正确释放,否则会造成资源泄漏。
4.模块初始化与退出
static int __init key_driver_init(void) { platform_driver_register(&pdrv); // 注册平台驱动 } static void __exit key_driver_exit(void) { platform_driver_unregister(&pdrv); // 注销平台驱动 }
  • 模块入口/出口:__init 和 __exit 宏告诉内核这些函数只在模块加载/卸载时使用,之后其占用的内存可以被回收,优化了内核内存。
  • 平台总线注册:通过 platform_driver_register 将驱动注册到 Linux 的 Platform 总线上,使其能够被设备树中的匹配节点发现并调用 probe。

四、应用测试:key_app.c

1.主函数逻辑
int main(int argc, const char *argv[]) { int fd = open("/dev/key", O_RDWR); // 打开设备节点 int status = 0; while(1) { int ret = read(fd, &status, sizeof status); // 调用驱动的 read 函数 printf("ret = %d status = %d\n", ret, status); } close(fd); return 0; }
  • 标准文件操作:应用程序完全将设备视为一个普通文件,通过 open、read、close 这些 POSIX 标准接口进行交互,体现了 Linux “一切皆文件” 的设计哲学。
  • 同步阻塞行为:read 调用在此处是同步且阻塞的。程序会一直停在此行,直到内核驱动有数据返回(即按键被按下),这简化了应用层的逻辑,无需自行管理轮询或异步通知。

五、 关键技术点总结

  1. 非轮询机制:相比传统的 while 循环读取 GPIO 电平,这种 中断 + 等待队列 的方式更加高效,不占用 CPU 资源。
  2. 设备树解耦:驱动代码不包含具体的硬件地址,而是通过设备树节点(/ptkey)动态获取 GPIO 和 IRQ,提高了驱动的通用性。
  3. 阻塞 I/O:wait_event_interruptible 和 wake_up_interruptible 是成对使用的宏/函数,是实现阻塞型驱动的标准范式。
  4. 参数传递:代码中使用 &arg 作为中断共享参数,虽然本例中仅用于演示,但在多设备驱动中,通常会传递指向设备私有数据结构(struct key_dev)的指针。
http://www.jsqmd.com/news/362642/

相关文章:

  • 【开题答辩全过程】以 基于SpringBoot云旅行微信小程序的设计和实现为例,包含答辩的问题和答案
  • 2026年高口碑系统门窗五金和五金配件产品推荐排行榜,提升家装体验 - 睿易优选
  • 2026年智能工厂规划全流程解析:浙江及江苏优秀企业推荐 - 孟哥商业圈
  • AI应用架构师分享:智能产品推荐AI系统的模型压缩技术
  • 2026年公司注册厂家权威推荐榜:南非公司注册、境外投资备案ODI公司、广州境外投资备案ODI、德国公司注册选择指南 - 优质品牌商家
  • AI 时代的前端技术:从系统编程到 JavaScript/TypeScript
  • 【claude】Claude 如何节省 Token?10 个实用技巧让成本降低 70%
  • 2026年评价高的不锈钢烟囱塔公司推荐:碳钢烟囱塔、角钢监控塔、道路监控塔、钢管监控塔、镀锌烟囱塔架选择指南 - 优质品牌商家
  • 2026年实测对比:宁波智能工厂规划服务商TOP5深度解析 - 孟哥商业圈
  • 【开题答辩全过程】以 河市富达购物微信小程序为例,包含答辩的问题和答案
  • 2026四川加气砖优选指南:从蒸压砌块到轻质隔墙的五家可靠之选 - 深度智识库
  • 递归思想的思路分享
  • Flutter for OpenHarmony 习惯养成 App:用打卡机制打造自律生活的可视化引擎
  • 【claude】最新Claude Opus 4.6 深度评测:AI编程工具的新王者诞生!
  • 深入解析:小白也能看懂的DeepSeek-R1本地部署指南
  • Flutter for OpenHarmony音乐播放器实战:打造动态波形可视化与沉浸式播放体验
  • 2026年自动洗瓶机厂家推荐:饮料瓶洗瓶机/啤酒瓶洗瓶机/回收瓶洗瓶机/实验室洗瓶机/毛刷式洗瓶机/选择指南 - 优质品牌商家
  • Flutter for OpenHarmony BMI 健康计算器:打造支持深色模式的智能健康工具
  • 【开题答辩全过程】以 基于Springboot图书管理系统为例,包含答辩的问题和答案
  • 2026年碰碰车厂家推荐:逍遥乐吧车/360摇滚乐吧车/亲子双人碰碰车/公园碰碰车/发光漂移碰碰车/商场碰碰车/选择指南 - 优质品牌商家
  • 2026年实测TOP3智能工厂规划服务商深度对比 - 孟哥商业圈
  • P3195 [HNOI2008] 玩具装箱
  • 题解:AWC 0001
  • 2026牛客寒假算法基础集训营4 题解
  • 2026年评价高的三柱避雷塔公司推荐:监控铁塔、角钢监控塔、角钢避雷塔、道路监控塔、钢管避雷塔、镀锌监控塔架选择指南 - 优质品牌商家
  • AI不是在杀死SaaS,而是在逼传统软件回到它真正值钱的那一层
  • YouTube 文字转语音怎么用?AI 配音提升效率与内容产出的完整指南
  • 2026年江西新工厂规划避坑指南:五大服务商深度评测;江西五大公司排名与常见误区解析 - 孟哥商业圈
  • 只知道WinPE?这款两款Linux PE维护系统,轻松化解Linux运维难题
  • AWC_0001 Beta