1 / 45

디바이스드라이버 응용

디바이스드라이버 응용. 디바이스와 주소 디바이스 드라이버 구현 일반 LED 디바이스 드라이버 FND 디바이스 드라이버 키 매트릭스 디바이스 드라이버 문자형 LCD 디바이스 드라이버 도트 매트릭스 디바이스 드라이버. 디바이스의 주소 지정 방식 전용 입출력 방식 (dedicated I/O 혹은 isolated I/O) 메모리 사상 입출력 방식 (memory mapped I/O). PXA270 의 주소 공간 커널은 가상 주소를 사용해 컴퓨팅 자원에 접근

maine
Download Presentation

디바이스드라이버 응용

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. 디바이스드라이버 응용 • 디바이스와 주소 • 디바이스 드라이버 구현 일반 • LED 디바이스 드라이버 • FND 디바이스 드라이버 • 키 매트릭스 디바이스 드라이버 • 문자형 LCD 디바이스 드라이버 • 도트 매트릭스 디바이스 드라이버

  2. 디바이스의 주소 지정 방식 • 전용 입출력 방식(dedicated I/O 혹은 isolated I/O) • 메모리 사상 입출력 방식(memory mapped I/O)

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

  4. 타겟 시스템 디바이스들의 물리주소

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

  6. 실습 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 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 }

  7. 실습 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);

  8. 실습 LED 디바이스 드라이버 테스트 프로그램작성 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 }

  9. 실습 LED 디바이스 드라이버 작성 • LED 디바이스 프로그램 컴파일 위한 Makefile 작성(11/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

  10. ② ③ ④ 실습 LED 디바이스 드라이버 작성 • 디바이스 드라이버와 응용프로그램을 컴파일

  11. ② ③ ④ ⑤ ⑥ 실습 LED 디바이스 드라이버 작성 • 생성한 모듈과 응용 프로그램을 타겟 시스템으로 전송 • 타겟 시스템에서 디바이스 드라이버를 적재→응용 프로그램 테스트

  12. 0 1 2 3 4 5 6 7 8 9 7-세그먼트 실습 FND 디바이스 드라이버 작성

  13. 실습 FND 디바이스 드라이버 작성 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

  14. 실습 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

  15. 실습 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 함수 호출

  16. 실습 FND 디바이스 드라이버 작성 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 }

  17. ② ③ 실습 FND 디바이스 드라이버 작성 • FND 디바이스 드라이버 프로그램을 컴파일하기 위한 Makefile 작성 • 디바이스 드라이버와 응용프로그램을 컴파일 • 기존 디바이스 드라이버를 테스트한 후에 삭제

  18. ② ③ ④ 실습 FND 디바이스 드라이버 작성 • 새로 생성한 디바이스 드라이버와 응용 프로그램을 타겟 시스템으로 전송 • 응용프로그램을 실행한 후 임의의 키를 눌러 결과를 관찰

  19. 키 매트릭스디바이스 드라이버 작성

  20. 시그널 함수 • 하나 이상의 프로세스에 비동기적인 사건을 알리기 위해 사용 • 디바이스, 오류 상황, 인터럽트 키 사용 등의 경우 발생 • 사용자 프로그램에서 사용하는 시그널 함수의 형식 • 디바이스 드라이버에서 사용자 프로그램에 시그널을 보내는 함수의 형식

  21. 시그널 사용법

  22. 커널 타이머 • 타이머 인터럽트: 주기적으로 인터럽트를 발생시켜 반복해서 처리해야 할 작업에 사용 • 타이머 인터럽트는 HZ(아키텍처에 의존적인 값)로 설정 • 타이머 인터럽트가 발생하면 스케줄러에 의해 새로운 작업을 스케줄하고 jiffies(운영체제가 부팅된 시점부터 발생한 클록 회수) 값을 증가 • 커널 타이머를 사용해 특정 작업을 정해진 시간에 실행 • “jiffies ≧ timer->expires” 조건을 만족할 때 타이머에 등록한 함수를 실행 • expires는 jiffies와 타이머 간격을 합한 값

  23. 커널 타이머의 사용법

  24. 실습 키 매트릭스 디바이스 드라이버 작성 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

  25. 실습 키 매트릭스 디바이스 드라이버 작성 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

  26. 실습 키 매트릭스 디바이스 드라이버 작성 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);

  27. 실습 키 매트릭스 디바이스 드라이버 작성 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 }

  28. 실습 키 매트릭스 디바이스 드라이버 작성 • Makefile을 작성 • 디바이스 드라이버 모듈과 응용 프로그램을 컴파일 • 기존 디바이스 드라이버를 테스트 후 삭제

  29. ② ③ ④ ⑤ 실습 키 매트릭스 디바이스 드라이버 작성 • 생성한 디바이스 파일과 응용프로그램을 타겟 시스템으로 전송 • 디바이스 드라이버를 커널로 적재하고 새로운 디바이스 파일을 만든 후 응용프로그램으로 테스트

  30. 타겟 시스템은HD44780 LCD 컨트롤러 모듈을 사용 • 16문자씩 2라인으로 표시. 폰트는 5*7도트. • 제어를 위한 2개의 제어 비트(RS, R/W’)와 데이터 비트(D0~D7)에 [표 11-5]의 명령어로 설정한 후 Enable 클록을 On/Off함으로써 문자형 LCD로 데이터를 전송

  31. 실습 문자형 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 }

  32. 실습 문자형 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); …… 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);

  33. 실습 문자형 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 }

  34. ② ③ 실습 문자형 LCD 디바이스 드라이버 작성 • 문자 LCD 디바이스 드라이버 프로그램을 컴파일하기 위한 Makefile을 작성 • 디바이스 드라이버 모듈과 응용 프로그램을 컴파일 • 기존 디바이스 드라이버와 디바이스 파일을 테스트한 후 삭제

  35. ② ③ 실습 문자형 LCD 디바이스 드라이버 작성 • 생성한 디바이스 드라이버와 응용 프로그램을 타겟 시스템으로 전송 • 디바이스 드라이버를 커널로 적재하고 필요한 디바이스 파일을 생성한 후 테스트

  36. 0x1180_0000 0x1190_0000 0x11A0_0000 0x11B0_0000 0x11C0_0000 • LED들을 매트릭스 형태로 배선시킨 구조 • LED를 점등해 원하는 글씨나 그림을 나타내는 디바이스 • 5개의 열에는 주소 버스가 연결, 7개의 행에는 데이터 버스가 연결됨

  37. 실습 도트 매트릭스 디바이스 드라이버 작성 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

  38. 실습 도트 매트릭스 디바이스 드라이버 작성 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);

  39. 실습 도트 매트릭스 디바이스 드라이버 작성 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);

  40. 실습 도트 매트릭스 디바이스 드라이버 작성 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 }

  41. 실습 도트 매트릭스 디바이스 드라이버 작성 • 도트 디바이스 프로그램 컴파일하기 위한 Makefile을 작성 • 디바이스 드라이버 모듈과 응용 프로그램을 컴파일 • 기존 디바이스 드라이버를 테스트한 후 디바이스 드라이버와 디바이스 파일을 삭제 ① ② ③

  42. 실습 도트 매트릭스 디바이스 드라이버 작성 • 생성한 디바이스 파일과 응용프로그램을 타겟 시스템으로 전송 • 디바이스 드라이버를 커널로 적재하고 새로운 디바이스 파일을 만든 후 응용프로그램으로 테스트 ① ② ③

  43. ARM 계열의 CPU는 메모리 사상 입출력 방식을 취한다. • 각 장치들의 하드웨어 특성이 서로 다르므로 동작방식을 잘 이해하고 디바이스 드라이버를 작성해야 한다. • LED 디바이스 드라이버는 사용자 공간에서 데이터를 받아 LED가 위치한 가상 주소로 출력하도록 프로그램한다. • FND는 7-segment라고도 하며 응용 프로그램에서 글자 모양을 만들어 디바이스 드라이버를 통해 출력한다. • 키 매트릭스 디바이스 드라이버는 타이머를 사용해 폴링으로 눌려진 키를 식별하도록 작성한다. • 문자형 LCD 디바이스 드라이버는 해당 장치의 레지스터로 데이터를 전송하여 출력한다. • 도트 매트릭스 디바이스 드라이버는 구성된 도트의 각 열 별로 데이터를 출력하도록 프로그램한다.

More Related