1 / 57

14 주차 . 디바이스 드라이버의 응용

14 주차 . 디바이스 드라이버의 응용. 수원과학대학교 정보통신과. 14.1 디바이스와 주소. 디바이스의 주소 지정 방식 전용 입출력 방식 (dedicated I/O 혹은 isolated I/O) 메모리 사상 입출력 방식 (memory mapped I/O). PXA270 디바이스의 주소공간. 커널이 가상 주소를 사용해 컴퓨팅 자원에 접근하므로 ARM 아키텍처의 디바이스에 접근하려면 물리 주소를 가상 메모리 공간으로 사상해야 작업 가능

arvid
Download Presentation

14 주차 . 디바이스 드라이버의 응용

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 14주차. 디바이스 드라이버의 응용 수원과학대학교 정보통신과

  2. 14.1 디바이스와 주소 • 디바이스의 주소 지정 방식 • 전용 입출력 방식(dedicated I/O 혹은 isolated I/O) • 메모리 사상 입출력 방식(memory mapped I/O) 수원과학대학 정보통신과

  3. PXA270 디바이스의 주소공간 • 커널이 가상 주소를 사용해 컴퓨팅 자원에 접근하므로 ARM 아키텍처의 디바이스에 접근하려면 물리 주소를 가상 메모리 공간으로 사상해야 작업 가능 • 디바이스의 접근은 시스템 모드에서 수행되므로 디바이스를 위한 가상 주소는 커널 공간임 • 응용 프로그램은 커널 공간을 직접 제어할 수 없으며 커널도 사용자 공간을 직접 다룰 수 없음 • 따라서 디바이스 드라이버가 사용자와 커널 공간 사이에 데이터를 전송하려면 시스템호출과 같은 함수를 사용해야 함 수원과학대학 정보통신과

  4. 타겟 시스템의 디바이스 구성 수원과학대학 정보통신과

  5. 타겟 시스템 디바이스들의 물리주소 수원과학대학 정보통신과

  6. 디바이스 드라이버 제작 과정 • 디바이스 드라이버 소스 코드 작성 • 응용 프로그램 소스 코드 작성 • 디바이스 드라이버와 응용 프로그램의 컴파일 • 호스트 시스템에서 타겟 시스템으로 디바이스 드라이버와 응용 프로그램을 전송 • 디바이스 드라이버를 타겟 시스템 커널에 적재 • 타겟 시스템에서 응용 프로그램을 수행하여 테스트 수원과학대학 정보통신과

  7. LED 디바이스 드라이버 [1] LED 포트를 GND로 만들면 불이 켜지고 3V를 가하면 불이 꺼진다. 수원과학대학 정보통신과

  8. LED 디바이스 드라이버 [2] LED의 물리주소 p = 0x12400000 예: LED7,8 켜기 *p = 0x3F 예: LED 1,2 켜기 *p = 0xF3 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 각 bit에 0을 기록하면 켜지고, 1을 기록하면 꺼진다. 수원과학대학 정보통신과

  9. 0 1 2 3 4 5 6 7 8 9 7-세그먼트 FND [1] 숫자별 값 b7 b6 b5 b4 b3 b2 b1 b0 수원과학대학 정보통신과

  10. FND [2] FND 별 물리 주소 0x11700000 0x11500000 0x11300000 0x11100000 0x11600000 0x11400000 0x11200000 0x11000000 FND8 FND7 FND6 FND5 FND4 FND3 FND2 FND1 b7 b6 b5 b4 b3 b2 b1 b0 a a f b g p = 0x11000000 *p = 0x5B 예: FND1에 2를 쓰려면 f b g e c e c d h h d 수원과학대학 정보통신과

  11. 키 매트릭스 KEYOUT 물리주소 = 0x11D000000 • KEY 검출 방법 • KEYOUT0에 1값을 출력하고 KEYIN0~KEYIN3을 차례대로 읽음 • 이 때 어떤 키가 눌려지면 대응하는 KEYIN의 값이 1로 검출되고 그렇지 않으면 0값이 검출됨 • 위 과정을 KEYOUT1, 2, 3에 대해 반복 • 예를 들어 KB1을 눌렀을 경우, KEYOUT3에 1을 출력했을 때 KEYIN을 읽으면 KEYIN0의 값이 1로 검출됨. KEYIN 물리주소 = 0x11E000000 수원과학대학 정보통신과

  12. 문자 LCD [1] • 16문자씩 2라인으로 표시. 폰트는 5*7도트. • LCD 컨트롤러에는 DR(data register)와 IR(instruction register)가 있음 • LCD 물리주소 • LCD 데이터: 0x12300000 • LCD 제어명령: 0x12380000 수원과학대학 정보통신과

  13. 문자 LCD [2] • 화면지우기(clear display): 0x01 • 리턴홈(return home): 0x02 • 엔트리모드 설정(entry mode set): • I/D=0: 커서우측이동, I/D=1: 커서 좌측이동, S=1: I/D값에 따라 전체내용 시프트 • 화면설정(display on/off control): • D: 화면표시 ON/OFF, C: 커서 ON/OFF, B: 커서 깜빡임 여부 • 기능설정(function set): • DL=0: 데이터 전송을 4비트씩, DL=1: 데이터 전송을 8비트씩, N=0: 1행만 사용, N=1: 2행 다 사용, F=0: 5x8도트문자, F=1: 5x10도트 문자 • DDRAM 주소선택: 표11-4 주소 사용 수원과학대학 정보통신과

  14. 0x1180_0000 0x1190_0000 0x11A0_0000 0x11B0_0000 0x11C0_0000 Dot Matrix [1] • LED들을 매트릭스 형태로 배선시킨 구조 • LED를 점등해 원하는 글씨나 그림을 나타내는 디바이스 • 5개의 열에는 주소 버스가 연결, 7개의 행에는 데이터 버스가 연결됨 데이터 버스 연결 주소 버스 연결 수원과학대학 정보통신과

  15. Dot Matrix [2] 0x11800000에 0x01을 기록하면 5x7 Matrix b6 b5 각 bit에 1을 기록하면 켜지고, 0을 기록하면 꺼진다. b4 b3 b2 Dot Matirx 각 세로줄의 물리주소 b1 b0 0x11C00000에 0x40을 기록하면 0x118000000 0x119000000 0x11A000000 0x11B000000 0x11C000000 수원과학대학 정보통신과

  16. 실습 프로그램 다운 받기 • 리눅스 기본 웹브라우저인 firefox 실행 • 강의 홈페이지(192.168.166.254)임베디드시스템1자료실14주차 실습프로그램들14.tgz 다운로드 • 웹 브라우저에서 다운받을 때 디스크에 저장을 선택 • cd ~/Desktop             (파일을 다운받는 디폴트 폴더가 ~/Desktop 임) • mkdir -p /embed/ex/14    (14 디렉토리 생성) • mv 14.tgz /embed/ex/14   (/embed/ex/14 디렉토리로 파일 이동) • cd /embed/ex/14           (/embed/ex/14 디렉토리로 위치 이동) • tar xvfz 14.tgz           (압축풀기) 수원과학대학 정보통신과

  17. 타겟 보드의 파일 시스템 초기화 • 왜? 타켓보드에서 타인이 앞서 실습한 결과를 없애기 위해 • 호스트에서 • cp /embed/hybus/images/rootfs.img /tftpboot • 타겟에서 • hybus> tftp rootfs.img root • hybus> flash root 수원과학대학 정보통신과

  18. LED 디바이스 드라이버 프로그램 작성(14/led/led.c) 실습 14-1 LED 디바이스 드라이버 작성 01 #include <linux/ioport.h> 02 #include <asm/uaccess.h> 03 #include <linux/module.h> 04 #include <linux/fs.h> 05 #include <asm/io.h> 06 07 #define LED_MAJOR 239 08 #define LED_NAME "LED" 09 #define LED_MODULE_VERSION "LED IO PORT V0.1" 10 #define LED_ADDRESS 0x12400000 11 #define LED_CS (*((volatile unsigned char *)(mem_base))) 12 13 static void *mem_base; 14 static unsigned long mem_addr, mem_len; 15 16 static int led_clear(void) { 17 LED_CS = 0xFF; 18 return 0; 19 } 20 21 int led_open(struct inode *minode, struct file *mfile) 22 { 23 return 0; 24 } 25 26 int led_release(struct inode *minode, struct file *mfile) 27 { 28 return 0; 29 } 30 31 ssize_t led_write_byte(struct file *inode, const char *gdata, size_t length, loff_t *off_what) 32 { 33 unsigned char c; 34 get_user(c, (unsigned char *)gdata); 35 LED_CS = c; 36 return length; 37 } 수원과학대학 정보통신과

  19. 실습 14-1 LED 디바이스 드라이버 작성 38 39 static struct file_operations led_fops = { 40 .owner = THIS_MODULE, 41 .write = led_write_byte, 42 .open = led_open, 43 .release = led_release, 44 }; 45 46 int led_init(void) 47 { 48 int result; 49 result = register_chrdev(LED_MAJOR, LED_NAME, &led_fops); 50 if(result < 0) { 51 printk(KERN_WARNING "can't get any major number.\n"); 52 return result; 53 } 54 mem_addr = LED_ADDRESS; 55 mem_len = 0x1000; 56 mem_base = ioremap_nocache(mem_addr, mem_len); 57 if(!mem_base) { 58 printk("Error mapping LED memory\n"); 59 release_mem_region(mem_addr, mem_len); 60 return -EBUSY; 61 } 62 printk("init module, LED major number : %d\n", LED_MAJOR); 63 return 0; 64 } 65 66 void led_exit(void) 67 { 68 led_clear(); 69 if (unregister_chrdev(LED_MAJOR, LED_NAME)) 70 printk(KERN_WARNING"%s driver cleanup failed.\n", LED_NAME); 71 iounmap(mem_base); 72 } 73 74 MODULE_LICENSE("GPL"); 75 module_init(led_init); 76 module_exit(led_exit); 수원과학대학 정보통신과

  20. 실습 14-1 LED 디바이스 드라이버 작성 • LED 디바이스 드라이버 테스트 프로그램 작성(14/led/test_led.c) 01 #include <stdio.h> 02 #include <stdlib.h> 03 #include <unistd.h> 04 #include <sys/types.h> 05 #include <sys/stat.h> 06 #include <fcntl.h> 07 08 int main(int argc, char **argv) 09 { 10 int dev; 11 char buff; 12 13 if(argc <= 1) { 14 printf("please input the parameter! ex)./test 0xa1\n"); 15 return -1; 16 } 17 18 dev = open("/dev/LED", O_WRONLY); 19 if (dev != -1) { 20 if(argv[1][0] == '0' && (argv[1][1] == 'x' || argv[1][1] == 'X')) 21 buff = (unsigned char)strtol(&argv[1][2], NULL, 16); 22 else 23 buff = atoi(argv[1]); 24 write(dev, &buff, 1); 25 close(dev); 26 } 27 else { 28 printf( "Device Open ERROR!\n"); 29 exit(-1); 30 } 31 32 return(0); 33 } 수원과학대학 정보통신과

  21. 실습 14-1 LED 디바이스 드라이버 작성 • LED 디바이스 프로그램 컴파일 위한 Makefile 작성(14/led/Makefile) 01 KDIR := /embed/kernel/linux 02 03 obj-m := led.o 04 05 build: 06 make -C $(KDIR) SUBDIRS=$(PWD) modules 07 08 09 clean: 10 rm -rf *.o *.ko *.mod.c 수원과학대학 정보통신과

  22. ② ③ ④ ① ② ③ ④ ⑤ ⑥ 실습 14-1 LED 디바이스 드라이버 작성 • 디바이스 드라이버와 응용프로그램을 컴파일 • 생성한 모듈(led.ko)과 응용 프로그램(test_led)을 타겟 시스템으로 전송 • 타겟 시스템에서 디바이스 드라이버를 적재→응용 프로그램 테스트 수원과학대학 정보통신과

  23. 실습 14-2 FND 디바이스 드라이버 작성 • FND 디바이스 드라이버 프로그램 작성(14/fnd/fnd.c) 001 #include <linux/module.h> …… 010 #include <asm/io.h> 011 012 #define FND_MAJOR 231 013 #define FND_NAME "FND" 014 #define MAX_FND 8 015 016 #define FPGA_FND_CS0 (0x11000000) …… 023 #define FPGA_FND_CS7 (0x11700000) 024 025 #define FND_CS0 (*((volatile unsigned char *)(mem_fnd_cs0))) …… 032 #define FND_CS7 (*((volatile unsigned char *)(mem_fnd_cs7))) 033 034 void *mem_fnd_cs0, *mem_fnd_cs1, *mem_fnd_cs2, *mem_fnd_cs3, *mem_fnd_cs4, *mem_fnd_cs5, *mem_fnd_cs6, *mem_fnd_cs7; 035 036 static char disp[8] = {0}; 037 038 static int fnd_clear(void) 039 { 040 FND_CS0 = 0x00; …… 047 FND_CS7 = 0x00; 048 return 0; 049 } 050 수원과학대학 정보통신과

  24. 실습 14-2 FND 디바이스 드라이버 작성 051 static int fnd_open(struct inode *minode, struct file *mfile) 052 { 053 fnd_clear(); 054 return 0; 055 } 056 057 static int fnd_release(struct inode *minode, struct file *mfile) 058 { 059 return 0; 060 } 061 062 static ssize_t fnd_write (struct file *filp, const char *buf, size_t count, loff_t *f_pos) 063 { 064 copy_from_user(disp, buf, count); 065 FND_CS0 = disp[0]; mdelay(100); ………… 072 FND_CS7 = disp[7]; mdelay(100); 073 return 0; 074 } 075 076 static struct file_operations device_fops = { 077 .owner = THIS_MODULE, 078 .open = fnd_open, 079 .write = fnd_write, 080 .release = fnd_release, 081 }; 082 수원과학대학 정보통신과

  25. 실습 14-2 FND 디바이스 드라이버 작성 083 static int fnd_init(void) 084 { 085 int result; 086 unsigned long mem_addr_fnd0, mem_addr_fnd1, mem_addr_fnd2, mem_addr_fnd3, mem_addr_fnd4, mem_addr_fnd5,mem_addr_fnd6, mem_addr_fnd7; 087 unsigned long mem_len; 088 089 result = register_chrdev(FND_MAJOR, FND_NAME, &device_fops); 090 printk("FPGA %s MAJOR %d IRQ %d\n", FND_NAME, FND_MAJOR,result); 091 mem_addr_fnd0 = FPGA_FND_CS0; …… 098 mem_addr_fnd7 = FPGA_FND_CS7; 099 mem_len = 0x1000; 100 101 mem_fnd_cs0 = ioremap_nocache ( mem_addr_fnd0, mem_len); 102 if( !mem_fnd_cs0) { 103 printk("Error mapping fnd0 memery"); 104 return -EBUSY; 105 } …… 143 mem_fnd_cs7 = ioremap_nocache ( mem_addr_fnd7, mem_len); 144 if( !mem_fnd_cs7) { 145 printk("Error mapping fnd7 memery"); 146 return -EBUSY; 147 } 148 return 0; 149 } 150 151 static void fnd_exit(void) 152 { 153 fnd_clear(); 154 iounmap(mem_fnd_cs0); …… 161 iounmap(mem_fnd_cs7); 162 unregister_chrdev(FND_MAJOR, FND_NAME); 163 printk("%s unregisterd.\n", FND_NAME); 164 } 165 MODULE_LICENSE("GPL"); 166 module_init(fnd_init); // 모듈을 커널에 등록시 fnd_init 함수 호출 167 module_exit(fnd_exit); // 커널에서 모듈 제거시 fnd_exit 함수 호출 수원과학대학 정보통신과

  26. 실습 14-2 FND 디바이스 드라이버 작성 • FND 디바이스 테스트 프로그램 작성(14/fnd/test_fnd.c) 01 #include <stdio.h> 02 #include <fcntl.h> 03 04 #define MAXFND 8 05 06 static char fndDev[] = "/dev/FND"; 07 static int fndFd = (-1); 08 09 asc2fnd(char *s, int n) 10 { 11 char c; 12 while (n-- > 0) { 13 c = *s; 14 switch (c) { // 여러 가지 문자 추가 가능 15 case '0': c = 0x3f; break; …… 24 case '9': c = 0x67; break; 25 default: c = 0x00; break; 26 } 27 *s++ = c; 28 } 29 } 30 31 main(int ac, char *av[]) 32 { 33 int n; 34 char buf[MAXFND+1]; 35 36 fndFd = open( fndDev, O_RDWR); 37 if (fndFd < 0) { 38 fprintf(stderr, "cannot open FND (%d)", fndFd); 39 exit(2); 40 } 41 memset(buf, 0, sizeof(buf)); 42 if (ac > 1) { 43 n = strlen(av[1]); 44 if (n > MAXFND) 45 n = MAXFND; 46 memcpy(buf, av[1], n); 47 } 48 asc2fnd(buf, MAXFND); 49 write(fndFd, buf, MAXFND); 50 } 수원과학대학 정보통신과

  27. ② ③ 실습 14-2 FND 디바이스 드라이버 작성 • FND 디바이스 드라이버 프로그램을 컴파일하기 위한 Makefile 작성 • 디바이스 드라이버와 응용프로그램을 컴파일 • make • arm-linux-gcc –o test_fnd test_fnd.c • 기존 디바이스 드라이버를 테스트한 후에 삭제 수원과학대학 정보통신과

  28. ② ③ ④ 실습 14-2 FND 디바이스 드라이버 작성 • 새로 생성한 디바이스 드라이버(fnd.ko)와 응용 프로그램(test_fnd)을 타겟 시스템으로 전송 • 응용프로그램을 실행한 후 임의의 숫자들을 입력해 결과를 관찰 수원과학대학 정보통신과

  29. 실습 14-3 키 매트릭스 디바이스 드라이버 작성 • 키 매트릭스 디바이스 드라이버 프로그램 작성(14/key/key.c) 001 #include <linux/module.h> ------------- 010 #include <asm/io.h> 011 012 #define KEY_MAJOR 233 013 #define KEY_NAME "KEY" 014 #define SCAN_NUM 4 015 016 #define FPGA_KEY_OUT (0x11D00000) 017 #define FPGA_KEY_IN (0x11E00000) 018 019 #define KEYOUT (*(volatile unsigned char *)mem_key_out) 020 #define KEYIN (*(volatile unsigned char *)mem_key_in) 021 022 static void *mem_key_out, *mem_key_in; 023 static struct timer_list key_timer_str; 024 static unsigned char key_data; 025 static pid_t id; 026 static int n = 1; 027 028 int key_open (struct inode *inode, struct file *filp) 029 { 030 return 0; 031 } 032 033 int key_release (struct inode *inode, struct file *filp) 034 { 035 del_timer(&key_timer_str); 036 return 0; 037 } 038 수원과학대학 정보통신과

  30. 실습 14-3 키 매트릭스 디바이스 드라이버 작성 039 ssize_t key_read (struct file *filp, char *buf, size_t count, loff_t *f_pos) 040 { 041 copy_to_user(buf, &key_data, sizeof(key_data)); 042 return 0; 043 } 044 045 void timer_function(unsigned long data) 046 { 047 unsigned int i, in, out; 048 049 for(i=0; i<4; i++) { 050 out = (1 << i); 051 KEYOUT = out; 052 in = ((KEYIN) & (0x0F)); 053 out =((out) << 4); 054 if (in != 0) { 055 key_data = ((out) | (in)); 056 kill_proc(id, SIGUSR1, 1); 057 } 058 } 059 key_timer_str.expires = jiffies + (HZ/100); 060 add_timer(&key_timer_str); 061 } 062 063 ssize_t key_write (struct file *filp, const char *buf, size_t count, loff_t *f_pos) 064 { 065 get_user(id,(int*)buf); 066 init_timer(&key_timer_str); 067 key_timer_str.expires = jiffies + (HZ/100); 068 key_timer_str.data = (unsigned long)n; 069 key_timer_str.function = &timer_function; 070 add_timer(&key_timer_str); 071 return 0; 072 } 073 수원과학대학 정보통신과

  31. 실습 14-3 키 매트릭스 디바이스 드라이버 작성 074 struct file_operations key_fops = { 075 .owner = THIS_MODULE, 076 .read = key_read, 077 .write = key_write, 078 .open = key_open, 079 .release = key_release, 080 }; 081 082 static int key_init(void) 083 { 084 int result; 085 unsigned long mem_addr_out, mem_addr_in, mem_len; 086 087 result = register_chrdev(KEY_MAJOR, KEY_NAME, &key_fops); …… 092 mem_addr_out = FPGA_KEY_OUT; 093 mem_addr_in = FPGA_KEY_IN; 094 mem_len = 0x1000; 095 mem_key_out = ioremap_nocache (mem_addr_out, mem_len); …… 100 mem_key_in = ioremap_nocache (mem_addr_in, mem_len); …… 105 printk("FPGA %s MAJOR %d\n", KEY_NAME, KEY_MAJOR); 106 return 0; 107 } 108 109 static void key_exit(void) 110 { 111 unregister_chrdev (KEY_MAJOR, KEY_NAME); 112 } 113 114 MODULE_LICENSE("GPL"); 115 module_init(key_init); 116 module_exit(key_exit); 수원과학대학 정보통신과

  32. 실습 14-3 키 매트릭스 디바이스 드라이버 작성 • 키 매트릭스 테스트 프로그램 작성(14/key/test_key.c) 01 #include <stdio.h> …… 08 #include <linux/delay.h> 09 10 static int dev; 11 static unsigned char vkey; 12 13 void keysignal(int sig) 14 { 15 read(dev, &vkey, 1); 16 printf("SIGNAL occur!!!!\n"); 17 } 18 19 int main(void) 20 { 21 pid_t id; 22 23 if ((dev = open("/dev/KEY", O_RDWR)) < 0) { 24 printf("return Value is %d\n",dev); 25 perror("open failed /dev/KEY"); 26 close(dev); 27 exit(-1); 28 } 29 (void) signal (SIGUSR1, keysignal); 30 id = getpid(); 31 write(dev, &id, 4); 32 printf("press the push button!\n"); 33 (void) signal (SIGUSR1, keysignal); 34 while(1) { 35 if(vkey != 0) { 36 printf("vkey is 0x%x\n", vkey); 37 vkey=0; 38 } 39 } 40 close(dev); 41 return 0; 42 } 수원과학대학 정보통신과

  33. 실습 14-3 키 매트릭스 디바이스 드라이버 작성 • Makefile을 작성 • 디바이스 드라이버 모듈과 응용 프로그램을 컴파일 • make • arm-linux-gcc –o test_key test_key.c • 기존 디바이스 드라이버를 테스트 수원과학대학 정보통신과

  34. ② ③ ④ ⑤ 실습 11-3 키 매트릭스 디바이스 드라이버 작성 • 생성한 디바이스 파일(key.ko)과 응용프로그램(test_key)을 타겟 시스템으로 전송 • 기존 디바이스 드라이버를 삭제하고 새 디바이스 드라이버를 커널로 적재하고 새로운 디바이스 파일을 만든 후 응용프로그램으로 테스트 수원과학대학 정보통신과

  35. 실습 14-4 문자형 LCD 디바이스 드라이버 작성 001 #include <linux/module.h> …… 009 #include <asm/io.h> 010 011 #define CLCD_MAJOR 238 012 #define CLCD_NAME "CLCD" 013 014 #define FPGA_CLCD_WR_ADD (0x12300000) 015 #define FPGA_CLCD_RS_ADD (0x12380000) 016 #define CLCD_CMD_ADDR (*((volatile unsigned char *)(mem_base_wr))) 017 #define CLCD_DATA_ADDR (*((volatile unsigned char *)(mem_base_rs))) 018 019 static void *mem_base_wr, *mem_base_rs; 020 static unsigned long mem_addr_wr, mem_addr_rs, mem_len; 021 022 static void lcd_init(void) 023 { 024 CLCD_CMD_ADDR = 0x38; 025 mdelay(300); 026 CLCD_CMD_ADDR = 0x0e; 027 mdelay(100); 028 CLCD_CMD_ADDR = 0x02; 029 mdelay(100); 030 CLCD_CMD_ADDR = 0x01; 031 mdelay(100); 032 } 033 034 static void string_out(char *str) 035 { 036 char *s; 037 int i=0; 038 039 printk("%s\n", str); 040 lcd_init(); 041 for (s=str; *s; s++) { 042 CLCD_DATA_ADDR = *s; 043 if(i == 15) { 044 udelay(100); 045 CLCD_CMD_ADDR = 0xC0; 046 } 047 udelay(100); 048 i++; 049 } 050 } • 문자형 LCD 디바이스 드라이버 프로그램 작성(14/clcd/clcd.c) 수원과학대학 정보통신과

  36. 실습 14-4 문자형 LCD 디바이스 드라이버 작성 …… 062 ssize_t clcd_write (struct file *filp, const char *buf, size_t count, loff_t *f_pos) 063 { 064 char data[32]; 065 066 memset(data, 0 , 32); 067 copy_from_user(data, buf, count); 068 string_out(data); 069 return 0; 070 } 071 072 struct file_operations clcd_fops = { 073 .owner = THIS_MODULE, 074 .write = clcd_write, 075 .open = clcd_open, 076 .release = clcd_release, 077 }; 078 079 static int clcd_init(void) 080 { 081 int result; 082 083 result = register_chrdev(CLCD_MAJOR, CLCD_NAME, &clcd_fops); …… 088 mem_addr_wr = FPGA_CLCD_WR_ADD; 089 mem_addr_rs = FPGA_CLCD_RS_ADD; 090 mem_len = 0x1000; 091 092 mem_base_wr = ioremap_nocache ( mem_addr_wr, mem_len); …… 097 098 mem_base_rs = ioremap_nocache ( mem_addr_rs, mem_len); …… 103 printk("FPGA %s MAJOR %d\n",CLCD_NAME, result); 104 return 0; 105 } 106 107 static void clcd_exit(void) 108 { 109 unregister_chrdev(CLCD_MAJOR, CLCD_NAME); 110 iounmap(mem_base_wr); 111 iounmap(mem_base_rs); 112 } 113 114 MODULE_LICENSE("GPL"); 115 module_init(clcd_init); 116 module_exit(clcd_exit); 수원과학대학 정보통신과

  37. 실습 14-4 문자형 LCD 디바이스 드라이버 작성 01 #include <stdio.h> 02 #include <fcntl.h> 03 #include <stdlib.h> 04 #include <unistd.h> 05 06 static char lcdDev[] = "/dev/CLCD"; 07 static int lcdFd = -1; 08 09 #define MAXCHR 32 10 11 int main(int argc, char **argv) 12 { 13 int n; 14 char buf[MAXCHR]; 15 16 lcdFd = open(lcdDev, O_RDWR); 17 if (lcdFd < 0) { 18 fprintf(stderr, "cannot open CLCD (%d)", lcdFd); 19 exit(2); 20 } 21 22 strcpy(buf, "Hi, Character LCD!\n"); 23 if (argc > 1) { 24 memset(buf, 0, sizeof(buf)); 25 n = strlen(argv[1]); 26 if (n > MAXCHR) 27 n = MAXCHR; 28 memcpy(buf, argv[1], n); 29 } 30 write(lcdFd, buf, MAXCHR); 31 return 0; 32 } • 디바이스 드라이버 테스트 프로그램 작성(14/clcd/test_clcd.c) 수원과학대학 정보통신과

  38. ② ③ 실습 14-4 문자형 LCD 디바이스 드라이버 작성 • 문자 LCD 디바이스 드라이버 프로그램을 컴파일하기 위한 Makefile을 작성 • 디바이스 드라이버 모듈과 응용 프로그램을 컴파일 • make • arm-linux-gcc –o test_clcd test_clcd.c • 기존 디바이스 드라이버와 디바이스 파일을 테스트한 후 삭제 수원과학대학 정보통신과

  39. ② ③ 실습 14-4 문자형 LCD 디바이스 드라이버 작성 • 생성한 디바이스 드라이버(clcd.ko)와 응용 프로그램(test_clcd)을 타겟 시스템으로 전송 • 디바이스 드라이버를 커널로 적재하고 필요한 디바이스 파일을 생성한 후 테스트 수원과학대학 정보통신과

  40. 실습 14-5 도트 매트릭스 디바이스 드라이버 작성 • 도트 매트릭스 디바이스 드라이버 프로그램 작성(11/dot/dot.c) 001 #include <linux/module.h> …… 009 #include <asm/io.h> 010 011 012 #define DOT_MAJOR 232 013 #define DOT_NAME "DOT" 014 015 #define FPGA_DOT_COL_1 (0x11800000) …… 019 #define FPGA_DOT_COL_5 (0x11C00000) 020 021 static void *mem_dot_col1, *mem_dot_col2, *mem_dot_col3, *mem _dot_col4, *mem_dot_col5; 022 023 #define DOT_COL_1 (*((volatile unsigned char *)(mem_dot_col1))) …… 027 #define DOT_COL_5 (*((volatile unsigned char *)(mem_dot_col5))) 028 029 void dot_test(void) 030 { 031 unsigned short dot_table[10][5] = { 032 {0x7F, 0x41, 0x41, 0x41, 0x7F}, 033 {0x00, 0x00, 0x7F, 0x00, 0x00}, …… 041 {0x78, 0x48, 0x48, 0x48, 0x7F} 042 }; 043 int i; 044 045 for(i=0; i < 10; i++) { 046 DOT_COL_1 = dot_table[i][0]; …… 050 DOT_COL_5 = dot_table[i][4]; 051 mdelay(500); 052 } 053 } 054 수원과학대학 정보통신과

  41. 실습 14-5 도트 매트릭스 디바이스 드라이버 작성 055 int dot_open (struct inode *inode, struct file *filp) 056 { 057 DOT_COL_1 = 0x00; …… 061 DOT_COL_5 = 0x00; 062 return 0; 063 } …… 070 int dot_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) 071 { 072 switch(cmd) { 073 case 1: 074 dot_test(); 075 break; 076 default: 077 return 0; 078 } 079 return 0; 080 } 081 082 struct file_operations dot_fops = { 083 .owner = THIS_MODULE, 084 .open = dot_open, 085 .ioctl = dot_ioctl, 086 .release = dot_release, 087 }; 088 089 static int dot_init(void) 090 { 091 int result; 092 unsigned long mem_addr_col1, mem_addr_col2, mem_addr_col3,mem_addr_col4, mem_addr_col5; 093 unsigned long mem_len; 094 095 result = register_chrdev(DOT_MAJOR, DOT_NAME, &dot_fops); 수원과학대학 정보통신과

  42. 실습 14-5 도트 매트릭스 디바이스 드라이버 작성 096 if(result < 0) 097 { 098 printk(KERN_ERR " DOT : failed to register device.\n"); 099 return result; 100 } 101 mem_addr_col1 = FPGA_DOT_COL_1; …… 105 mem_addr_col5 = FPGA_DOT_COL_5; 106 mem_len = 0x1000; 107 108 mem_dot_col1 = ioremap_nocache ( mem_addr_col1, mem_len); …… 131 mem_dot_col5 = ioremap_nocache ( mem_addr_col5, mem_len); …… 136 137 printk("FPGA %s, MAJOR %d\n", DOT_NAME, result); 138 return 0; 139 } 140 141 static void dot_exit(void) 142 { 143 unregister_chrdev(DOT_MAJOR, DOT_NAME); 144 iounmap(mem_dot_col1); …… 148 iounmap(mem_dot_col5); 149 } 150 151 MODULE_LICENSE("GPL"); 152 module_init(dot_init); 153 module_exit(dot_exit); 수원과학대학 정보통신과

  43. 실습 14-5 도트 매트릭스 디바이스 드라이버 작성 • 도트 매트릭스 디바이스 테스트 프로그램 작성(14/dot/test_dot.c) 01 #include <stdio.h> 02 #include <fcntl.h> 03 #include <sys/ioctl.h> 04 05 static char dotDev[] = "/dev/DOT"; 06 static int dotFd = -1; 07 08 int main() 09 { 10 dotFd = open(dotDev, O_RDWR ); 11 12 if ( dotFd < 0 ) { 13 fprintf(stderr, "cannot open DOT (%d)", dotFd); 14 exit(2); 15 } 16 17 ioctl(dotFd, 1, 0); 18 return 0; 19 } 수원과학대학 정보통신과

  44. 실습 14-5 도트 매트릭스 디바이스 드라이버 작성 • 도트 디바이스 프로그램 컴파일하기 위한 Makefile을 작성 • 디바이스 드라이버 모듈과 응용 프로그램을 컴파일 • make • arm-linux-gcc –o test_dot test_dot.c • 기존 디바이스 드라이버를 테스트한 후 디바이스 드라이버와 디바이스 파일을 삭제 ① ② ③ 수원과학대학 정보통신과

  45. 실습 14-5 도트 매트릭스 디바이스 드라이버 작성 • 생성한 디바이스 파일(dot.ko)과 응용프로그램(test_dot)을 타겟 시스템으로 전송 • 디바이스 드라이버를 커널로 적재하고 새로운 디바이스 파일을 만든 후 응용프로그램으로 테스트 ① ② ③ 수원과학대학 정보통신과

  46. 실습문제 1번 Key Driver 개선 • 문제점: 교재의 키 드라이버는 키를 한번 눌러도 여러번 누른 것으로 인식됨 • 개선: 키를 계속 누르고 있어도 한 번 누른 것으로 인식시킨다. 즉, 한번 눌렀다가 뗀 후 다시 눌러야 새로운 키로 인식시킨다. 수원과학대학 정보통신과

  47. [Review] 키 매트릭스 디바이스 드라이버 • 키 매트릭스 디바이스 드라이버 프로그램 (14/key/key.c) 001 #include <linux/module.h> ------------- 010 #include <asm/io.h> 011 012 #define KEY_MAJOR 233 013 #define KEY_NAME "KEY" 014 #define SCAN_NUM 4 015 016 #define FPGA_KEY_OUT (0x11D00000) 017 #define FPGA_KEY_IN (0x11E00000) 018 019 #define KEYOUT (*(volatile unsigned char *)mem_key_out) 020 #define KEYIN (*(volatile unsigned char *)mem_key_in) 021 022 static void *mem_key_out, *mem_key_in; 023 static struct timer_list key_timer_str; 024 static unsigned char key_data; 025 static pid_t id; 026 static int n = 1; 027 028 int key_open (struct inode *inode, struct file *filp) 029 { 030 return 0; 031 } 032 033 int key_release (struct inode *inode, struct file *filp) 034 { 035 del_timer(&key_timer_str); 036 return 0; 037 } 038 수원과학대학 정보통신과

  48. [Review] 키 매트릭스 디바이스 드라이버 작성 039 ssize_t key_read (struct file *filp, char *buf, size_t count, loff_t *f_pos) 040 { 041 copy_to_user(buf, &key_data, sizeof(key_data)); // key_data를 buf로 복사 042 return 0; 043 } 044 045 void timer_function(unsigned long data) 046 { 047 unsigned int i, in, out; 048 049 for(i=0; i<4; i++) { 050 out = (1 << i); 051 KEYOUT = out; 052 in = ((KEYIN) & (0x0F)); 053 out =((out) << 4); 054 if (in != 0) { 055 key_data = ((out) | (in)); 056 kill_proc(id, SIGUSR1, 1); // 프로세스 id에게 signal 보냄 057 } 058 } 059 key_timer_str.expires = jiffies + (HZ/100); 060 add_timer(&key_timer_str); 061 } 062 063 ssize_t key_write (struct file *filp, const char *buf, size_t count, loff_t *f_pos) 064 { 065 get_user(id,(int*)buf); 066 init_timer(&key_timer_str); 067 key_timer_str.expires = jiffies + (HZ/100); 068 key_timer_str.data = (unsigned long)n; 069 key_timer_str.function = &timer_function; 070 add_timer(&key_timer_str); 071 return 0; 072 } 073 수원과학대학 정보통신과

  49. [Review] 키 매트릭스 디바이스 드라이버 작성 074 struct file_operations key_fops = { 075 .owner = THIS_MODULE, 076 .read = key_read, 077 .write = key_write, 078 .open = key_open, 079 .release = key_release, 080 }; 081 082 static int key_init(void) 083 { 084 int result; 085 unsigned long mem_addr_out, mem_addr_in, mem_len; 086 087 result = register_chrdev(KEY_MAJOR, KEY_NAME, &key_fops); …… 092 mem_addr_out = FPGA_KEY_OUT; 093 mem_addr_in = FPGA_KEY_IN; 094 mem_len = 0x1000; 095 mem_key_out = ioremap_nocache (mem_addr_out, mem_len); …… 100 mem_key_in = ioremap_nocache (mem_addr_in, mem_len); …… 105 printk("FPGA %s MAJOR %d\n", KEY_NAME, KEY_MAJOR); 106 return 0; 107 } 108 109 static void key_exit(void) 110 { 111 unregister_chrdev (KEY_MAJOR, KEY_NAME); 112 } 113 114 MODULE_LICENSE("GPL"); 115 module_init(key_init); 116 module_exit(key_exit); 수원과학대학 정보통신과

  50. [Review] 키 매트릭스 디바이스 드라이버 • 키 매트릭스 테스트 프로그램 (14/key/test_key.c) 01 #include <stdio.h> …… 08 #include <linux/delay.h> 09 10 static int dev; 11 static unsigned char vkey; 12 13 void keysignal(int sig) // 시그널 함수 keysignal() 생성 14 { 15 read(dev, &vkey, 1); // dev로부터 key 값을 변수 vkey로 읽어옴 16 printf("SIGNAL occur!!!!\n"); 17 } 18 19 int main(void) 20 { 21 pid_t id; 22 23 if ((dev = open("/dev/KEY", O_RDWR)) < 0) { 24 printf("return Value is %d\n",dev); 25 perror("open failed /dev/KEY"); 26 close(dev); 27 exit(-1); 28 } 29 (void) signal (SIGUSR1, keysignal); // 시그널 함수 keysignal() 등록 30 id = getpid(); // 프로세스 ID 얻기 31 write(dev, &id, 4); // 프로세스 ID를 커널에 알려줌 32 printf("press the push button!\n"); 33 // (void) signal (SIGUSR1, keysignal); 34 while(1) { 35 if(vkey != 0) { 36 printf("vkey is 0x%x\n", vkey); 37 vkey=0; 38 } 39 } 40 close(dev); 41 return 0; 42 } 수원과학대학 정보통신과

More Related