KeyPad Device Control - Device driver Jo, Heeseung
HBE-SM5-S4210 에는 16 개의 Tack Switch 를사용하여 4 행 4 열의 Keypad 가장착 4x4 Keypad 2
KeyPad 를제어하기위하여 FPGA 내부에 KeyPad controller 가구현 KeyPad controller 16bit 로구성된 2 개의 register 에의해제어 - Keypad_Col_Reg(Keypad Column Register) - Keypad_Row_Reg (Keypad Row Register) 3
Keypad Column Register 의데이터비트구조 Physical Address 0x0500_0070 Dot_Scan_Reg BIT 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Reserved COL_3 COL_2 COL_1 COL_0 Reset X X X X X X 0 0 0 0 0 0 0 0 0 0 Bits Name Description 0 COL_0 Keypad Column Bit0 (Active High) 1 COL_1 Keypad Column Bit1 (Active High) 2 COL_2 Keypad Column Bit2 (Active High) 3 COL_3 Keypad Column Bit3 (Active High) 4
Keypad Row Register 의데이터비트구조를나타낸표 Physical Address 0x0500_0072 Dot_Scan_Reg BIT 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Reserved ROW_3 ROW_2 ROW_1 ROW_0 Reset X X X X X X 0 0 0 0 0 0 0 0 0 0 Bits Name Description 0 ROW_0 Keypad ROW Bit0 (Active High) 1 ROW_1 Keypad ROW Bit1 (Active High) 2 ROW_2 Keypad ROW Bit2 (Active High) 3 ROW_3 Keypad ROW Bit3 (Active High) Keypad Column/Row Register 는 Keypad 로부터출력된 Data 를저장하는메모리역할 Host 쪽에서는 Register 에기록은할수없으며오직읽기만가능 5
드라이버소스파일 Keypad 드라이버는커널에포함 linux-2.6.35-s4210/drviers/input/keyboard/ hanback_fpga_keypad.c 설정방법 menuconfig 를실행 Device Drivers -> Input device support -> [*] keyboards -> [*] HBE-XXX-S4210 FPGA keypad support 6
드라이버테스트프로그램작성 root@ubuntu:/working/device_driver/keypad_driver# vi key_test.c 001: #include <stdio.h> 002: #include <stdlib.h> 003: #include <string.h> 004: #include <sys/ioctl.h> 005: #include <sys/types.h> 006: #include <sys/stat.h> 007: #include <fcntl.h> 008: #include <unistd.h> 009: #include <linux/input.h> // 커널소스 /include/linux/input.h 에서 struct input_event 확인 010: 011: #define EVENT_BUF_NUM 64 012: 7
013: int main(void) 014: { 015: int i, quit=1; 016: int fd = -1; 017: size_t read_bytes; 018: struct input_event event_buf[event_buf_num]; 019: 020: if ((fd = open("/dev/input/event2", O_RDONLY)) < 0) 021: { 022: printf("application : keypad driver open fail!\n"); 023: exit(1); 024: } 025: 026: printf("press the key button!\n"); 027: printf("press the key 16 to exit!\n"); 028: 8
029: while(quit) 030: { 031: read_bytes = read(fd, event_buf, (sizeof(struct input_event)*event_buf_num) ); 032: if( read_bytes < sizeof(struct input_event) ) 033: { 034: printf("application : read error!!"); 035: exit(1); 036: } 037: 038: for( i=0; i<(read_bytes/sizeof(struct input_event)); i++ ) 039: { 040: if ( (event_buf[i].type == EV_KEY) && (event_buf[i].value == 0)) 041: { 042: printf("\n Button key : %d\n", event_buf[i].code); 9
043: 044: if(event_buf[i].code == 16) { 045: printf("\napplication : Exit Program!! (key = %d)\n", event_buf[i].code); 046: quit = 0; 047: } 048: } 049: } 050: } 051: close(fd); 052: return 0; 053: } 10
root@ubuntu:/working/device_driver/keypad_driver# vi Makefile CC = arm-linux-gcc CFLAGS = -DNO_DEBUG EXEC=key_test OBJS=$(EXEC).o ####### Implicit rules.suffixes:.cpp.cxx.cc.c.c.cpp.o: $(CXX) -c $(CXXFLAGS) -o $@ $<.cxx.o: $(CXX) -c $(CXXFLAGS) -o $@ $<.cc.o: $(CXX) -c $(CXXFLAGS) -o $@ $<.C.o: $(CXX) -c $(CXXFLAGS) -o $@ $<.c.o: $(CC) -c $(CFLAGS) -o $@ $< all: $(EXEC) $(EXEC): $(OBJS) $(CC) -o $@ $^ clean: rm -f $(OBJS) $(EXEC) 11
컴파일 root@ubuntu:/working/device_driver/keypad_driver# ls Makefile key_test.c root@ubuntu:/working/device_driver/keypad_driver# make clean; make ------------------다음과같은메시지가출력된다 ----------------- rm -f key_test.o key_test arm-linux-gcc -c -DNO_DEBUG -o key_test.o key_test.c arm-linux-gcc -o key_test key_test.o root@ubuntu:/working/device_driver/keypad_driver# ls Makefile key_test key_test.c key_test.o 테스트 board 에서실행 12
KeyPad Device Control - mmap() Jo, Heeseung
KeyPad 제어 /working/mmap/keypad 디렉터리에서 keypad.c 작성 root@ubuntu:# mkdir -p /working/mmap/keypad root@ubuntu:# cd /working/mmap/keypad/ root@ubuntu:/working/mmap/keypad# vi keypad.c 001: #include <stdio.h> 002: #include <string.h> 003: #include <stdlib.h> 004: #include <unistd.h> 005: #include <sys/mman.h> 006: #include <fcntl.h> 007: 008: #define FPGA_BASEADDRESS 0x05000000 009: #define PIEZO_OFFSET 0x50 010: #define KEY_COL_OFFSET 0x70 011: #define KEY_ROW_OFFSET 0x72 012: 14
KeyPad 제어 013: int main(void) 014: { 015: short value; 016: unsigned short *addr_fpga; 017: unsigned short *keypad_row_addr, *keypad_col_addr, *piezo_addr; 018: int fd; 019: int i,quit=1; 020: if ((fd=open("/dev/mem",o_rdwr O_SYNC)) < 0) { 021: perror("mem open fail\n"); 022: exit(1); 023: } 024: 025: addr_fpga= (unsigned short *)mmap(null, 4096, PROT_WRITE PROT_READ, MAP_SHARED, fd, FPGA_BASEADDRESS); 027: keypad_col_addr = addr_fpga + KEY_COL_OFFSET/sizeof(unsigned short); 028: 029: keypad_row_addr = addr_fpga + KEY_ROW_OFFSET/sizeof(unsigned short); 030: 031: piezo_addr = addr_fpga + PIEZO_OFFSET/sizeof(unsigned short); 032: 15
KeyPad 제어 033: 034: if(*keypad_row_addr ==(unsigned short)-1 *keypad_col_addr ==(unsigned short)-1 ) 035: { 036: close(fd); 037: printf("mmap error\n"); 038: exit(1); 039: } 040: 041: printf("- Keypad\n"); 042: printf("press the key button!\n"); 043: printf("press the key 0x16 to exit!\n"); 044: 045: while(quit) { 046: *keypad_row_addr = 0x01; 047: usleep(1000); 048: value =(*keypad_col_addr & 0x0f); 049: *keypad_row_addr = 0x00; 050: switch(value) { 051: case 0x01 : value = 0x01; break; 052: case 0x02 : value = 0x02; break; 053: case 0x04 : value = 0x03; break; 054: case 0x08 : value = 0x04; break; 055: } 16
KeyPad 제어 056: if(value!= 0x00) goto stop_poll; 057: 058: *keypad_row_addr = 0x02; 059: for(i=0;i<2000;i++); 060: value = value (*keypad_col_addr & 0x0f); 061: *keypad_row_addr = 0x00; 062: switch(value) { 063: case 0x01 : value = 0x05; break; 064: case 0x02 : value = 0x06; break; 065: case 0x04 : value = 0x07; break; 066: case 0x08 : value = 0x08; break; 067: } 068: if(value!= 0x00) goto stop_poll; 069: 070: *keypad_row_addr = 0x04; 071: for(i=0;i<2000;i++); 072: value = value (*keypad_col_addr & 0x0f); 073: *keypad_row_addr = 0x00; 074: switch(value) { 075: case 0x01 : value = 0x09; break; 076: case 0x02 : value = 0x0a; break; 077: case 0x04 : value = 0x0b; break; 078: case 0x08 : value = 0x0c; break; 079: } 080: if(value!= 0x00) goto stop_poll; 17
KeyPad 제어 081: 082: *keypad_row_addr = 0x08; 083: for(i=0;i<2000;i++); 084: value = value (*keypad_col_addr & 0x0f); 085: *keypad_row_addr = 0x00; 086: switch(value) { 087: case 0x01 : value = 0x0d; break; 088: case 0x02 : value = 0x0e; break; 089: case 0x04 : value = 0x0f; break; 090: case 0x08 : value = 0x10; break; 091: } 092: 093: stop_poll: 094: if(value>0) { 095: printf("\n pressed key = %02d\n",value); 096: *piezo_addr=0x1; 097: usleep(50000); 098: *piezo_addr=0x0; 099: } 18
KeyPad 제어 100: else *keypad_row_addr = 0x00; 101: for(i=0;i<4000000;i++); 102: 103: if(value == 16) { 104: printf("\nexit Program!! (key = %02d)\n\n", value); 105: *piezo_addr=0x1; 106: usleep(150000); 107: *piezo_addr=0x0; 108: quit = 0; 109: } 110: } 111: 112: munmap(addr_fpga,4096); 113: close(fd); 114: return 0; 115: } 19
KeyPad 제어 Makefile 작성 root@ubuntu:/working/mmap/5.keypad# vi Makefile CC = arm-linux-gcc CFLAGS = -DNO_DEBUG EXEC=keypad OBJS=$(EXEC).o ####### Implicit rules.suffixes:.cpp.cxx.cc.c.c.cpp.o: $(CXX) -c $(CXXFLAGS) -o $@ $<.cxx.o: $(CXX) -c $(CXXFLAGS) -o $@ $<.cc.o: $(CXX) -c $(CXXFLAGS) -o $@ $<.C.o: $(CXX) -c $(CXXFLAGS) -o $@ $<.c.o: $(CC) -c $(CFLAGS) -o $@ $< all: $(EXEC) $(EXEC): $(OBJS) $(CC) -o $@ $^ clean: rm -f $(OBJS) $(EXEC) 20
KeyPad 제어 컴파일 root@ubuntu:/working/mmap/keypad# make arm-linux-gcc -c -DNO_DEBUG -o keypad.o keypad.c arm-linux-gcc -o keypad keypad.o 테스트 board 에서실행 [root@sm5s4210 ~]$./keypad - Keypad press the key button! press the key 0x16 to exit! pressed key = 01 pressed key = 16 Exit Program!! (key = 16) 21