【Linux驱动】设备树中指定中断 | 驱动中获得中断 | 按键中断实验

🐱作者:一只大喵咪1201
🐱专栏:《Linux驱动》
🔥格言:你只管努力,剩下的交给时间!
图

目录

  • 🏀在设备树中指定中断
  • 🏀代码中获得中断
  • 🏀按键中断
    • ⚽驱动程序
    • ⚽设备树
    • ⚽上机实验
  • 🏀总结

🏀在设备树中指定中断

图
继续拿这个中断流程图来说话。

在硬件上,中断控制器只有GIC这一个,但是我们在软件上可以把GPIO也归类为中断控制器。

芯片会有多个GPIO模块,所以软件上的中断控制器就会有很多个:GIC,GPIO1,GPIO2,GPIO3…等等。

其中GPIO1、GPIO2、GPIO3这些中断控制器模块都连接汇集到GIC模块,所以GIC模块就是GPIOx模块的父亲。

假设GPIO1有32个中断源,但是它把其中的16个汇聚起来向GIC发出一 个中断,把另外16个汇聚起来向GIC发出另一个中断。这就意味着GPIO1会用到 GIC 的两个中断,会涉及 GIC 里的 2 个 hwirq

  • 这些层级关系、中断号(hwirq),都会在设备树中有所体现。

dtsi:

图
如上图所示由BSP工程师提供的dtsi设备树文件:

  • intc:表示GIC中断控制器。
  • gpio1:表示GPIO1中断控制器。
  • gpio2:表示GPIO2中断控制器。

GIC是顶层中断控制器,所以它没有父亲,而GPIO1和GPIO2都是soc的子节点,子节点会继承父节点的属性

  • interrupt-parent = <&gpc>:表示父亲节点,soc节点的interrupt-parent = <&gpc>
  • GPIO1和GPIO2继承socinterrupt-parent = <&gpc>属性,所以它们的父节点也是gpc

本喵没有列出来,gpc的父节点是GIC中断控制器,所以从设备树反推出IMX6ULL的中断框图,它比之前多了一个GPC INTC

图
如上图所示新的中断框图,GPC INTC的功能是提供中断屏蔽、中断状态查询等功能。

  • 实际上这些功能在GIC中也实现了。
  • 之所以保留它是因为它还能提供唤醒功能。

继续回到dtsi设备树文件来看,每一个中断控制器中都有两个必须的属性:

  • interrupt-controller:该属性表明它是中断控制器。
  • #interrupt-cells:该属性表明引用这个中断控制器的话需要多少个cell
    • #interrupt-cells=<1>:别的节点要使用这个中断控制器时,只需要一个 cell来表明使用哪一个中断。
    • #interrupt-cells=<2>:别的节点要使用这个中断控制器时,需要两个cell,其中第一个来表明使用哪一个中断,第二个一般来描述中断的触发类型。

由于GIC规定了要引用该中断控制器需要使用3个cell,所以GPIO1和GPIO2就使用了<GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>这样的3个cell

  • GIC_SPI:GPIO模块向GIC发出中断的类型。
  • 66:GPIO模块向GIC发出中断的硬件中断号hirq
  • IRQ_TYPE_LEVEL_HIGH:GPIO模块向GIC发出中断的触发类型。

除了引用GIC中断控制器外,GPIOx模块也有自己的interrupt-controller属性和#interrupt-cells = <2>属性:

  • GPIO1和GPIO2中断控制器模块规定引用该控制器时需要使用两个cell

这是都是芯片厂家写好的,提供给我们使用的,我们只需要知道怎么去用它们就行。

dts:

图
如上图我们写的dts设备树文件中,这是一个spidev节点:

  • interrupt-parent = <&gpio1>:该设备的父节点是gpio1,表明该外部设备引用GPIO1控制器。
  • interrupts = <1 1>:表示该设备使用的硬件中断号hirq是1,触发类型是1。
    • 新写法interrupts-extend:一个这样的属性就可以既指定interrupt-parent又指定interrupts
    • 比如interrupts-extend = <&gpio1 1 1>

