
本文共 3545 字,大约阅读时间需要 11 分钟。
软件环境: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#include #include #include #include #include #include #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 。
发表评论
最新留言
关于作者
