上一篇已經談過,在現內核的中引入設備樹之后對於內核驅動的編寫,主要集中在硬件接口的配置上了即xxxx.dts文件的編寫。
在自己的開發板上移植按鍵驅動:
1、根據開發板的原理圖
確定按鍵的硬件接口為:GPIO2_2、GPIO2_3、GPIO2_5、GPIO0_30。
修改dts文件使其與原理圖的按鍵接口一致。
gpio_buttons: gpio_buttons@0 { compatible = "gpio-keys"; #address-cells = <1>; #size-cells = <0>; switch@1 { label = "button0"; linux,code = <0x100>; gpios = <&gpio2 3 GPIO_ACTIVE_HIGH>; }; switch@2 { label = "button1"; linux,code = <0x101>; gpios = <&gpio2 2 GPIO_ACTIVE_HIGH>; }; switch@3 { label = "button2"; linux,code = <0x102>; gpios = <&gpio0 30 GPIO_ACTIVE_HIGH>; gpio-key,wakeup; }; switch@4 { label = "button3"; linux,code = <0x103>; gpios = <&gpio2 5 GPIO_ACTIVE_HIGH>; }; };
gpio_keys_s0: gpio_keys_s0 { pinctrl-single,pins = < 0x94 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_oen_ren.gpio2_3 */ 0x90 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_advn_ale.gpio2_2 */ 0x70 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_wait0.gpio0_30 */ 0x9c (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ben0_cle.gpio2_5 */ >; };
保存編譯生成zyr-am335x-evmsk.dtb
在內核中確保xxx/linux3.14.65/drivers/input/keyboard/gpio_key.c被編譯進去(可以通過各層的Makefile與Kconfig還有menuconfig來實現)
編譯好的內核和dtb文件下載到開發板中查看按鍵的事件類型:
[root@zyr-am335x mnt]#cd [root@zyr-am335x ]#cat /proc/bus/input/devices I: Bus=0019 Vendor=0001 Product=0001 Version=0100 N: Name="gpio_buttons.7" P: Phys=gpio-keys/input0 S: Sysfs=/devices/gpio_buttons.7/input/input0 U: Uniq= H: Handlers=event0 B: PROP=0 B: EV=3 B: KEY=f 0 0 0 0 0 0 0 0 [root@zyr-am335x ]#
可以看到按鍵的事件或者是用戶接口吧為event0.。知道了用戶的按鍵接口就可以編寫測試程序了。
測試程序目的:實現一個按鍵對應一個LED燈,按鍵按一次LED燈的狀態變化一次(前提是led子系統對應的LED驅動已經加載入內核中):
#include <stdio.h> #include <linux/input.h> #include <fcntl.h> #include <sys/time.h> #include <unistd.h> void keyboard_test() { int count_sw1 = 0; int count_sw2 = 0; int count_sw3 = 0; int count_sw4 = 0; int fd=open("/dev/input/event0",O_RDWR); if( fd <= 0 ) { printf("Can not open keyboard input file\n"); } struct input_event *event; char buf[128] = {0}; fd_set rfds; FD_ZERO(&rfds); FD_SET(fd, &rfds); while(1) { int ret = select(fd + 1,&rfds, NULL,NULL,NULL); if(ret < 0) continue; if( FD_ISSET(fd, &rfds) ) { int readn = read(fd, buf, sizeof(struct input_event)); if (readn <= 0) { printf("uart read error %d\n", readn); continue; } struct input_event *my_event=(struct input_event*)buf; if(my_event->type == EV_KEY) { switch( my_event->code ) { case 256: printf("This is a button:%d %d\n", my_event->code,my_event->value); count_sw1++; if(count_sw1==1) { system("echo 1 > /sys/class/leds/zyrD1:green:usr0/brightness"); } else if(count_sw1==4) { system("echo 0 > /sys/class/leds/zyrD1:green:usr0/brightness"); count_sw1=0; } break; case 257: printf("This is a button:%d %d\n", my_event->code,my_event->value); count_sw2++; if(count_sw2==1) { system("echo 1 > /sys/class/leds/zyrD2:green:usr1/brightness"); } else if(count_sw2==4) { system("echo 0 > /sys/class/leds/zyrD2:green:usr1/brightness"); count_sw2=0; } break; case 258: printf("This is a button:%d %d\n", my_event->code,my_event->value); count_sw3++; if(count_sw3==1) { system("echo 1 > /sys/class/leds/zyrD3:green:heartbeat/brightness"); } else if(count_sw3==4) { system("echo 0 > /sys/class/leds/zyrD3:green:heartbeat/brightness"); count_sw3=0; } break; case 259: printf("This is a button:%d %d\n", my_event->code,my_event->value); count_sw4++; if(count_sw4==1) { system("echo 1 > /sys/class/leds/zyrD4:green:mmc0/brightness"); } else if(count_sw4==4) { system("echo 0 > /sys/class/leds/zyrD4:green:mmc0/brightness"); count_sw4=0; } break; default: break; } } } } } int main() { keyboard_test(); return 0; }
將生成的可執行文件copy到nfs的共享目錄下運行:
[root@zyr-am335x ]#cd mnt/ [root@zyr-am335x mnt]#ls LED_zixitong gpio_keys.ko leds-gpio.ko zyr-hello.ko gpio_buttons_leds led_test zleds-gpio.ko [root@zyr-am335x mnt]#./gpio_buttons_leds This is a button:257 1 This is a button:257 0 This is a button:258 1 This is a button:258 0 This is a button:259 1 This is a button:259 0 This is a button:256 1 This is a button:256 0 This is a button:256 1 This is a button:256 0 This is a button:257 1 This is a button:257 0 This is a button:258 1 This is a button:258 0 This is a button:259 1 This is a button:259 0
其中的256,257,258,259分別對應dts文件中的linux,code = <0x101>;linux,code = <0x102>;linux,code = <0x103>;linux,code = <0x104>;