触发类型这里写的1,代表什么意思呢?有写什么类型呢?

tu
如上图所示,1就代表着low-to-high edge triggered上升沿触发。

如此一来,在设备树中指定了该外部设备的中断,在驱动程序中就可以直接使用了。

🏀代码中获得中断

我们知道,设备树中的节点有的会被内核转化为platform_device结构体,有些则不会。

对于能转化为platform_device结构体的节点,如果它在设备树里指定了中断属性,那么可以从platform_device中获得中断资源:

图
如上图所示platform_get_resource函数,用来获取中断资源:

  • dev:转化后的platform_device结构体指针。
  • type:获取哪类资源。
    • IORESOURCE_MEMIORESOURCE_REGIORESOURCE_IRQ 等。
  • num:这类资源中的哪一个。
    • 一个节点中使用不止一个中断源。

对于I2C设备、SPI设备,总线驱动在处理设备树里的I2C子节点时,也会处理其中的中断信息。

  • 一个I2C设备会被转换为一个i2c_client结构体,中断号会保存在i2c_clientirq成员里。

图
如上图代码所示,当I2C总线和驱动程序匹配以后,会自动调用probe函数,在该函数中使用of_irq_get函数,从它的子节点I2C设备中解析出中断号irq

  • 一个 SPI 设备会被转换为一个spi_device结构体,中断号会保存在spi_deviceirq成员里。

图
如上图,当SPI总线和驱动程序匹配后,在它的probe函数中,也会调用of_irq_get从子节点SPI设备中解析出中断号irq

如果设备节点既不能转换为platform_device,也不是I2C和SPI设备,那么在驱动程序中,可以自行调用of_irq_get函数去解析得到中断号。


对于GPIO引脚,芯片厂家提供了专门的接口函数来获取中断:

  • of_get_gpio_flags:使用该函数获取GPIO引脚,此时获取到的是使用老的方式描述GPIO引脚信息的那个整数。
  • gpio_to_desc:使用该函数获取GPIO引脚,获得是使用新方式描述GPIO引脚信息的那个desc结构体。
  • gpiod_to_irq:最后使用该函数从得到的GPIO引脚信息中获得软件中断号。

🏀按键中断

对于 GPIO 按键,我们并不需要去写驱动程序,使用内核自带的驱动程序 drivers/input/keyboard/gpio_keys.c就可以,然后需要做的只是修改设备树指定引脚及键值。

但是本喵还是要从头写一遍按键驱动程序,特别是如何使用中断,因为中断是其他基础知识的前提,以后的休眠-唤醒,POLL机制,异步通知,定时器,中断的线程化处理等内容都离不开中断。

图
如上图所示本喵使用的IMX6ULL开发板原理图,按键KEY1和按键KEY2使用的是GPIO5_1GPIO4_14两个引脚,并且是低电平有效。

同样的,按键驱动程序也要分为驱动程序和设备树两部分。

⚽驱动程序

图
如上图所示gpio_key_drv.c文件中的驱动程序:

  • 创建platform_driver结构体gpio_keys_driver,并且进行初始化。
    • 使用gpio_key_probe初始化probe函数。
    • 使用gpio_key_remove初始化remove函数。
    • 使用of_device_id数组Big_Miaomi_keys初始化driver.of_match_table
      • 数组中compatible属性的值是"Big_Miaomi,gpio_keys",用来和设备节点匹配。
  • 在入口函数gpio_key_init中使用platform_driver_register函数向内核注册驱动程序。
  • 在出口函数gpio_key_exit中使用platform_driver_unregister从内核中取消驱动程序注册。
  • 完善设备驱动信息。
  • 由于这是按键中断,不需要应用层来调用,所以不用在/dev下创建设备节点,也不用注册file_operations结构体。

probe函数:

