[IMX6ULL驱动开发]-Linux对中断的处理(三)

前两篇文章主要是理论上的知识,此文章主要内容为代码上的编写以及思路等

[IMX6ULL驱动开发]-Linux对中断的处理(一)

[IMX6ULL驱动开发]-Linux对中断的处理(二)

目录

设备树中的操作

中断控制器

设备树中使用中断

编程思路

设备树相关

驱动程序相关


设备树中的操作

中断控制器

我们首先要在设备树当中创建对应的中断节点,首先我们需要了解一下中断控制器这个概念,在硬件的概念上,中断控制器其实只有GIC,但是在软件上,我们也可以把GPIO看为一个中断控制器,所以,从软件层面上看,中断控制器包括GIC、GPIO1、GPIO2等,一个GPIO上可能连接多个外部设备,它们共用一个中断号,此GPIO控制这些中断号。

GPIO1 连接到 GIC,GPIO2 连接到 GIC,所以 GPIO1 的父亲是 GIC,GPIO2 的父亲是 GIC。

假设GPIO1总共控制32个中断外部设备,假设其中16个共用一个中断号,另外16个共用另一个中断号,那么GPIO1总共会使用到GIC的两个中断号,会涉及 GIC 里的 2 个 hwirq。这些都会在设备树当中体现出来。

在设备树当中,如果存在属性:interrupt-controller,则表示该节点为中断控制器,除此之外,还需要另外一个属性,#interrupt-cells,表示使用这个中断控制器需要多少个cell

如果中断控制器存在级联关系,那么子级的中断控制器需要指定自己的父级中断控制器为哪个,比如上级的GPIO中断控制器需要指定自己的 interrupt-parent 为GIC。


设备树中使用中断

一个外设,使用哪一个中断控制器,使用中断控制器的哪个引脚,中断的触发方式在设备树中是如何体现出来的。

interrupt-parent=< &xxxx >       使用的父级中断控制器为哪个

interrupts                                   使用的父级中断控制器的引脚,具体几个cell表示由父级决定

为了方便,通常interrupt-parent和interrupts两个属性可以合起来,使用 interrupts-extended来进行表示。

interrupts-extended = <&intc1 5 1>, <&intc2 1 0>;

  • &intc1&intc2:这些是中断控制器的引用,它们是设备树中定义的节点,负责管理中断请求。

  • 51:这些是中断号,它们是中断控制器分配给特定设备的中断请求号。

  • 10:这些是中断的触发类型。


编程思路

设备树相关

在这里,我们需要使用两个按键来触发中断,我们首先查阅引脚图,来判断使用的引脚以及触发的方式。

我们可以依照这些信息编写出如下设备树信息:

节点的名称为:gpio_key_interrupt 

compatible的值为"100ask_interrupt_test",用来适配驱动程序

gpios属性指定了引脚GPIO5 1和 GPIO4 14为中断源,当它们为低电平的时候看为中断触发

gpio_key_interrupt { 
    compatible = "100ask_interrupt_test";
	gpios = <&gpio5 1 GPIO_ACTIVE_LOW
	 		 &gpio4 14 GPIO_ACTIVE_LOW >;
    };

但是这些还是不够完整的,我们需要使用pinctrl来指定这两个引脚的为GPIO功能,表明自身是哪一个 GPIO 模块里的哪一个引脚。

使用引脚配置工具按照如下方式指定,然后把对应生成代码拷贝到dts文件当中

GPIO5 1引脚的配置如上 GPIO4 14所示,但是需要注意的是,存在的节点GPIO4为iomuxc,但是GPIO5为iomuxc_snvs。

gpio_key_interrupt { 
    compatible = "100ask_interrupt_test";
    gpios = <&gpio5 1 GPIO_ACTIVE_LOW
	 		  &gpio4 14 GPIO_ACTIVE_LOW >;

    pinctrl-names = "default";
	pinctrl-0 = <&KEY1_interrupt 
 				 &KEY2_interrupt>; 
    };

设备树文件就完成了,把它编译后,放置于开发板的 /boot/ 目录下。


驱动程序相关

驱动程序的主要思路如下:

一、编写驱动的出口函数和入口函数

二、定义 platform_driver 结构体,重点填充 probe 以及 remove

