【JokerのZYNQ7020】LINUX_EMIO_BUTTON。

软件环境:vivado 2017.4        硬件平台:XC7Z020


这篇主要说下PL端由按钮产生的中断,在Linux系统下是怎样获取和处理的,工程依旧没变过还是那个工程。

然后设备树这里,其实Xilinx提供了两个button的驱动是可以直接加载使用的,分别是gpio-keys和gpio-keys-polled,这两个驱动在kernel中的位置是/kernel/drivers/input/keyboard/gpio_keys.c和gpio_keys_polled.c,主要差别是,使用gpio-keys驱动时按键的按下是可以给系统产生中断事件的,换句话说,你应用里open /dev/input/event0可以接收到输入事件,或者cat /proc/interrupts查看对应中断事件的计数是有变化的,另一方面,gpio-keys-polled驱动更类似于矩阵键盘,不使用gpio中断,依靠在配置设备树时候给不同的按键配置不同的code码,使用时不停的轮询,当有按键按下时,通过轮询区分不同code码来判断当前按下的是什么按键。这里以gpio-keys-polled来说一下整个操作过程。设备树如下。

/*
 * CAUTION: This file is automatically generated by Xilinx.
 * Version:  
 * Today is: Thu Aug  8 10:09:43 2019
 */


/ {
	amba_pl: amba_pl {
		#address-cells = <1>;
		#size-cells = <1>;
		compatible = "simple-bus";
		ranges ;
		axi_gpio_button: gpio@41210000 {
			#gpio-cells = <2>;
			#interrupt-cells = <2>;
			clock-names = "s_axi_aclk";
			clocks = <&clkc 15>;
			compatible = "xlnx,xps-gpio-1.00.a";
			gpio-controller ;
			interrupt-controller ;
			interrupt-names = "ip2intc_irpt";
			interrupt-parent = <&intc>;
			interrupts = <0 29 4>;
			reg = <0x41210000 0x10000>;
			xlnx,all-inputs = <0x0>;
			xlnx,all-inputs-2 = <0x0>;
			xlnx,all-outputs = <0x0>;
			xlnx,all-outputs-2 = <0x0>;
			xlnx,dout-default = <0x00000000>;
			xlnx,dout-default-2 = <0x00000000>;
			xlnx,gpio-width = <0x2>;
			xlnx,gpio2-width = <0x20>;
			xlnx,interrupt-present = <0x1>;
			xlnx,is-dual = <0x0>;
			xlnx,tri-default = <0xFFFFFFFF>;
			xlnx,tri-default-2 = <0xFFFFFFFF>;
		};
		
		gpio-keys-polled {
			compatible = "gpio-keys-polled";
			#address-cells = <1>;
			#size-cells = <0>;
			poll-interval = <20>;
			up {
				label = "up";
				gpios = <&axi_gpio_button 0 0>;
				linux,code = <103>;
			};
			down {
				label = "down";
				gpios = <&axi_gpio_button 1 0>;
				linux,code = <108>;
			};
		};
	};
};

对了忘了说了,不论是gpio-led或者gpio-keys,只要涉及gpio操作的,生成设备树的时候,默认生成的#gpio-cells = <3>,记得切记切记切记要把3改成2,不然系统启动以后使用会有问题的。下面gpio-keys-polled是手动添加的,修改compatible后面双引号部分,来修改需要加载的驱动,因为我板子pl部分只有两个按键,所以这里只添加了up和down,更多的linux,code的对应关系可以在/kernel/include/uapi/linux/input-event-codes.h中得到。

 另外还需要注意的是,在使用这两个驱动的时候,记得在配置kernel的时候,将如下部分使能。

Device Driver
----GPIO Support
--------Xilinx GPIO support

----Input device support
--------Keyboards
------------GPIO Buttons
------------Polled GPIO buttons

接下来测试代码贴一下,当有按键按下的时候,打印当前按的是哪个键。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <fcntl.h>
#include <signal.h>
#include <unistd.h>
#include <linux/input.h>

#define	INPUT_EVENT	"/dev/input/event0"

int main(void)
{
	struct input_event ev;
	int fd;
	int key_code;
	int size = sizeof(ev);

	/* Read event0 */
	fd = open(INPUT_EVENT, O_RDONLY);
	if (fd < 0) {
		printf("\nOpen " INPUT_EVENT " failed!\n");
		return 1;
	}
	/* Read and parse event, update global variable */
	while (1) {
		if (read(fd, &ev, size) < size) {
			printf("\nReading from " INPUT_EVENT " failed!\n");
			return 1;
		}
		
		if (ev.value == 1 && ev.type == 1) {
			key_code = ev.code;			
			if (key_code == KEY_DOWN) {
				printf("key input KEY_DOWN \n");
			} else if (key_code == KEY_UP) {
				printf("key input KEY_UP \n");
			}
			usleep(1000);
		}
	}
}

 /dev/input/event0对应的就是键盘的输入,通过对event0句柄的不断读取,来判断当前是否有值按下和按的是哪个键,说到这就不得不说下input_event这个结构体,它在/kernel/include/uapi/linux/input.h中有定义。

 

struct input_event {
	struct timeval time;    //按键时间
	__u16 type;             //按键类型
	__u16 code;             //按键值,什么键被按下
	__s32 value;            //是按下还是释放
};

code就是在/kernel/include/uapi/linux/input-event-codes.h中定义的按键对应的值,和设备树中注册的按键要有对应关系,type:

EV_KEY代表键盘,EV_REL,代表相对坐标,EV_ABS代表绝对坐标,同样在input-event-codes.h中都能看到定义。

value是按键事件的值,如果判断的对象ev.type是键盘(ev.type == EV_KEY),那么,当按键按下时,ev.value的值是1,当按键松开,ev.value的值是0 。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值