图
如上图所示probe函数的实现:

  • 定义全局一个结构体指针gpio_keys_Big_Miaomi,该结构体是struct gpio_key 类型,用来存放中断的信息。
  • 使用of_gpio_count获得中断源个数,因为一个设备节点可能有多个中断源。
    • 按键设备可能有多个按键,此时就有多个中断源。
  • 使用内核的kzalloc函数在堆区上开辟一段堆空间,来存放中断信息。
  • 每一个中断源,都需要获取它的详细信息:
    • 使用of_get_gpio_flags获取中断的引脚信息gpio和有效标志。
    • 将用整数描述的引脚信息转换成使用gpio_desc类型描述的引脚信息。
    • 将中断引脚设置成低电平有效,与OF_GPIO_ACTIVE_LOW相与。
      • 因为电路中按键是低电平有效,原本的引脚标志是输入GPIOF_IN
    • 再使用devm_gpio_request_one将引脚状态设置成逻辑值。
      • 按键按下后,读取到的引脚值是1,尽管物理值是0。
    • 使用gpio_to_irq获取中断引脚的软件中断号irq

将所有中断信息获取到以后,再为每一个中断注册中断函数:

  • 使用request_irq注册中断服务函数:
    • 第一个参数传入中断的软件中断号gpio_keys_Big_Miaomi[i].irq
    • 第二个参数传入中断服务函数gpio_key_isr
    • 第三个参数传入中断触发方式IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING双边沿触发。
    • 第四个参数传入中断名称"100ask_gpio_key",该参数不重要。
    • 第五个参数传入dev_id,也就是中断信息所在的结构体指针&gpio_keys_Big_Miaomi[i]

此时中断函数就注册完成了,接下来就是实现中断服务函数中要做什么:

图
如上图所示中断服务函数,在里面仅获取引脚电平的逻辑值,并且打印出描述引脚的那个整数编号和引脚状态。

remove函数:

tu
如上图所示remove函数,在卸载驱动程序时:

  • 使用free_irq将所有前面注册的中断释放掉。
  • 使用kfree将存放引脚信息的堆空间释放掉。

⚽设备树

图
如上图所示蓝色框中代码,使用图形化工具生成GPIO5_1GPIO4_14的两个pin-controller节点代码。

图
如上图所示,将生成的pin-controller节点代码复制到我们要写的dts设备树文件中:

  • GPIO5_1:节点名称为Big_Miaomi_key1,表示按键1。
  • GPIO4_14:节点名称为Big_Miaomi_key2,表示按键2。

图
如上图所示,在dts设备树文件的根节点下,增加按键外部设备节点gpio_keys_Big_Miaomi

  • 使用GPIO子系统指定按键引脚和有效电平。
  • 使用Pinctrl子系统将引脚复用为通用GPIO功能。
  • 在原本的gpio-keys节点中,使用status = "disabled"属性让该节点失能,防止影响我们自己创建的按键节点。
  • 这里并没有在设备树中指定按键的interrupts-extend
  • 因为对于GPIO,芯片厂家提供了驱动程序中的一些列接口,可以直接获取GPIO的中断信息,包括中断号以及中断控制器等。

⚽上机实验

图
如上图所示,使用上面的makefile文件编译驱动程序,生成gpio_key_drv.ko驱动模块。

图
如上图所示,将写好的gpio_key_drv.c驱动程序和设备树文件,以及Makefile上传到服务器上,分别进行编译,编程成功后将生成的gpio_key.kodtb文件都拷贝到网络文件系统中供开发板使用。

图
如上图所示,先让开发板使用新的dtb设备树文件,再使用insmod安装gpio_key_drv.ko驱动模块,可以看到安装成功后输出匹配porbe函数的调试信息。

图
如上图所示,按下开发板上的KEY1KEY2时:

  • 按键按下,按键值是1,松开按键值是0。
  • 按键值前面的整数就是描述按键引脚的编号。

🏀总结

要知道在设备树中是如何描述一个设备的中断的,包括父节点interrupt-parent属性,以及描述中断引脚的interrupts属性的用法。

还要知道在中断程序中是如何获取设备树中的中断信息的,以及如何使用这些中断信息。

最后要会实现按键中断程序。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/628071.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

闪存剩下内容