三、在probe函数中获取设备树中节点的各种GPIO信息,并为它们创建中断号,remove主要用于清除这些信息

四、中断处理函数的编写

五、驱动卸载的一些操作函数

如下结构体为 platform_driver结构体的填充,主要就是完成probe函数,在该结构体的driver成员的of_match_table的类型为 of_device_id 结构体,我们需要再定义一个此结构体,然后填充此结构体的compatible属性,用来匹配设备树。

probe函数主要实现在设备树中获取对应的引脚信息,然后通过对应的引脚信息来创建中断,创建中断的时候,需要创建中断处理函数,在这里我们的中断处理函数负责读取当前按键的值

remove函数主要用来通过对应的中断号来清除对应的中断,在这里我们还需要释放kzalloc申请的内核态的堆区空间

如果内核没有打印日志信息,使用如下命令:

echo "7 4 1 7" > /proc/sys/kernel/printk 

Makefile如下

KERN_DIR = /home/book/100ask_imx6ull-sdk/Linux-4.9.88

all:
	make -C $(KERN_DIR) M=`pwd` modules 
	

clean:
	make -C $(KERN_DIR) M=`pwd` modules clean
	rm -rf modules.order
	
obj-m	+= interrupt_test.o

#include <linux/module.h>

#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>
#include <linux/gpio/consumer.h>
#include <linux/platform_device.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/slab.h>


/* 中断结构体,存储按键中断的GPIO等信息 */
struct key_gpio{

	int gpio;
	int irq;
	enum of_gpio_flags flag;
	

};

static struct key_gpio* ket_interrupt_res;


/* 中断函数 */
static irqreturn_t irq_handler(int irq	, void *dev_id)
{
	struct key_gpio* p_key_gpio = (struct key_gpio*)dev_id;
	int val;

	val = gpio_get_value(p_key_gpio->gpio);

	printk("key %d %d\n", p_key_gpio->irq , val);

 
	return IRQ_HANDLED;

}



int interrupt_test_probe(struct platform_device *pdev)
{
	int count = 0;
	int i = 0;
	struct device_node *node = pdev->dev.of_node;
	enum of_gpio_flags flag;
	int err;

	/* 获取GPIO中断个数 */
	count = of_gpio_count(node);

	ket_interrupt_res = kzalloc(count * sizeof(struct key_gpio), GFP_KERNEL);	
	if( !count )
	{
		printk("%s %s line %d, there isn't any gpio available\n", __FILE__, __FUNCTION__, __LINE__);
		return -1;
	}

	for( i = 0 ; i < count ; i++ )
	{
		ket_interrupt_res[i].gpio = of_get_gpio_flags(node , i , &flag);

		if( ket_interrupt_res[i].gpio < 0 )
		{
			printk("%s %s line %d, of_get_gpio_flags fail \n", __FILE__, __FUNCTION__, __LINE__);
		}
		ket_interrupt_res[i].irq = gpio_to_irq(ket_interrupt_res[i].gpio);
		ket_interrupt_res[i].flag = flag & OF_GPIO_ACTIVE_LOW;



		err = request_irq(ket_interrupt_res[i].irq, irq_handler, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, \
						  "ket_interrupt", &ket_interrupt_res[i]);
		
	}
	return 0;
	
	
}
int interrupt_test_remove(struct platform_device *pdev)
{
	struct device_node *node = pdev->dev.of_node;
	int count = 0;
	int i = 0;
	count = of_gpio_count(node);

	for( i = 0 ; i < count ; i++ )
	{
		free_irq(ket_interrupt_res[i].irq,&ket_interrupt_res[i]);
	}
	kfree(ket_interrupt_res);
    return 0;
	
}


static const struct of_device_id ask100_interrupt[] = {
    { .compatible = "100ask_interrupt_test" },
    { },
};



static struct platform_driver interrupt_test_driver = {
    .probe      = interrupt_test_probe,
    .remove     = interrupt_test_remove,
    .driver     = {
        .name   = "100ask_interrupt",
        .of_match_table = ask100_interrupt,
    },
};




static int __init interrupt_test_init(void)
{
    int err;
    
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
	printk(" interrupt_test_driver register \n");
	
    err = platform_driver_register(&interrupt_test_driver); 
	
	return err;
}

