rk3288 使用100ask扩展板编写按钮中断

本文详细介绍了如何在Linux系统下为GPIO按键编写驱动程序,包括设备树配置、中断处理函数的编写以及中断注册等步骤。通过实例代码展示了如何在中断中读取GPIO状态,并在按键按下时触发中断处理。此教程适用于嵌入式硬件和Linux驱动开发者,有助于深入理解GPIO和中断机制。
摘要由CSDN通过智能技术生成

对 于 GPIO 按 键 , 我 们 并 不 需 要 去 写 驱 动 程 序 , 使 用 内 核 自 带 的 驱 动 程 序drivers/input/keyboard/gpio_keys.c 就可以,然后你需要做的只是修改设备树指定引脚及键值。
但是自己编写相关的内容则可以更好的学习到这些功能。

编程思路

在设备树里指定相关的引脚,这里使用的是GPIO7_B1。然后使用pinctrl对引脚进行读取,读取函数需要在中断中进行。
中断的注册是通过一系列设备树函数设定的。
在这里插入图片描述执行过程:
用户态

设置树相关的配置:

/ {
	mybutton {
        compatible = "mybtn,btn_drv";
        gpios = <&gpio7 9 GPIO_ACTIVE_LOW>;
        pinctrl-names = "default";
        pinctrl-0 = <&my_btn>;
    };

&pinctrl {
    mybutton {
        my_btn: my-btn {
            rockchip,pins = <7 9 RK_FUNC_GPIO &pcfg_pull_up>;
        };
    };
};
};

在arch/arm/boot/dts/rk3288-firefly-port.dtsi中,有100ask的设备节点,这个就是用gpio-key编写的。
需要把它注释掉,不然注册中断的时候会冲突。

        //100ask extend board.
        button@1 {
            gpios = <&gpio7 9 GPIO_ACTIVE_LOW>;
            linux,code = <KEY_A>;
            label = "GPIO KEY_A";
            linux,input-type = <1>;
            gpio-key,wakeup = <1>;
            debounce-interval = <100>;

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

代码编写思路

  1. 从设备树中获取GPIO号
  2. 从GPIO获取中断号
  3. 申请中断
  4. 编写中断函数

相关函数

//计算设备树中节点np下的gpios属性的个数
static inline int of_gpio_count(struct device_node *np)//获取gpio flags的参数,这里的返回值应该是gpio号。
static inline int of_get_gpio_flags(struct device_node *np, int index, enum of_gpio_flags *flags);
//把gpio号转换成gpio_desc
struct gpio_desc *gpio_to_desc(unsigned gpio);
//把gpio号转换成irq号
static inline int pio_to_irq(unsigned gpio);
//注册中断函数,irq申请的中断号,handler处理函数,flags触发条件,name中断总线中的名字,dev设备指针
static inline int __must_check
request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char *name, void *dev);

源码

button_irq.c

#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/device.h>
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/uaccess.h>
#include <linux/irqreturn.h>
#include <linux/gpio/consumer.h>
#include <linux/of_gpio.h>
#include <linux/slab.h>
#include <linux/interrupt.h>

struct gpio_key {
	int gpio;
	struct gpio_desc *gpiod;
	int flag;
	int irq;
};
static struct gpio_key *myBtn_key;

static irqreturn_t myBtn_irq_request(int irq, void *dev_id)
{
	struct gpio_key *gpio_key = dev_id;
	int val;
	val = gpiod_get_value(gpio_key->gpiod);
	
	printk(KERN_WARNING"key %d %d\n", gpio_key->gpio, val);
	return IRQ_HANDLED;
}

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

	count = of_gpio_count(node);
	if(!count) {
		printk("%s,there isn't any gpio availiable\n", __FUNCTION__);
		return -1;
	}
	
	myBtn_key = (struct gpio_key*)kzalloc(sizeof(struct gpio_key)*count, GFP_KERNEL);
	if(!myBtn_key) {
		printk("%s,kzalloc malloc failed\n", __FUNCTION__);
		return -1;
	}

	for(i=0;i<count;i++) {
		myBtn_key[i].gpio = of_get_gpio_flags(node, i, &flag);
		if(myBtn_key[i].gpio < 0) {
			printk("%s, of_get_gpio_flags failed\n", __FUNCTION__);
			return -1;
		}
		myBtn_key[i].gpiod = gpio_to_desc(myBtn_key[i].gpio);
		myBtn_key[i].flag  = flag & OF_GPIO_ACTIVE_LOW;
		myBtn_key[i].irq   = gpio_to_irq(myBtn_key[i].gpio);
		err = request_irq(myBtn_key[i].irq, myBtn_irq_request, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
				"myBtn_key", &myBtn_key[i]);
	}

	return 0;
}

static int my_button_remove(struct platform_device *pdev)
{
	struct device_node *node= pdev->dev.of_node;
	int count;
	int i;

	count = of_gpio_count(node);
	for(i=0;i<count;i++) {
		free_irq(myBtn_key[i].irq, &myBtn_key[i]);
	}

	kfree(myBtn_key);
	return 0;
}

static struct of_device_id mybuttons[] = {
	{ .compatible = "mybtn,btn_drv" },
	{ },
};

static struct platform_driver my_button_driver = {
	.probe  = my_button_probe,
	.remove = my_button_remove,
	.driver = {
		.name = "button_dirver",
		.of_match_table = mybuttons,
	},
};

static int gpio_button_init(void)
{
	int err;
	err = platform_driver_register(&my_button_driver);
	printk(KERN_WARNING"my button dirver init\n");
	return 0;
}

static void gpio_button_exit(void)
{
	platform_driver_unregister(&my_button_driver);
	printk(KERN_WARNING"my button dirver exit\n");
}

module_init(gpio_button_init);
module_exit(gpio_button_exit);
MODULE_LICENSE("GPL");

button_irq.dts

/ {
    mybutton {
        compatible = "mybtn,btn_drv";
        gpios = <&gpio7 9 GPIO_ACTIVE_LOW>;
        pinctrl-names = "default";
        pinctrl-0 = <&my_btn>;
    };

&pinctrl {
    mybutton {
        my_btn: my-btn {
            rockchip,pins = <7 9 RK_FUNC_GPIO &pcfg_pull_up>;
        };
    };
};
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

习惯就好zz

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

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

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

打赏作者

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

抵扣说明:

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

余额充值