1&#xff1a;通过Arduino IDE向闪存文件系统上传文件 1. 下载 Arduino-ESP8266闪存文件插件程序 2&#xff1a;使用闪存文件系统建立功能更加丰富的网络服务器 1&#xff1a;在网页中加载闪存文件系统中的图片、CSS和JavaScript index.html&#xff1a;ESP8266开发板建立的网…

SpringBoot+SSM项目实战 苍穹外卖(12) Apache POI

继续上一节的内容&#xff0c;本节是苍穹外卖后端开发的最后一节&#xff0c;本节学习Apache POI&#xff0c;完成工作台、数据导出功能。 目录 工作台Apache POI入门案例 导出运营数据Excel报表 工作台 工作台是系统运营的数据看板&#xff0c;并提供快捷操作入口&#xff0c…

初识OpenCV

首先你得保证你的虚拟机Ubuntu能上网 可看 http://t.csdnimg.cn/bZs6c 打开终端输入 sudo apt-get install libopencv-dev 回车 输入密码 回车 遇到Y/N 回车 OpenCV在线文档 opencv 文档链接 点zip可以下载&#xff0c;点前面的直接在线浏览&#xff0c;但是很慢 https…

单元测试:Testing leads to failure, and failure leads to understanding

单元测试的概念可能多数读者都有接触过。作为开发人员&#xff0c;我们编写一个个测试用例&#xff0c;测试框架发现这些测试用例&#xff0c;将它们组装成测试 suite 并运行&#xff0c;收集测试报告&#xff0c;并且提供测试基础设施&#xff08;断言、mock、setup 和 teardo…

JAVAEE初阶 文件IO(一)

这里写目录标题 一. 计算机中存储数据的设备1.1 CPU1.2 内存1.3 硬盘1.4 三种存储的区别 二.文件系统2.1 相对路径2.2 绝对路径2.3 .和..的含义2.4 例子2.5 everything工具 三.文件3.1 文本文件3.2 二进制文件 四. JAVA对于文件的API4.1 getParent getName getPath getAbsolute…

Jest单元测试:玩转代码的小捉迷藏!

Jest Jest 是什么&#xff1f; Jest 是一个流行的 JavaScript 测试框架&#xff0c;专注于简化和改进代码的测试流程。它由 Facebook 开发并维护&#xff0c;具有以下特点&#xff1a; 1、易用性&#xff1a;Jest 提供了一个简单而强大的测试框架&#xff0c;使得编写和运行测…

uniapp h5 发行后 微信第二次打开网址 页面白屏

发行后把网址给客户&#xff0c;第一次可以正常登录打开&#xff0c;第二次打开白屏 原因&#xff1a;第一次打开时没有token&#xff0c;所以跳转登录页&#xff0c;可以正常访问 第二次打开时有token&#xff0c;但是网址根目录没有配置默认页面&#xff0c;所以白屏 解决…

Windows Server调整策略实现999999个远程用户用时登录

正文共&#xff1a;1234 字 23 图&#xff0c;预估阅读时间&#xff1a;2 分钟 上篇文章中&#xff08;Windows Server 2019配置多用户远程桌面登录服务器&#xff09;&#xff0c;我们主要介绍了Windows Server 2019在配置远程桌面时&#xff0c;如何通过3种方式创建本地用户账…

使用Qt连接scrcpy-server控制手机

Qt连接scrcpy-server 测试环境如何启动scrcpy-server1. 连接设备2. 推送scrcpy-server到手机上3. 建立Adb隧道连接4. 启动服务5. 关闭服务 使用QTcpServer与scrcpy-server建立连接建立连接并视频推流完整流程1. 开启视频推流过程2. 关闭视频推流过程 视频流的解码1. 数据包协议…

NVMe系统内存结构 - Meta Data

NVMe系统内存结构 - Meta Data 1 为什么需要数据保护2 Meta Data定义3 Meta Data传输方式4 常见Meta Data使用场景4.1 不带数据保护信息4.2 带数据保护信息“数据写”流程4.3 带数据保护信息“数据读”流程4.4 SSD内部加入数据保护信息4.5 SSD内部根据数据保护信息验证数据 本文…

