文章目录
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代码下载地址如下:
正在上传中…