Linux 中断(十一)

  1. 中断号 Linux 内核中使用一个 int 变量表示中断号
  2.  request_irq 函数

        irq:要申请中断的中断号。

        handler:中断处理函数,

        flags:中断标志,//在文件 include/linux/interrupt.h 里面查看所有的中断标志

       上半部:上半部就是中断处理函数,那些处理过程比较快,不会占用很长时间的处理就可以放在上半部完成。

        下半部:如果中断处理过程比较耗时,那么就将这些比较耗时的代码提出来,交给下半部去执行,这样中断处理函数就会快进快出。
3、 free_irq 函数
4、中断处理函数
5、设备树中断信息节点
6、获取中断号
 

#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_gpio.h>
#include <linux/semaphore.h>
#include <linux/timer.h>
#include <linux/irq.h>
#include <linux/wait.h>
#include <linux/poll.h>
#include <linux/fs.h>
#include <linux/fcntl.h>
#include <linux/platform_device.h>
#include <asm/mach/map.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/of_irq.h>
#include <linux/irq.h>

#define IMX6UIRQ_CNT		1			/* 设备号个数 	*/
#define IMX6UIRQ_NAME		"wei_imx6uirq"	/* 名字 		*/
#define KEY0VALUE			0X01		/* KEY0按键值 	*/
#define INVAKEY				0XFF		/* 无效的按键值 */
#define KEY_NUM				1			/* 按键数量 	*/


/* 中断IO描述结构体 */
struct irq_keydesc {
	int gpio;								/* gpio */
	int irqnum;								/* 中断号     */
	unsigned char value;					/* 按键对应的键值 */
	char name;							/* 名字 */
	irqreturn_t (*handler)(int, void *);	/* 中断服务函数 */
};

/* imx6uirq设备结构体 */
struct imx6uirq_dev{
	dev_t devid;			/* 设备号 	 */
	struct cdev cdev;		/* cdev 	*/
	struct class *class;	/* 类 		*/
	struct device *device;	/* 设备 	 */
	int major;				/* 主设备号	  */
	int minor;				/* 次设备号   */
	struct device_node	*nd; /* 设备节点 */

	struct timer_list timer;/* 定义一个定时器*/
	struct irq_keydesc  irqkeydesc;	/* 按键描述数组 */
};

struct imx6uirq_dev imx6uirq;	/* irq设备 */

void timer_function(unsigned long arg)
{
	printk("触发\r\n");	
}
static irqreturn_t key0_handler(int irq, void *dev_id)
{
	// printk("haha\r\n");
	mod_timer(&imx6uirq.timer, jiffies + msecs_to_jiffies(10));
	return IRQ_RETVAL(IRQ_HANDLED);
}
static int irq_open(struct inode *inode, struct file *filp)
{
	filp->private_data = &imx6uirq;
	printk("open\r\n");
	return 0;
}
static ssize_t irq_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt)
{
	// int value;
	// value=gpio_get_value(imx6uirq.irqkeydesc.gpio);

	// copy_to_user(buf, &value, sizeof(value));
	//printk("key=%d\r\n",value);
	return 0;
}
static ssize_t irq_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt)
{
	int retvalue;
	unsigned char databuf[1];
	unsigned char irqstat;
	struct imx6uirq *dev = filp->private_data;
 
}
static int irq_release(struct inode *inode, struct file *filp)
{
	return 0;
}
/* 设备操作函数 */
static struct file_operations irq_fops = {
	.owner = THIS_MODULE,
	.open = irq_open,
	.read = irq_read,
	.write = irq_write,
	.release = 	irq_release,
};
/*****************************************************************/

static int irq_remove(struct platform_device *dev)
{
	// gpio_free(imx6uirq.irqkeydesc.gpio);

	del_timer_sync(&imx6uirq.timer);		/* 删除timer */
	free_irq(imx6uirq.irqkeydesc.irqnum, &imx6uirq);
	cdev_del(&imx6uirq.cdev);/*  删除cdev */
	unregister_chrdev_region(imx6uirq.devid, 1); /* 注销设备号 */
 
	device_destroy(imx6uirq.class, imx6uirq.devid);
	class_destroy(imx6uirq.class);

	return 0;
}

static int irq_probe(struct platform_device *dev)
{
	int ret = 0;
	imx6uirq.nd = of_find_node_by_path("/key");
		if(imx6uirq.nd == NULL) {
		printk("imx6uirq node not find!\r\n");
		return -EINVAL;
	} else {
		printk("imx6uirq node find!\r\n");
	}

	imx6uirq.irqkeydesc.gpio=of_get_named_gpio(imx6uirq.nd,"key-gpio",0);
	if(imx6uirq.irqkeydesc.gpio < 0) {
		printk("can't get key-gpio");
		return -EINVAL;
	}
	printk("key-gpio num = %d\r\n",imx6uirq.irqkeydesc.gpio);

	ret=gpio_direction_input(imx6uirq.irqkeydesc.gpio);
	if(ret < 0) {
		printk("can't set gpio!\r\n");
	}

	//中断
	 //imx6uirq.irqkeydesc.irqnum = irq_of_parse_and_map(imx6uirq.nd,0);
	imx6uirq.irqkeydesc.irqnum = gpio_to_irq(imx6uirq.irqkeydesc.gpio);
		/* 申请中断 */
	imx6uirq.irqkeydesc.handler = key0_handler;//中断处理函数
	request_irq(imx6uirq.irqkeydesc.irqnum, imx6uirq.irqkeydesc.handler, 
		                 IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING, imx6uirq.irqkeydesc.name, &imx6uirq);
	/*定时器的*/
	init_timer(&imx6uirq.timer);
	imx6uirq.timer.function = timer_function;
	imx6uirq.timer.data =  (unsigned long)(&imx6uirq);
	// mod_timer(&imx6uirq.timer, jiffies + msecs_to_jiffies(10000));

	alloc_chrdev_region(&imx6uirq.devid,0,1,IMX6UIRQ_NAME);
	imx6uirq.cdev.owner = THIS_MODULE;
	cdev_init(&imx6uirq.cdev,&irq_fops);
	//cdev_add(&imx6uirq.cdev,imx6uirq.devid,1);
	imx6uirq.class = class_create(THIS_MODULE,IMX6UIRQ_NAME);
	imx6uirq.device = device_create(imx6uirq.class, NULL, imx6uirq.devid, NULL,IMX6UIRQ_NAME);

	return 0;
}
/* 匹配列表 */
static const struct of_device_id irq_of_match[] = {
	{ .compatible = "atkalpha-key" },
	{ /* Sentinel */ }
};
/* platform驱动结构体 */
static struct platform_driver irq_driver = {
	.driver		= {
		.name	= "wei_dtsplatirq",			/* 驱动名字,用于和设备匹配 */
		.of_match_table	= irq_of_match, /* 设备树匹配表 		 */
	},
	.probe		= irq_probe,
	.remove		= irq_remove,
};
static int __init irq_init0(void)
{
	return platform_driver_register(&irq_driver);
}

static void __exit irq_exit0(void)
{
	platform_driver_unregister(&irq_driver);
}
module_init(irq_init0);
module_exit(irq_exit0);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("wei");

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值