【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.mfbz.cn/a/322299.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python教程79:关于海龟画图,Turtle模块需要学习的知识点

1.海龟画图的基本步骤&#xff1a;A-B-C-D-E-F A.导入turtle模块&#xff1a;首先需要导入Python中的turtle模块&#xff0c;该模块提供了海龟绘图所需的基本函数和属性。 import turtle as tB.设置画布大小 使用turtle.screensize()函数。该函数可以设置画布的宽度高度背景…

中小企业如何做好信息化规划?

中小企业需不需要做信息化规划&#xff1f;什么时候做信息化规划比较好&#xff1f; 企业的信息化规划&#xff0c;一定是越早越好&#xff0c;越快越好。 因为信息化是一个过程&#xff0c;不是一个结果&#xff0c;它不是一天完成的事情&#xff0c;而是贯穿着企业经营管理…

FPGA引脚 Bank认知--FPGA 选型的一些常识

关键字 HP I/O Banks, High performance The HP I/O banks are deisgned to meet the performance requirements of high-speed memory and other chip-to-chip interface with voltages up to 1.8V. HR I/O Banks, High Range The HR I/O banks are designed to support a wid…

用python提取PDF中各类文本内容的方法

从PDF文档中提取信息&#xff0c;是很多类似RAG这样的应用第一步要处理的事情&#xff0c;这里需要做好三件事&#xff1a; 提取出来的文本要保持信息完整性&#xff0c;也就是准确性提出的结果需要有附加信息&#xff0c;也就是要保存元数据提取过程要完成自动化&#xff0c;…

FPGA四选一的多路选择器(用三元运算符?:解决)

一. 三元运算符? :用法 ?:符号通常用于条件运算符&#xff0c;表示条件判断。它类似于C语言中的三元运算符&#xff0c;用于根据条件选择不同的操作或值。 例如&#xff0c;在Verilog中&#xff0c;条件运算符?:可以用于if-else语句的简写形式。它的一般语法格式如下&#x…

市场复盘总结 20240113

仅用于记录当天的市场情况&#xff0c;用于统计交易策略的适用情况&#xff0c;以便程序回测 短线核心&#xff1a;不参与任何级别的调整&#xff0c;采用龙空龙模式 昨日主题投资 连板进级率 100% 二进三&#xff1a; 进级率低 14% 最常用的二种方法&#xff1a; 方法一&a…

IIC学习之SHT30温湿度传感器(基于STM32)

简介 附上SHT30资料和逻辑分析仪源文件&#xff0c;点击下载 关于IIC的介绍网上已经非常详尽&#xff0c;这里只说重点&#xff1a; 双线&#xff08;SDA&#xff0c;SCL&#xff09;&#xff0c;半双工采用主从结构&#xff0c;支持一主多从&#xff0c;通过地址寻址&#…

Hologres + Flink 流式湖仓建设

Hologres Flink 流式湖仓建设 1 Flink Hologres2 实时维表 Lookup 1 Flink Hologres holo在实时数仓领域非常受欢迎&#xff0c;一般搭配flinkhologres来做实时数仓&#xff0c;中间分层用holo&#xff0c;上下游一般依赖于holo的binlog来下发数据 2 实时维表 Lookup Holo…

生活的再思考,写在开篇

近几年的就业行情很特别&#xff0c;特别是对中年人&#xff0c;早先网络上主流的声音是动不动总包百万&#xff0c;手握几个 Offer &#xff0c;纠结应该去哪里。现在的主流声音变成了&#xff0c;被毕业优化掉后几个月都没找到合适的工作&#xff0c;焦虑迷茫无所适从&#x…

药物“出气”可知|ZL-005大小鼠雾化给药仪

雾化吸入给药是一种通过装置使药物进入肺部局部或全身发挥作用的给药方式。相较于口服药剂&#xff0c;雾化吸入给药可避免首过效应和药剂破坏&#xff0c;提高药物生物利用度。 而ZL-005大小鼠雾化给药仪&#xff0c;则是新一代小动物雾化装置的理想选择&#xff0c;可完成动…

你升级GPT-4了吗?,如何申请GPT-4 API?最全攻略

