420 likes | 612 Views
디바이스 드라이버 응용. 디바이스와 주소 디바이스 드라이버 구현 일반 LED 디바이스 드라이버 FND 디바이스 드라이버 키 매트릭스 디바이스 드라이버 문자형 LCD 디바이스 드라이버 도트 매트릭스 디바이스 드라이버. 디바이스의 주소 지정 방식 전용 입출력 방식 (dedicated I/O 혹은 isolated I/O) 메모리 사상 입출력 방식 (memory mapped I/O). PXA270 의 주소 공간 커널은 가상 주소를 사용해 컴퓨팅 자원에 접근
E N D
디바이스 드라이버 응용 • 디바이스와 주소 • 디바이스 드라이버 구현 일반 • LED 디바이스 드라이버 • FND 디바이스 드라이버 • 키 매트릭스 디바이스 드라이버 • 문자형 LCD 디바이스 드라이버 • 도트 매트릭스 디바이스 드라이버 한빛미디어(주)
디바이스의 주소 지정 방식 • 전용 입출력 방식(dedicated I/O 혹은 isolated I/O) • 메모리 사상 입출력 방식(memory mapped I/O)
PXA270의 주소 공간 • 커널은 가상 주소를 사용해 컴퓨팅 자원에 접근 • ARM 아키텍처의 디바이스를 접근하려면 물리 주소를 가상 메모리 공간으로 사상해야 작업 가능 • 디바이스의 접근은 시스템 모드에서 수행되므로 디바이스를 위한 가상 주소는 커널 공간 • 응용 프로그램은 커널 공간을 직접 제어할 수 없으며 커널도 사용자 공간을 직접 다룰 수 없음 • 따라서 디바이스 드라이버가 사용자와 커널 공간 사이에 데이터를 전송하려면 시스템호출과 같은 함수를 사용해야 함
디바이스 드라이버 제작 과정 • 디바이스 드라이버 소스 코드 작성 • 응용 프로그램 소스 코드 작성 • 디바이스 드라이버와 응용 프로그램의 컴파일 • 호스트 시스템에서 타겟 시스템으로 디바이스 드라이버와 응용 프로그램을 전송 • 디바이스 드라이버를 타겟 시스템 커널에 적재 • 타겟 시스템에서 응용 프로그램을 수행하여 테스트
실습 11-1 LED 디바이스 드라이버 작성 • LED 디바이스 드라이버 프로그램 작성(11/led/led.c) 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 }
실습 11-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);
실습 11-1 LED 디바이스 드라이버 작성 • LED 디바이스 드라이버 테스트 프로그램 작성(11/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 }
실습 11-1 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
① ② ③ ④ ① ② ③ ④ ⑤ ⑥ 실습 11-1 LED 디바이스 드라이버 작성 • 디바이스 드라이버와 응용프로그램을 컴파일 • 생성한 모듈과 응용 프로그램을 타겟 시스템으로 전송 • 타겟 시스템에서 디바이스 드라이버를 적재→응용 프로그램 테스트
0 1 2 3 4 5 6 7 8 9 7-세그먼트
실습 11-2 FND 디바이스 드라이버 작성 • FND 디바이스 드라이버 프로그램 작성(11/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
실습 11-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
실습 11-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 함수 호출
실습 11-2 FND 디바이스 드라이버 작성 • FND 디바이스 테스트 프로그램 작성(11/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 }
① ② ③ 실습 11-2 FND 디바이스 드라이버 작성 • FND 디바이스 드라이버 프로그램을 컴파일하기 위한 Makefile 작성 • 디바이스 드라이버와 응용프로그램을 컴파일 • 기존 디바이스 드라이버를 테스트한 후에 삭제
① ② ③ ④ 실습 11-3 키 매트릭스 디바이스 드라이버 작성 • 새로 생성한 디바이스 드라이버와 응용 프로그램을 타겟 시스템으로 전송 • 응용프로그램을 실행한 후 임의의 키를 눌러 결과를 관찰
회로도와 같이 KEYIN과 KEYOUT에 각각 4개의 라인만 사용. • KEYOUT0~KEYOUT의 값을 순서대로 1로 설정하는 것을 반복 • 이 때 어떤 키가 눌려지면 대응하는 KEYIN의 값이 1로 검출됨 • 예를 들어 KB1을 눌렀을 때, KEYOUT3의 값이 1로 설정되면 KEYIN0의 값이 1로 검출됨. 따라서 4개의 KEYOUT과 4개의 KEYIN에 대한 값을 조합해 눌려진 키를 식별할 수 있음.
실습 11-3 키 매트릭스 디바이스 드라이버 작성 • 키 매트릭스 디바이스 드라이버 프로그램 작성(11/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
실습 11-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
실습 11-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);
실습 11-3 키 매트릭스 디바이스 드라이버 작성 • 키 매트릭스 테스트 프로그램 작성(11/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 }
실습 11-3 키 매트릭스 디바이스 드라이버 작성 • Makefile을 작성 • 디바이스 드라이버 모듈과 응용 프로그램을 컴파일 • 기존 디바이스 드라이버를 테스트 후 삭제
① ② ③ ④ ⑤ 실습 11-3 키 매트릭스 디바이스 드라이버 작성 • 생성한 디바이스 파일과 응용프로그램을 타겟 시스템으로 전송 • 디바이스 드라이버를 커널로 적재하고 새로운 디바이스 파일을 만든 후 응용프로그램으로 테스트
타겟 시스템은HD44780 LCD 컨트롤러 모듈을 사용 • 16문자씩 2라인으로 표시. 폰트는 5*7도트. • 제어를 위한 2개의 제어 비트(RS, R/W’)와 데이터 비트(D0~D7)에 [표 11-5]의 명령어로 설정한 후 Enable 클록을 On/Off함으로써 문자형 LCD로 데이터를 전송
실습 11-4 문자형 LCD 디바이스 드라이버 작성 • 문자형 LCD 디바이스 드라이버 프로그램 작성(11/clcd/clcd.c) 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 }
실습 11-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);
실습 11-4 문자형 LCD 디바이스 드라이버 작성 • 디바이스 드라이버 테스트 프로그램 작성(11/clcd/test_clcd.c) 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 }
① ② ③ 실습 11-4 문자형 LCD 디바이스 드라이버 작성 • 문자 LCD 디바이스 드라이버 프로그램을 컴파일하기 위한 Makefile을 작성 • 디바이스 드라이버 모듈과 응용 프로그램을 컴파일 • 기존 디바이스 드라이버와 디바이스 파일을 테스트한 후 삭제
① ② ③ 실습 11-4 문자형 LCD 디바이스 드라이버 작성 • 생성한 디바이스 드라이버와 응용 프로그램을 타겟 시스템으로 전송 • 디바이스 드라이버를 커널로 적재하고 필요한 디바이스 파일을 생성한 후 테스트
0x1180_0000 0x1190_0000 0x11A0_0000 0x11B0_0000 0x11C0_0000 • LED들을 매트릭스 형태로 배선시킨 구조 • LED를 점등해 원하는 글씨나 그림을 나타내는 디바이스 • 5개의 열에는 주소 버스가 연결, 7개의 행에는 데이터 버스가 연결됨
실습 11-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
실습 11-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);
실습 11-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);
실습 11-5 도트 매트릭스 디바이스 드라이버 작성 • 도트 매트릭스 디바이스 테스트 프로그램 작성(11/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 }
실습 11-5 도트 매트릭스 디바이스 드라이버 작성 • 도트 디바이스 프로그램 컴파일하기 위한 Makefile을 작성 • 디바이스 드라이버 모듈과 응용 프로그램을 컴파일 • 기존 디바이스 드라이버를 테스트한 후 디바이스 드라이버와 디바이스 파일을 삭제 ① ② ③
실습 11-5 도트 매트릭스 디바이스 드라이버 작성 • 생성한 디바이스 파일과 응용프로그램을 타겟 시스템으로 전송 • 디바이스 드라이버를 커널로 적재하고 새로운 디바이스 파일을 만든 후 응용프로그램으로 테스트 ① ② ③
ARM 계열의 CPU는 메모리 사상 입출력 방식을 취한다. • 각 장치들의 하드웨어 특성이 서로 다르므로 동작방식을 잘 이해하고 디바이스 드라이버를 작성해야 한다. • LED 디바이스 드라이버는 사용자 공간에서 데이터를 받아 LED가 위치한 가상 주소로 출력하도록 프로그램한다. • FND는 7-segment라고도 하며 응용 프로그램에서 글자 모양을 만들어 디바이스 드라이버를 통해 출력한다. • 키 매트릭스 디바이스 드라이버는 타이머를 사용해 폴링으로 눌려진 키를 식별하도록 작성한다. • 문자형 LCD 디바이스 드라이버는 해당 장치의 레지스터로 데이터를 전송하여 출력한다. • 도트 매트릭스 디바이스 드라이버는 구성된 도트의 각 열 별로 데이터를 출력하도록 프로그램한다.