正点原子linux阿尔法开发板使用——Linux中断实验_irqreturn_t ( handler) (int, void );

在这里插入图片描述

驱动代码编写

添加中断信息

	key {
		#address-cells = <1>;
		#size-cells = <1>;
		compatible = "atkalpha-key";
		pinctrl-names = "default";
		pinctrl-0 = <&pinctrl_key>;
		key-gpio = <&gpio1 18 GPIO_ACTIVE_LOW>; /\* KEY0 \*/
		
		interrupt-parent = <&gpio1>;
		interrupts = <18 IRQ_TYPE_EDGE_BOTH>; /\* FALLING RISING \*/
		status = "okay";
	};

加载驱动失败的原因是因为:
两个节点都使用了 同一个GPIO
在这里插入图片描述
原厂驱动代码解析 按键设备树。
在这里插入图片描述

#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/of\_address.h>
#include <linux/of\_gpio.h>
#include <asm/mach/map.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/atomic.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/semaphore.h>
#include <linux/of\_irq.h>
#include <linux/irq.h>


#define IMX6ULIRQ\_NAME "imx6ul"
#define IMX6ULIRQ\_COUNT 1 

#define IMX6ULIRQOFF 0 /\* 关灯 \*/
#define IMX6ULIRQON 1 /\* 开灯 \*/



#define KEY\_NUM 1

#define KEY0\_VALUE 0X01
#define INVAKEY 0XFF


/\*按键结构体\*/
struct irq\_keydesc{
	int gpio;			/\*io编号\*/
	int irqnum;			/\*中断号\*/
	unsigned char value;	/\*键值\*/
	char name[10];		/\*名字\*/
	irqreturn\_t (\*handler)(int ,void \*);					/\*中断处理函数\*/

};



struct imx6uirq\_dev {
	
	struct cdev cdev;
	struct class \*class;/\*类:为了自动创建节点\*/
	struct device \*device;/\*设备:为了自动创建节点\*/
	dev\_t devid; //设备号
	int major;   //主设备号
	int minor;   //次设备号
	struct device\_node \*nd; //设备节点
	int led_gpio;

	struct irq\_keydesc	irqkey[KEY_NUM];

	struct timer\_list	timer;

	atomic\_t keyvalue;
	
	atomic\_t releasekey; //
	

	struct mutex lock;
};

struct imx6uirq\_dev imx6uirq; //imx6uirq设备

static int imx6uirq\_open(struct inode \*inode,struct file \*filp)
{
	filp->private_data = &imx6uirq;

	return 0;
}

static ssize\_t imx6uirq\_read(struct file \*filp,char __user \*buf,size\_t cnt, loff\_t \*offt)
{
	int ret = 0;
	unsigned char keyvalue;
	unsigned char releasekey;
	struct imx6uirq\_dev \*dev = filp->private_data;

	keyvalue = atomic\_read(&dev->keyvalue);
	releasekey = atomic\_read(&dev->releasekey);
	if (releasekey)
	{
		if (keyvalue & 0x80)
		{
			keyvalue &= ~0x80;
			ret = copy\_to\_user(buf,&keyvalue,sizeof(keyvalue));
		}
		else{
			goto data_error;
		}
		atomic\_set(&dev->releasekey,0);//按下标志清0
	}else{
		goto data_error;
	}


	return ret;

data_error:
	return -EINVAL;

}

static ssize\_t imx6uirq\_write(struct file \*filp, const char __user \*buf,size\_t cnt, loff\_t \*offt)
{
	//struct imx6uirq\_dev \*dev = (struct imx6uirq\_dev \*)filp->private\_data;
	
	return 0;
}

static int imx6uirq\_release(struct inode \*inode,struct file \*filp)
{
	//struct imx6uirq\_dev \*dev = (struct imx6uirq\_dev \*)filp->private\_data;

	return 0;
}

static irqreturn\_t key0\_handler(int irq,void \*dev_id)
{

	struct imx6uirq\_dev \*dev = dev_id;	

#if 0
	value = gpio\_get\_value(dev->irqkey[0].gpio);
	if (value == 0) 
	{
		printk("key 0 press\r\n");
	}
	else if (value == 1)
	{
		printk("key 0 release\r\n");
	}
#endif
	dev->timer.data = (volatile unsigned long)dev_id;
	mod\_timer(&dev->timer,jiffies + msecs\_to\_jiffies(10)); //10ms
	return IRQ_HANDLED;
}

/\*定时器处理函数\*/
static void timer\_func(unsigned long arg)
{
	int value = 0;

	struct imx6uirq\_dev \*dev = (struct imx6uirq\_dev \*)arg;	

	value = gpio\_get\_value(dev->irqkey[0].gpio);
	if (value == 0) 
	{
		atomic\_set(&dev->keyvalue,dev->irqkey[0].value);
		printk("key 0 press\r\n");
	}
	else if (value == 1)
	{
		atomic\_set(&dev->keyvalue,0x80|(dev->irqkey[0].value));
		atomic\_set(&dev->releasekey,1);//完整的释放 按键完成之后写入1
		printk("key 0 release\r\n");
	}

	//重新开启定时器
	//mod\_timer(&dev->timer,jiffies + msecs\_to\_jiffies(dev->timerperiod));
	
}