static void __exit interrupt_test_exit(void)
{
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
	printk(" interrupt_test_driver unregister \n");

    platform_driver_unregister(&interrupt_test_driver);
}


                                

module_init(interrupt_test_init);
module_exit(interrupt_test_exit);

MODULE_LICENSE("GPL");





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

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

相关文章

网页基础三剑客

目录 一、网页开发技术 1&#xff0e;HTML 2&#xff0e;CSS 3&#xff0e;JavaScript 二、网页的结构 三、 网页的分类 1&#xff0e;静态网页 2&#xff0e;动态网页 1&#xff0e;jQuery 2&#xff0e;AJAX 3&#xff0e;DHTML 2.3.4 网页数据的格式 1&#xf…

刷代码随想录有感(111):动态规划——零钱兑换II

干&#xff0c;被上了一课。注意题干&#xff0c;到底是求能装最大价值的方案还是装满这个容量共有多少种方法。他们的公式都不同&#xff0c;最大价值的方案是&#xff1a; dp[j] max(dp[j], dp[j - weight[i]] value[i]); 而装满有多少种方法是&#xff1a; dp[j] dp[j…

yum的概念、相关命令、ftp http部署步骤;NFS共享文件操作步骤

目录 yum 配置文件 缓存功能操作步骤 创建并配置本地仓库文件 yum相关命令 yum install __ yum repolist yum list __ yum info __ yum search __ yum whatprovides __ yum remove __ yum -y update __ yum history yum grouplist yum groupinstall "__&q…

小程序 获取插件用户openpid?

接口英文名 getPluginOpenPId 功能描述 通过 wx.pluginLogin 接口获得插件用户标志凭证 code 后传到开发者服务器&#xff0c;开发者服务器调用此接口换取插件用户的唯一标识 openpid。 调用方式 HTTPS 调用 第三方调用 调用方式以及出入参和HTTPS相同&#xff0c;仅是调…

AXI学习笔记

文章目录 AXI口诀&#xff1a;AXI三种总线&#xff0c;三种接口&#xff0c;一个协议背景知识一、 AMBA&#xff1a;二、AXI2.1 通信协议与握手机制2.2 AXI协议特点2.3 三种AXI总线类型&#xff08;AXI4、AXI4-lite、AXI4-stream&#xff09;2.3.1 AXI通道&#xff08;5通道&am…

通信系统概述

1.定义 通信系统&#xff08;也称为通信网络&#xff09;是利用各种通信线路将地理上分散的、具有独立功能的计算机系统和通信设备按不同的形式连接起来&#xff0c;依靠网络软件及通信协议实现资源共享和信息传递的系统。 2.概述 随着通信技术和网络技术的不断发展&#xff…

『 Linux 』 进程间通信 - 匿名管道

文章目录 什么是管道匿名管道的直接原理pipe( )系统调用接口匿名管道代码示例匿名管道的特征总结 什么是管道 管道(Pipe) 是一种基本的进程间通信(IPC)机制,允许一个进程与另一个进程之间进行数据传输; 管道工作方式类似于生活中的水管因此命名为管道,数据从一端流入另一段流出…

技术分享 | 基于 API 解析的 Python 爬虫

最近各大高校纷纷翻拍 Coincidence 抖肩舞&#xff0c;需要对这种流行现象进行数据分析。数据分析首先需要有数据&#xff0c;本文介绍了爬取 B 站相应视频的评论、弹幕、播放量、点赞数等数据的方法。爬虫有多种实现方法&#xff0c;大型的网络爬虫多基于成熟的爬虫框架&#…

2-12 基于CV模型卡尔曼滤波、CT模型卡尔曼滤波、IMM模型滤波的目标跟踪

基于CV模型卡尔曼滤波、CT模型卡尔曼滤波、IMM模型滤波的目标跟踪。输出跟踪轨迹及其误差。程序已调通&#xff0c;可直接运行。 2-12 CV模型卡尔曼滤波 CT模型卡尔曼滤波 - 小红书 (xiaohongshu.com)

基于jeecgboot-vue3的Flowable流程-自定义业务表单处理(一)支持同一个业务多个关联流程的选择支持

因为这个项目license问题无法开源&#xff0c;更多技术支持与服务请加入我的知识星球。 这部分先讲讲支持自定义业务表单一个业务服务表单多个流程的支持处理 1、后端mapper部分 如下&#xff0c;修改selectSysCustomFormByServiceName为list对象&#xff0c;以便支持多个 &…