如何在你的网站接入QQ登录?

文章目录 准备阶段申请QQ登录的权限创建应用最后上传qqlogin.php代码 准备阶段 国内服务器和备案域名需要你有张独一无二本人的身份证你正面手持身份证的图片一张100px*100px的网站图标 申请QQ登录的权限 首先访问qq互联&#xff0c;点击我直接访问 登陆完成后我们点击面的…

bash shell基础命令(一)

1.shell启动 shell提供了对Linux系统的交互式访问&#xff0c;通常在用户登录终端时启动。系统启动的shell程序取决于用户账户的配置。 /etc/passwd/文件包含了所有用户的基本信息配置&#xff0c; $ cat /etc/passwd root:x:0:0:root:/root:/bin/bash ...例如上述root账户信…

Python新年文字烟花简单代码

简单的Python新年烟花代码示例&#xff1a; import random import timedef create_firework():colors [红色, 橙色, 黄色, 绿色, 蓝色, 紫色]flashes [爆裂, 闪光, 旋转, 流星, 喷射]color random.choice(colors)flash random.choice(flashes)print(f"发射一枚{color…

redis之单线程和多线程

目录 1、redis的发展史 2、redis为什么选择单线程&#xff1f; 3、主线程和Io线程是怎么协作完成请求处理的&#xff1f; 4、IO多路复用 5、开启redis多线程 1、redis的发展史 Redis4.0之前是用的单线程&#xff0c;4.0以后逐渐支持多线程 Redis4.0之前一直采用单线程的主…

GUI编程(函数解析以及使用)

1.介绍 AWT&#xff08;Abstract Window Toolkit&#xff09;和Swing 是 Java 提供的用于创建图形用户界面&#xff08;GUI&#xff09;的类库。 AWT&#xff1a;AWT 是 Java 最早提供的 GUI 类库&#xff0c;它基于本地平台的窗口系统&#xff0c;使用操作系统的原生组件进行…

文件的创建时间可以修改吗,怎么改?

文件的创建时间可以修改吗&#xff0c;怎么改&#xff1f;文件的创建时间是由操作系统自动生成并记录的&#xff0c;通常情况下无法直接修改。创建时间是文件的属性之一&#xff0c;它反映了文件在文件系统中的生成时间。一旦文件被创建&#xff0c;其创建时间就被确定下来&…

Vulnhub-tr0ll-1

一、信息收集 端口收集 PORT STATE SERVICE VERSION 21/tcp open ftp vsftpd 3.0.2 | ftp-anon: Anonymous FTP login allowed (FTP code 230) |_-rwxrwxrwx 1 1000 0 8068 Aug 09 2014 lol.pcap [NSE: writeable] | ftp-syst: | STAT: | FTP …

分布式搜索——Elasticsearch

Elasticsearch 文章目录 Elasticsearch简介ELK技术栈Elasticsearch和Lucene 倒排索引正向索引倒排索引正向和倒排 ES概念文档和字段索引和映射Mysql与Elasticsearch 安装ES、Kibana安装单点ES创建网络拉取镜像运行 部署kibana拉取镜像部署 安装Ik插件扩展词词典停用词词典 索引…

Linux 内核大转变:是否将迈入现代 C++ 的时代?

Linux开发者 H. Peter Anvin 在邮件列表中重启了关于 Linux内核C代码转换为C的讨论&#xff0c;并陈述了自己的观点。说之前先看一下这个话题的历史背景。 早在2018年4月1日&#xff0c;Andrew Pinski提议将 Linux 内核源码转为 C&#xff0c;在文中写道之所以引入是由于以下优…

centos7配置时间同步网络时间

centos7配置时间同步网络时间 1、安装 NTP 工具。 sudo yum install -y ntp2启动 NTP 服务。 sudo systemctl start ntpd3、将 NTP 服务设置为开机自启动。 sudo systemctl enable ntpd4、验证 date