static int keyio\_init(struct imx6uirq\_dev \*dev)
{
	/\*1、按键的初始化\*/
	int i = 0;
	int ret = 0;
	dev->nd = of\_find\_node\_by\_path("/key");
	if (dev->nd == NULL)
	{
		printk("key node not find!\r\n");
		return -EINVAL;

	}

	for(i = 0; i <KEY_NUM;i++){
		
		dev->irqkey[i].gpio = of\_get\_named\_gpio(dev->nd,"key-gpio",i);
		if (dev->irqkey[i].gpio < 0) {
		printk("can't get key%d\r\n", i);
		}
		
	}
	for(i = 0; i <KEY_NUM;i++){
		// /\*获取按键的IO编号\*/
		// dev->irqkey[i].gpio = of\_get\_named\_gpio(dev->nd,"key-gpios",i);


		memset(dev->irqkey[i].name,0,sizeof(dev->irqkey[i].name));

		sprintf(dev->irqkey[i].name,"KEY%d",i);

		gpio\_request(dev->irqkey[i].gpio,dev->irqkey[i].name);

		gpio\_direction\_input(dev->irqkey[i].gpio);

		dev->irqkey[i].irqnum = gpio\_to\_irq(dev->irqkey[i].gpio);

		printk("key%d:gpio=%d, irqnum=%d\r\n",i,dev->irqkey[i].gpio,dev->irqkey[i].irqnum);
		//或者
		//dev->irqkey[i].irqnum = irq\_of\_parse\_and\_map(dev->nd,i);
	}


	dev->irqkey[0].handler = key0_handler;
	dev->irqkey[0].value = KEY0_VALUE;
	/\*2、中断初始化\*/


	for(i = 0; i <KEY_NUM;i++){
		ret = request\_irq(dev->irqkey[i].irqnum,dev->irqkey[i].handler,
		IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING,
		dev->irqkey[i].name,&imx6uirq);

		if (ret<0)
		{
			printk("irq request\_irq err");
			goto fail_irq;
		}
	}

	/\*3 初始化定时器\*/
	init\_timer(&imx6uirq.timer);

	//imx6uirq.timer.expires = jiffies + msecs\_to\_jiffies(imx6uirq.timerperiod);

	imx6uirq.timer.function = timer_func;

	imx6uirq.timer.data = (unsigned long)&imx6uirq;

	return 0;

fail_irq:
	for(i = 0; i <KEY_NUM;i++)
		gpio\_free(dev->irqkey[i].gpio);
	return ret;
}


static struct file\_operations imx6uirq_fops = {
	.owner = THIS_MODULE,
	.write = imx6uirq_write,
	.open = imx6uirq_open,
	.release = imx6uirq_release,
	.read = imx6uirq_read,
};

static int __init imx6uirq\_init(void)
{

	int ret = 0; 

	/\*互斥体初始化\*/
	mutex\_init(&imx6uirq.lock);


	/\*注册字符设备\*/
	imx6uirq.major = 0;
	if (imx6uirq.major){	
		imx6uirq.devid = MKDEV(imx6uirq.major,0);//设备号
		ret = register\_chrdev\_region(imx6uirq.devid,IMX6ULIRQ_COUNT,IMX6ULIRQ_NAME);
	}	else{
		ret = alloc\_chrdev\_region(&imx6uirq.devid,0,IMX6ULIRQ_COUNT,IMX6ULIRQ_NAME);
		imx6uirq.major = MAJOR(imx6uirq.devid);
		imx6uirq.minor = MINOR(imx6uirq.devid);
	}printk("led major = %d led minor = %d \r\n",imx6uirq.major,imx6uirq.minor);
	if (ret < 0){
		goto faile_devid;
	}

	/\*2、添加字符设备\*/
	imx6uirq.cdev.owner = THIS_MODULE;
	cdev\_init(&imx6uirq.cdev,&imx6uirq_fops);
	ret = cdev\_add(&imx6uirq.cdev,imx6uirq.devid,IMX6ULIRQ_COUNT);
	if(ret<0){
		goto fail_cdev;
	}
	/\*3、创建设备类\*/
	imx6uirq.class = class\_create(THIS_MODULE,IMX6ULIRQ_NAME);
	if(IS\_ERR(imx6uirq.class)){
		ret = PTR\_ERR(imx6uirq.class);
		printk("can't class\_create \r\n");
		goto fail_class;
	}
	/\*创建设备节点\*/
	imx6uirq.device = device\_create(imx6uirq.class,NULL,imx6uirq.devid,NULL,IMX6ULIRQ_NAME);
	if(IS\_ERR(imx6uirq.device)){
		ret = PTR\_ERR(imx6uirq.device);
		printk("can't device\_create \r\n");
		goto fail_device;
	}
	

	ret = keyio\_init(&imx6uirq);
## 最后

**自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。**

**深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。**

**因此收集整理了一份《2024年嵌入式&物联网开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**

![img](https://img-blog.csdnimg.cn/img_convert/9f1459917377e69268b2907f0046009f.png)

![img](https://img-blog.csdnimg.cn/img_convert/776f47f43245060d59850e59dbb1d819.jpeg)

![img](https://img-blog.csdnimg.cn/img_convert/d28f4c4780144ff3367c5e4293a40659.png)

 ![img](https://img-blog.csdnimg.cn/img_convert/7e10f89e6200680644e7407500aeedd8.png)

![img](https://img-blog.csdnimg.cn/img_convert/e020062fb60e490d0c4bbbb7c01fd8ae.png)

![img](https://img-blog.csdnimg.cn/img_convert/f96468aea095363f2dd504bcc498341c.png)

![](https://img-blog.csdnimg.cn/img_convert/356bb3ec39d464adb141a4fba4da1304.png)

 

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!**

[**如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!**](https://bbs.csdn.net/topics/618654289)

**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**!!


链图片转存中...(img-LIcmf62I-1715757378972)]

[外链图片转存中...(img-HdxNQ6G4-1715757378973)]

[外链图片转存中...(img-eKLYZu0F-1715757378973)]

 

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!**

[**如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!**](https://bbs.csdn.net/topics/618654289)

**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**!!


  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值