580 likes | 902 Vues
14 주차 . 디바이스 드라이버의 응용. 수원과학대학교 정보통신과. 14.1 디바이스와 주소. 디바이스의 주소 지정 방식 전용 입출력 방식 (dedicated I/O 혹은 isolated I/O) 메모리 사상 입출력 방식 (memory mapped I/O). PXA270 디바이스의 주소공간. 커널이 가상 주소를 사용해 컴퓨팅 자원에 접근하므로 ARM 아키텍처의 디바이스에 접근하려면 물리 주소를 가상 메모리 공간으로 사상해야 작업 가능
E N D
14주차. 디바이스 드라이버의 응용 수원과학대학교 정보통신과
14.1 디바이스와 주소 • 디바이스의 주소 지정 방식 • 전용 입출력 방식(dedicated I/O 혹은 isolated I/O) • 메모리 사상 입출력 방식(memory mapped I/O) 수원과학대학 정보통신과
PXA270 디바이스의 주소공간 • 커널이 가상 주소를 사용해 컴퓨팅 자원에 접근하므로 ARM 아키텍처의 디바이스에 접근하려면 물리 주소를 가상 메모리 공간으로 사상해야 작업 가능 • 디바이스의 접근은 시스템 모드에서 수행되므로 디바이스를 위한 가상 주소는 커널 공간임 • 응용 프로그램은 커널 공간을 직접 제어할 수 없으며 커널도 사용자 공간을 직접 다룰 수 없음 • 따라서 디바이스 드라이버가 사용자와 커널 공간 사이에 데이터를 전송하려면 시스템호출과 같은 함수를 사용해야 함 수원과학대학 정보통신과
타겟 시스템의 디바이스 구성 수원과학대학 정보통신과
타겟 시스템 디바이스들의 물리주소 수원과학대학 정보통신과
디바이스 드라이버 제작 과정 • 디바이스 드라이버 소스 코드 작성 • 응용 프로그램 소스 코드 작성 • 디바이스 드라이버와 응용 프로그램의 컴파일 • 호스트 시스템에서 타겟 시스템으로 디바이스 드라이버와 응용 프로그램을 전송 • 디바이스 드라이버를 타겟 시스템 커널에 적재 • 타겟 시스템에서 응용 프로그램을 수행하여 테스트 수원과학대학 정보통신과
LED 디바이스 드라이버 [1] LED 포트를 GND로 만들면 불이 켜지고 3V를 가하면 불이 꺼진다. 수원과학대학 정보통신과
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을 기록하면 꺼진다. 수원과학대학 정보통신과
0 1 2 3 4 5 6 7 8 9 7-세그먼트 FND [1] 숫자별 값 b7 b6 b5 b4 b3 b2 b1 b0 수원과학대학 정보통신과
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 수원과학대학 정보통신과
키 매트릭스 KEYOUT 물리주소 = 0x11D000000 • KEY 검출 방법 • KEYOUT0에 1값을 출력하고 KEYIN0~KEYIN3을 차례대로 읽음 • 이 때 어떤 키가 눌려지면 대응하는 KEYIN의 값이 1로 검출되고 그렇지 않으면 0값이 검출됨 • 위 과정을 KEYOUT1, 2, 3에 대해 반복 • 예를 들어 KB1을 눌렀을 경우, KEYOUT3에 1을 출력했을 때 KEYIN을 읽으면 KEYIN0의 값이 1로 검출됨. KEYIN 물리주소 = 0x11E000000 수원과학대학 정보통신과
문자 LCD [1] • 16문자씩 2라인으로 표시. 폰트는 5*7도트. • LCD 컨트롤러에는 DR(data register)와 IR(instruction register)가 있음 • LCD 물리주소 • LCD 데이터: 0x12300000 • LCD 제어명령: 0x12380000 수원과학대학 정보통신과
문자 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 주소 사용 수원과학대학 정보통신과
0x1180_0000 0x1190_0000 0x11A0_0000 0x11B0_0000 0x11C0_0000 Dot Matrix [1] • LED들을 매트릭스 형태로 배선시킨 구조 • LED를 점등해 원하는 글씨나 그림을 나타내는 디바이스 • 5개의 열에는 주소 버스가 연결, 7개의 행에는 데이터 버스가 연결됨 데이터 버스 연결 주소 버스 연결 수원과학대학 정보통신과
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 수원과학대학 정보통신과
실습 프로그램 다운 받기 • 리눅스 기본 웹브라우저인 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 (압축풀기) 수원과학대학 정보통신과
타겟 보드의 파일 시스템 초기화 • 왜? 타켓보드에서 타인이 앞서 실습한 결과를 없애기 위해 • 호스트에서 • cp /embed/hybus/images/rootfs.img /tftpboot • 타겟에서 • hybus> tftp rootfs.img root • hybus> flash root 수원과학대학 정보통신과
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 } 수원과학대학 정보통신과
실습 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); 수원과학대학 정보통신과
실습 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 } 수원과학대학 정보통신과
실습 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 수원과학대학 정보통신과
① ② ③ ④ ① ② ③ ④ ⑤ ⑥ 실습 14-1 LED 디바이스 드라이버 작성 • 디바이스 드라이버와 응용프로그램을 컴파일 • 생성한 모듈(led.ko)과 응용 프로그램(test_led)을 타겟 시스템으로 전송 • 타겟 시스템에서 디바이스 드라이버를 적재→응용 프로그램 테스트 수원과학대학 정보통신과
실습 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 수원과학대학 정보통신과
실습 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 수원과학대학 정보통신과
실습 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 함수 호출 수원과학대학 정보통신과
실습 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 } 수원과학대학 정보통신과
① ② ③ 실습 14-2 FND 디바이스 드라이버 작성 • FND 디바이스 드라이버 프로그램을 컴파일하기 위한 Makefile 작성 • 디바이스 드라이버와 응용프로그램을 컴파일 • make • arm-linux-gcc –o test_fnd test_fnd.c • 기존 디바이스 드라이버를 테스트한 후에 삭제 수원과학대학 정보통신과
① ② ③ ④ 실습 14-2 FND 디바이스 드라이버 작성 • 새로 생성한 디바이스 드라이버(fnd.ko)와 응용 프로그램(test_fnd)을 타겟 시스템으로 전송 • 응용프로그램을 실행한 후 임의의 숫자들을 입력해 결과를 관찰 수원과학대학 정보통신과
실습 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 수원과학대학 정보통신과
실습 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 수원과학대학 정보통신과
실습 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); 수원과학대학 정보통신과
실습 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 } 수원과학대학 정보통신과
실습 14-3 키 매트릭스 디바이스 드라이버 작성 • Makefile을 작성 • 디바이스 드라이버 모듈과 응용 프로그램을 컴파일 • make • arm-linux-gcc –o test_key test_key.c • 기존 디바이스 드라이버를 테스트 수원과학대학 정보통신과
① ② ③ ④ ⑤ 실습 11-3 키 매트릭스 디바이스 드라이버 작성 • 생성한 디바이스 파일(key.ko)과 응용프로그램(test_key)을 타겟 시스템으로 전송 • 기존 디바이스 드라이버를 삭제하고 새 디바이스 드라이버를 커널로 적재하고 새로운 디바이스 파일을 만든 후 응용프로그램으로 테스트 수원과학대학 정보통신과
실습 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) 수원과학대학 정보통신과
실습 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); 수원과학대학 정보통신과
실습 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) 수원과학대학 정보통신과
① ② ③ 실습 14-4 문자형 LCD 디바이스 드라이버 작성 • 문자 LCD 디바이스 드라이버 프로그램을 컴파일하기 위한 Makefile을 작성 • 디바이스 드라이버 모듈과 응용 프로그램을 컴파일 • make • arm-linux-gcc –o test_clcd test_clcd.c • 기존 디바이스 드라이버와 디바이스 파일을 테스트한 후 삭제 수원과학대학 정보통신과
① ② ③ 실습 14-4 문자형 LCD 디바이스 드라이버 작성 • 생성한 디바이스 드라이버(clcd.ko)와 응용 프로그램(test_clcd)을 타겟 시스템으로 전송 • 디바이스 드라이버를 커널로 적재하고 필요한 디바이스 파일을 생성한 후 테스트 수원과학대학 정보통신과
실습 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 수원과학대학 정보통신과
실습 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); 수원과학대학 정보통신과
실습 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); 수원과학대학 정보통신과
실습 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 } 수원과학대학 정보통신과
실습 14-5 도트 매트릭스 디바이스 드라이버 작성 • 도트 디바이스 프로그램 컴파일하기 위한 Makefile을 작성 • 디바이스 드라이버 모듈과 응용 프로그램을 컴파일 • make • arm-linux-gcc –o test_dot test_dot.c • 기존 디바이스 드라이버를 테스트한 후 디바이스 드라이버와 디바이스 파일을 삭제 ① ② ③ 수원과학대학 정보통신과
실습 14-5 도트 매트릭스 디바이스 드라이버 작성 • 생성한 디바이스 파일(dot.ko)과 응용프로그램(test_dot)을 타겟 시스템으로 전송 • 디바이스 드라이버를 커널로 적재하고 새로운 디바이스 파일을 만든 후 응용프로그램으로 테스트 ① ② ③ 수원과학대학 정보통신과
실습문제 1번 Key Driver 개선 • 문제점: 교재의 키 드라이버는 키를 한번 눌러도 여러번 누른 것으로 인식됨 • 개선: 키를 계속 누르고 있어도 한 번 누른 것으로 인식시킨다. 즉, 한번 눌렀다가 뗀 후 다시 눌러야 새로운 키로 인식시킨다. 수원과학대학 정보통신과
[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 수원과학대학 정보통신과
[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 수원과학대학 정보통신과
[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); 수원과학대학 정보통신과
[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 } 수원과학대학 정보통신과