卫星导航与gazebo仿真

全球卫星导航系统(Global Navigation Satelite System,GNSS)&#xff0c;简称卫星导航&#xff0c;是室外机器人定位的一个主要信息来源。 卫星导航能给机器人提供什么信息&#xff1f; 正常工作时&#xff0c;实际上可以提供机器人所需的所有定位信息&#xff0c;包括&#x…

【例子】webpack配合babel实现 es6 语法转 es5 案例 [通俗易懂]

首先来说一下实现 es6 转 es5 的一个简单步骤 1、新建一个项目&#xff0c;并且在命令行中初始化项目 npm init -y2、安装对应版本的 webpack webpack-cli(命令行工具) "webpack""webpack-cli"3、安装 Babel 核心库和相关的 loader "babel-core&qu…

K8s 如何集成ChatGPT?

文章目录 1. 什么是K8s&#xff1f;2. 集成K8s和大模型的效果3. ChatGPT监测K8s集群Demo4.可预想的实践用例5. 结论 1. 什么是K8s&#xff1f; 熟悉云原生领域的朋友对 K8s 一定不会陌生。K8s&#xff08;Kubernetes&#xff09;是一个开源的容器编排平台&#xff0c;用于自动…

《华为项目管理之道》第1章笔记

《华为项目管理之道》&#xff0c;是新出的华为官方的项目管理书&#xff0c;整个书不错。第1章的精华&#xff1a; 1.2.2 以项目为中心的机制 伴随着项目型组织的建立&#xff0c;华为逐步形成了完备的项目管理流程和制度&#xff0c;从而将业务运 作构建在项目经营管理之…

生成模型的两大代表:VAE和GAN

生成模型 给定数据集&#xff0c;希望生成模型产生与训练集同分布的新样本。对于训练数据服从\(p_{data}(x)\)&#xff1b;对于产生样本服从\(p_{model}(x)\)。希望学到一个模型\(p_{model}(x)\)与\(p_{data}(x)\)尽可能接近。 这也是无监督学习中的一个核心问题——密度估计…

STM32——温湿度采集与显示

一、I2C协议 关于I2C协议的基本原理和时序协议 12C协议使用两条线&#xff1a;SDA&#xff08;Serial Data Line&#xff0c;串行数据线&#xff09;和SCL&#xff08;Serial Clock Line&#xff0c;串行时钟线&#xff09;。这两条线都是开漏输出&#xff0c;意味着它们需要上…

智能网联汽车实训教学“好帮手”——渡众机器人自动驾驶履带车

智能网联汽车实训教学“好帮手”——渡众机器人自动驾驶履带车 人工智能技术的兴起&#xff0c;为传统汽车行业注入了强有力的变革基因&#xff0c;以AI技术为驱动的无人驾驶成为汽车产业的未来&#xff0c;同样也面临诸多机遇和挑战。 一方面智能网联汽车的发展&#xff0c;为…

基于TensorFlow和OpenCV的物种识别与个体相似度分析【附完整源码】Flask网页版

一、OpenCV与TensorFlow介绍 1. 什么是OpenCV OpenCV&#xff08;Open Source Computer Vision Library&#xff09;是一个开源的计算机视觉和机器学习软件库。OpenCV由英特尔公司在1999年发起&#xff0c;并在2000年以开源的方式发布。该库被设计为高效的计算机视觉应用程序…

OpenHarmony-HDF驱动框架介绍及加载过程分析

前言 HarmonyOS面向万物互联时代&#xff0c;而万物互联涉及到了大量的硬件设备&#xff0c;这些硬件的离散度很高&#xff0c;它们的性能差异与配置差异都很大&#xff0c;所以这要求使用一个更灵活、功能更强大、能耗更低的驱动框架。OpenHarmony系统HDF驱动框架采用C语言面…

UE5近战对抗系统Tutorial

文章目录 BP_Character 组合攻击Notify State 检测攻击BP_Character 攻击反馈BP_Character 生命系统BP_Character 死亡效果BP_Character 武器系统BP_Enemy 初始化和行为树 BP_Character 组合攻击 首先我们获取攻击动画&#xff0c;在这里使用的是 Easy Combo Buffering 的攻击…