linux设备驱动之 按键中断编写

信息描述部分

#define IMX6UIRQ_CNT		1			/* 设备号个数 	*/
#define IMX6UIRQ_NAME		"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[10];							/* 名字 */
	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; /* 设备节点 */
	atomic_t keyvalue;		/* 有效的按键键值 */
	atomic_t releasekey;	/* 标记是否完成一次完成的按键,包括按下和释放 */
	struct timer_list timer;/* 定义一个定时器*/
	//struct irq_keydesc irqkeydesc[KEY_NUM];	/* 按键描述数组 */
    struct irq_keydesc irqkeydesc;
	unsigned char curkeynum;				/* 当前的按键号 */
};

struct imx6uirq_dev imx6uirq;	/* irq设备 */

驱动编写部分

static irqreturn_t key0_handler(int irq, void *dev_id)
{
    struct imx6uirq_dev *dev = (struct imx6uirq_dev *)dev_id;
    printk("gpio num=%d\n", dev->irqkeydesc.gpio);
    dev->curkeynum = 0;

    return IRQ_RETVAL(IRQ_HANDLED);
}

static int keyio_init(void)
{
    int ret = 0;

    imx6uirq.nd = of_find_node_by_path("/key");
	if (imx6uirq.nd== NULL){
		printk("key node not find!\r\n");
		return -EINVAL;
	} 

	/* 提取GPIO */
    imx6uirq.irqkeydesc.gpio = of_get_named_gpio(imx6uirq.nd, "key-gpio", 0);
    if(imx6uirq.irqkeydesc.gpio < 0)
    {
        printk("can not get gpio\r\n");
        return -ENAVAIL;
    }

    ret = gpio_request(imx6uirq.irqkeydesc.gpio, "key0");
    if(ret < 0)
    {
        printk("request gpio failed\r\n");
        return -EINVAL;
    }
    gpio_direction_input(imx6uirq.irqkeydesc.gpio);

    imx6uirq.irqkeydesc.irqnum = irq_of_parse_and_map(imx6uirq.nd, 0);
    imx6uirq.irqkeydesc.handler = key0_handler;
    imx6uirq.irqkeydesc.value = KEY0VALUE;
    ret = request_irq(imx6uirq.irqkeydesc.irqnum, imx6uirq.irqkeydesc.handler, \
    IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING, imx6uirq.irqkeydesc.name, &imx6uirq);
    if(ret < 0)
    {
        printk("irq %d request failed!\r\n", imx6uirq.irqkeydesc.irqnum);
        return -EINVAL;
    }

    return ret;
}

void create_device(void)
{
	/* 1、构建设备号 */
	if (imx6uirq.major) {
		imx6uirq.devid = MKDEV(imx6uirq.major, 0);
		register_chrdev_region(imx6uirq.devid, IMX6UIRQ_CNT, IMX6UIRQ_NAME);
	} else {
		alloc_chrdev_region(&imx6uirq.devid, 0, IMX6UIRQ_CNT, IMX6UIRQ_NAME);
		imx6uirq.major = MAJOR(imx6uirq.devid);
		imx6uirq.minor = MINOR(imx6uirq.devid);
	}

	/* 2、注册字符设备 */
	cdev_init(&imx6uirq.cdev, &imx6uirq_fops);
	cdev_add(&imx6uirq.cdev, imx6uirq.devid, IMX6UIRQ_CNT);

	/* 3、创建类 */
	imx6uirq.class = class_create(THIS_MODULE, IMX6UIRQ_NAME);
	if (IS_ERR(imx6uirq.class)) {
		return PTR_ERR(imx6uirq.class);
	}

	/* 4、创建设备 */
	imx6uirq.device = device_create(imx6uirq.class, NULL, imx6uirq.devid, NULL, IMX6UIRQ_NAME);
	if (IS_ERR(imx6uirq.device)) {
		return PTR_ERR(imx6uirq.device);
	}
}

static int __init imx6ullirq_init(void)
{
    int ret = 0;
    printk("irq module init\r\n");
    
	//创建设备
	create_device();
	//注册中断
	keyio_init();

	return ret;
}

static void __exit imx6ullirq_exit(void)
{
    printk("irq module exit\r\n");

    free_irq(imx6uirq.irqkeydesc.irqnum, &imx6uirq);
    gpio_free(imx6uirq.irqkeydesc.gpio);

	//卸载设备
	cdev_del(&imx6uirq.cdev);
	unregister_chrdev_region(imx6uirq.devid, IMX6UIRQ_CNT);
	device_destroy(imx6uirq.class, imx6uirq.devid);
	class_destroy(imx6uirq.class);


}

module_init(imx6ullirq_init);
module_exit(imx6ullirq_exit);

执行结果如下:

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

路过的小熊~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值