【Linux】编写一个Linux按键中断Demo

1. 前言

在内核里面实现了按键驱动,drivers/input/keyboard/gpio_keys.c,我们可以参考它来学着写一个按键中断程序。

2. 硬件介绍

通过下面的硬件我们可以知道按键检测GPIO默认是高电平,如果按键被按下就变成低电平。所以,我们可以配置GPIO为中断模式,检测KEY是否被按下。
在这里插入图片描述

3. 编写按键驱动程序

  • 在设备树中添加按键使用的引脚,如下:
    imx_gpio_keys {
    	compatible = "imx,gpio_key";
    	gpios = <&gpio5 1 GPIO_ACTIVE_HIGH
    			 &gpio4 14 GPIO_ACTIVE_HIGH>;
    	
    	pinctrl-names = "default";
    	pinctrl-0 = <&pinctrl_gpio_key1
    				 &pinctrl_gpio_key2>;
    };
    
  • 在probe函数中从设备树获取GPIO,并且从GPIO中获得中断号
    count = of_gpio_count(node);
    if(!count){
    	printk("[%s:%d] There isn't gpio available!\n", __FUNCTION__, __LINE__);
    	return -1;
    }
    
    pGpioKeyCfg = kzalloc(count * sizeof(struct gpio_key_cfg), GFP_KERNEL);
    
    for(i = 0; i < count; i++)
    {
    	pGpioKeyCfg[i].gpio_num = of_get_gpio_flags(node, i, &flag);
    	if(pGpioKeyCfg[i].gpio_num < 0){
    		printk("[%s:%d] of_get_gpio_flags is fail!!!\n", __FUNCTION__, __LINE__);
    		return -1;
    	}
    
    	pGpioKeyCfg[i].gpio_flag = flag & OF_GPIO_ACTIVE_LOW; // 获取GPIO的flag
    	pGpioKeyCfg[i].gpiod = gpio_to_desc(pGpioKeyCfg[i].gpio_num); // 获取GPIO的描述符
    	pGpioKeyCfg[i].gpio_irq = gpio_to_irq(pGpioKeyCfg[i].gpio_num); // 获取GPIO的中断号
    }
    
  • 申请中断和编写中断函数
    for(i = 0; i < count; i++)
    {
    	request_irq(pGpioKeyCfg[i].gpio_irq, gpio_key_isr, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "gpio_key", &pGpioKeyCfg[i]);
    }
    
    static irqreturn_t gpio_key_isr(int irq, void *dev_id)
    {
    	int val;
    	struct gpio_key_cfg *pGpioKey = dev_id;
    
    	val = gpiod_get_value(pGpioKey->gpiod);
    
    	printk("key %d %d\n", pGpioKey->gpio_num, val);
    
    	return IRQ_HANDLED;
    }
    

4. 配置设备树

IMX平台可以通过“i.MX Pins Tool v6”配置gpio,一般一个引脚作为中断时,要通过 PinCtrl 把它设置为 GPIO 功能。配置效果如下:
在这里插入图片描述
工具生成的代码,对应修改dtsi如下:

diff --git a/arch/arm/boot/dts/imx6ul-14x14-evk.dtsi b/arch/arm/boot/dts/imx6ul-14x14-evk.dtsi
index 6b70f287e..52c5bd0ee 100644
--- a/arch/arm/boot/dts/imx6ul-14x14-evk.dtsi
+++ b/arch/arm/boot/dts/imx6ul-14x14-evk.dtsi
@@ -326,7 +326,7 @@
 &qspi {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_qspi>;
-	status = "okay";
+	status = "disabled";
 
 	flash0: n25q256a@0 {
 		#address-cells = <1>;
@@ -748,4 +748,10 @@
 			MX6UL_PAD_LCD_RESET__WDOG1_WDOG_ANY    0x30b0
 		>;
 	};
+	
+	pinctrl_gpio_key2: gpio_key2 {
+		fsl,pins = <
+			MX6UL_PAD_NAND_CE1_B__GPIO4_IO14       0x000010B0
+		>;
+	};
 };
diff --git a/arch/arm/boot/dts/imx6ull-14x14-evk.dts b/arch/arm/boot/dts/imx6ull-14x14-evk.dts
index bb8f91034..44818b470 100644
--- a/arch/arm/boot/dts/imx6ull-14x14-evk.dts
+++ b/arch/arm/boot/dts/imx6ull-14x14-evk.dts
@@ -10,8 +10,27 @@
 / {
 	model = "Freescale i.MX6 ULL 14x14 EVK Board";
 	compatible = "fsl,imx6ull-14x14-evk", "fsl,imx6ull";
+	
+	imx_gpio_keys {
+		compatible = "imx,gpio_key";
+		gpios = <&gpio5 1 GPIO_ACTIVE_HIGH
+				 &gpio4 14 GPIO_ACTIVE_HIGH>;
+		
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_gpio_key1
+					 &pinctrl_gpio_key2>;
+	};
 };
 
+&iomuxc_snvs {
+	pinctrl_gpio_key1: gpio_key1 {
+		fsl,pins = <
+			MX6ULL_PAD_SNVS_TAMPER1__GPIO5_IO01        0x000110A0
+		>;
+	};
+};
+
+
 &clks {
 	assigned-clocks = <&clks IMX6UL_CLK_PLL3_PFD2>,
 			  <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;

5. 烧录验证

编译烧录验证如下:
在这里插入图片描述

6. 工程代码下载地址

完整的实验工程Demo代码下载地址如下:
https://download.csdn.net/download/ZHONGCAI0901/22268720

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值