ChatGPT4就是ChatGPTPlus&#xff0c;调用接口就分ChatGPT3.5与ChatGPT4.0&#xff0c;如果你想使用ChatGPT4的接口就先充值ChatGPTPlus&#xff0c;在区ChatGPT绑定API即可调用4.0的API 在国内很多小伙伴还不知道怎么升级ChatGPT-4&#xff0c;因为自己只有国内的卡&#xff…

春晚为什么失去了观众?

​春晚失去了观众&#xff0c;这是近年来不可忽视的现象。春晚作为中国的一项传统文化活动&#xff0c;曾经吸引了亿万观众的眼球&#xff0c;但如今却面临着越来越多的挑战和质疑。那么&#xff0c;春晚为什么失去了观众呢&#xff1f; 首先&#xff0c;随着时代的变迁&#…

【C语言】指针进阶

指针的主题&#xff0c;在初阶的《指针》章节已经接触过了&#xff0c;我们知道了指针的概念&#xff1a; 指针就是个变量&#xff0c;用来存放地址&#xff0c;地址唯一标识一块内存空间。指针的大小是固定的4/8个字节&#xff08;32位平台/64位平台&#xff09;。指针是有类…

如何使用Imagewheel搭建一个简单的的私人图床无公网ip也能访问

文章目录 1.前言2. Imagewheel网站搭建2.1. Imagewheel下载和安装2.2. Imagewheel网页测试2.3.cpolar的安装和注册 3.本地网页发布3.1.Cpolar临时数据隧道3.2.Cpolar稳定隧道&#xff08;云端设置&#xff09;3.3.Cpolar稳定隧道&#xff08;本地设置&#xff09; 4.公网访问测…

每日一题——LeetCode1200.最小绝对差

方法一 个人方法 排序一次遍历&#xff1a; 最小差值一定是出现在大小相邻的两个元素之间&#xff0c;所以将数组从小到大排序 循环求两元素之间的差值&#xff0c;先假设当前差值为最小差值&#xff0c;先往res数组里面push数据&#xff0c;当碰到更小差值的时候&#xff0c…

Vue-Router 路径匹配与重定向

一、效果与描述 通过设置路由匹配同时设置重定向&#xff0c;让输错的网址重定向到指定页面&#xff0c;例如在网页输入网页地址把路径进行任意修改&#xff0c;重定向到登录页面。 二、Vue-Router代码 import { createRouter, createWebHashHistory } from vue-routerimport …

PyCharm安装插件后重启报错:java.lang.RuntimeException

一、问题描述 某次Pycharm 安装Sourcegraph Cody插件后&#xff0c;重启报错:java.lang.RuntimeException: com.intellij.ide.plugins.PluginManager$StartupAbortedException: Fatal error initializing ‘com.intellij.openapi.actionSystem.ActionManager’ &#xff0c;现…

Unity中URP下 SimpleLit框架

文章目录 前言一、整体框架1、该Shader是用于低端设备的2、包含一个Properties3、只有一个SubShader4、如果SubShader错误&#xff0c;返回洋葱紫5、调用自定义ShaderGUI面板 二、SubShader中1、Tags2、Pass 三、我们看一下ForwardLit的Pass1、混合模式、深度写入、面皮剔除、透…

Python教程44:海龟画图turtle画卡塔尔世界杯吉祥物

---------------turtle源码集合--------------- Python教程42&#xff1a;海龟画图turtle画海绵宝宝 Python教程41&#xff1a;海龟画图turtle画蜡笔小新 Python教程40&#xff1a;使用turtle画一只杰瑞 Python教程39&#xff1a;使用turtle画美国队长盾牌 Python教程38&a…

庆祝安科瑞企业微电网智慧能源管理系统生态交流会圆满举办-安科瑞 蒋静

2024年1月12日&#xff0c;安科瑞企业微电网智慧能源管理系统生态交流会顺利举行&#xff0c;本次会议旨在围绕双碳目标&#xff0c;共同探讨如何抓住新机遇、新市场&#xff0c;充分利用安科瑞企业微电网智慧能源的一站式服务&#xff0c;为企业节能、减碳、降本赋能&#xff…
最新文章