FND (Flexible Numeric Display)
FND 어드레스 디코딩 회로 설명 개요 7 세그먼트라고도 하고 숫자나 간단한 기호 표현에 많이 이용. 7-segment LED는 A-G 의 7개의 LED와 소수점 표시를 한 DP (Decimal Point)의 LED 1개로 구성된다. 각 LED는 표시되는 문자의 일부분을 구성하므로 각각을 세그먼트(segment : 부분, 구분)라 부른다.
FND 제어용 Device Driver FND 디바이스 물리 주소 영역 nCS4번 영역인 0x1000_0000 ~ 0x13FF_FFFF 사이에 FND 존재
FND 제어용 Device Driver IEB 보드 어드레스 디코딩 회로 CS4에 의해 어드레스 디코딩과 버퍼의 역할을 하는 FPGA 칩이 활성화
FND 제어용 Device Driver FND 어드레스 FND 물리주소(접근번지)는 0x1100_0000 ~ 0x1170_0000 영역에 8개가 할당 되어있는데 adress table을 구성해서 보면 최상위 6bit(A31~26)가 CS4 해당하고, 나머지 26bit중 최상위 6bit(A25~20)가 실질적인 어드레스 디코딩을 위해 사용되고 있다.
FND 제어용 Device Driver FND 어드레스 디코딩 회로 구성 data[31..0] D- 플리 플롭 FND의 물리주소 FND_CS0 ~ FND_CS7가 주어지면 CS4에 의해 FPGA가 선택되고 FPGA 내부에 있는 어드레드 디코딩 논리 회로에 의해 활성화 신호가 발생하고 해당 FND에 D-플리플롭에 상승엣지가 공급되어 FND에 연결된 데이타버스 하위 8비트가 FND에 전달되어 FND의 불을 켜게 된다.
FND 제어용 Device Driver FND 제어 방법(해당 비트에 데이터를 보냄) FND 1 : FND_CS = (0x01 << 0) 7 : FND_CS = (0x01 << 6) FND 6 : FND_CS = (0x01 << 5) 2 : FND_CS = (0x01 << 1) 5 : FND_CS = (0x01 << 4) 3 : FND_CS = (0x01 << 2) 8 : FND_CS = (0x01 << 7) 4 : FND_CS = (0x01 << 3)
FND 제어용 Device Driver 가상주소 맵핑 MMU를 사용하는 리눅스에서는 물리주소를 가지고 디바이스에 접근하면 페이지 폴트가 발생한다. 따라서 커널이 사용하는 가상주소를 할당받아 야 한다. ioremap 함수는 해당하는 디바이스를 위해 메모리 상에 일정영역을 커널이 관리하는 가상주소를 맵핑하여 준다. 따라서 FND에 해당하는 가상주소로 ioremap함수를 이용하여 FND를 위한 가상주소를 얻어와야 한다.
FND 제어용 Device Driver 소스 설명 Makefile fnd.c : lcd 디바이스 드라이버 소스이다. fnd.ko : lcd 디바이스 드라이버를 컴파일하면 생성되는 object 파일이다. fnd_test.c : lcd 디바이스 드라이버를 테스트하는 어플리케이션 소스이다.
FND 제어용 Device Driver FND 드라이버 소스 설명 (fnd.c) #define FPGA_FND_CS0 (0x11000000) //FND 물리주소 #define FPGA_FND_CS1 (0x11100000) #define FPGA_FND_CS2 (0x11200000) #define FPGA_FND_CS3 (0x11300000) #define FPGA_FND_CS4 (0x11400000) #define FPGA_FND_CS5 (0x11500000) #define FPGA_FND_CS6 (0x11600000) #define FPGA_FND_CS7 (0x11700000)
FND 제어용 Device Driver FND 드라이버 소스 설명 (fnd.c) mem_addr_fnd0 = FPGA_FND_CS0; …… mem_len = 0x1000; ….. static int fnd_init(void){ mem_fnd_cs0 = ioremap_nocache ( mem_addr_fnd0, mem_len); //가상주소 얻기 if( !mem_fnd_cs0) { printk("Error mapping fnd0 memery"); return -EBUSY; } ……. static void fnd_exit(void){ fnd_clear(); unregister_chrdev(FND_MAJOR, FND_NAME); iounmap(mem_fnd_cs0);
FND 제어용 Device Driver FND 응용프로그램 소스 설명 (fnd_test.c) unsigned char asc_to_fnd(int n){ unsigned char c; switch (n) { /* 여러가지 문자를 추가할수 있다 */ case 0: c = 0x3f; break; case 1: c = 0x06; break; case 2: c = 0x5b; break; case 3: c = 0x4f; break; case 4: c = 0x66; break; case 5: c = 0x6d; break; case 6: c = 0x7d; break; case 7: c = 0x07; break; ….. } return c;
FND 제어용 Device Driver FND 응용프로그램 소스 설명 (fnd_test.c) main(int ac, char *av[]){ int n, count, dev; unsigned char buf[MAXFND+1]; dev = open( fnd_dev, O_RDWR); if (dev < 0) { fprintf(stderr, "cannot open FND (%d)", dev); exit(2); } memset(buf, 0, sizeof(buf)); for (n = 0 ; n <= 9; n++) { for( count = 0 ; count < MAXFND; count++){ buf[count]= asc_to_fnd(n); write(dev, buf, MAXFND); usleep(500000);
FND 제어용 Device Driver Makefile 설명 CC := /opt/iwmmxt-1.0.0/bin/arm-linux-gcc KDIR := /PXA270/kernel/linux-2.6.11-h270-tku_v1.1 TEST_TARGET = fnd_test TEST_OBJS = fnd_test.o TEST_SRCS = fnd_test.c obj-m := fnd.o build: $(TEST_TARGET) make -C $(KDIR) SUBDIRS=`pwd` modules $(TEST_TARGET) : $(TEST_OBJS) $(CC) -o $@ $(TEST_OBJS) clean: rm -rf *.o *.ko *.mod.c rm -f $(TEST_TARGET)
FND 제어용 Device Driver # make clean # make 다운로드 : fnd.ko, fnd_test 실행방법 이미 타겟보드에 fnd의 드라이버가 올라가 있으므로 rmmod로 제거한 후 자신이 만든 fnd드라이버를 올리고 실행시켜보자. (host) # make clean # make 다운로드 : fnd.ko, fnd_test 실행 hybus~>#./fnd_test”
Key Matrix
Key matrix in XHYPER270TKU 4X4 Key matrix
Key 입력의 검출 4 inputs & 4 outputs Input 1 to keyout0, and 0 to others Make a loop to scan all keys find one with keyoutX and keyinX 1 All outputs are 0 Only 1 key will be 1
Key scan driver fpga_device/key/key.c void Print_Key(int out , int in){ switch(out){ case 1: if(in == 1) { dbg("key 4 is pressed\n"); key_data = 4;} else if(in == 2){ dbg("key 8 is pressed\n"); key_data = 8;} else if(in == 4){ dbg("key 12 is pressed\n"); key_data = 12;} else if(in == 8){ dbg("key 16 is pressed\n"); key_data = 16;} break; case 2: if(in == 1) { dbg("key 3 is pressed\n"); key_data = 3;} else if(in == 2){ dbg("key 7 is pressed\n"); key_data = 7;} else if(in == 4){ dbg("key 11 is pressed\n"); key_data = 11;} else if(in == 8){ dbg("key 15 is pressed\n"); key_data = 15;} case 3: if(in == 1) { dbg("key 2 is pressed\n"); key_data = 2;} else if(in == 2){ dbg("key 6 is pressed\n"); key_data = 6;} else if(in == 4){ dbg("key 10 is pressed\n"); key_data = 10;} else if(in == 8){ dbg("key 14 is pressed\n"); key_data = 14;} case 4: if(in == 1) { dbg("key 1 is pressed\n"); key_data = 1;} else if(in == 2){ dbg("key 5 is pressed\n"); key_data = 5;} else if(in == 4){ dbg("key 9 is pressed\n"); key_data = 9;} else if(in == 8){ dbg("key 13 is pressed\n"); key_data = 13;} break; } }
Key scan driver /* FPGA KEY 0x16400000 //FPGA_KEY_OUT# KEYOUT_D[0:3] : X_D[0:3] 0x16800000 //FPGA_KEY_IN# KEYIN_D[0:3] : X_D[0:3] */ #define FPGA_KEY_OUT (0x11D00000) #define FPGA_KEY_IN (0x11E00000) // (*((volatile unsigned char *)(mem_base))) #define KEYOUT (*((volatile unsigned char *)(mem_key_out))) #define KEYIN (*((volatile unsigned char *)(mem_key_in)))
Key scan driver void key_timer_function(unsigned long ptr) { int in, out; KEYOUT = ((1 << (ptr-1)) & (0x0f)); out = ptr; in = KEYIN; if(in != 0) { Print_Key(out, in); mdelay(200); } init_add_timer(); } void init_add_timer(void) { ++n; if( n > SCAN_NUM) n = 1; init_timer(&key_timer_str); // timer pointer key_timer_str.function =&key_timer_function ; key_timer_str.data = (unsigned long)n; key_timer_str.expires = jiffies + (HZ/100); add_timer(&key_timer_str);
Key scan driver static int key_init(void) { …… mem_addr_out = FPGA_KEY_OUT; mem_addr_in = FPGA_KEY_IN; mem_len = 0x1000; mem_key_out = ioremap_nocache (mem_addr_out, mem_len); if(!mem_key_out) { printk(" Error mapping key_out memory\n"); return -EBUSY; } mem_key_in = ioremap_nocache (mem_addr_out, mem_len); if(!mem_key_in) { printk(" Error mapping key_in memory\n"); ……….
Device 생성 확인: ls –l /dev/key Module 적재 ☞ lsmod↲ ☞ rmmod key↲ ☞ insmod key.ko↲
Key test ☞ ./ key-test↲
Character LCD 타겟 시스템은 HD44780 LCD 컨트롤러 모듈을 사용 16문자씩 2라인으로 표시. 폰트는 5*7도트. 제어를 위한 2개의 제어 비트(RS, R/W’)와 데이터 비트(D0~D7)에 [표 11-5]의 명령어로 설정한 후 Enable 클록을 On/Off함으로써 문자형 LCD로 데이터를 전송
문자형 LCD 디바이스 드라이버 작성 문자형 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 디바이스 드라이버 작성 …… 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 }
문자형 LCD 디바이스 드라이버 작성 문자 LCD 디바이스 드라이버 프로그램을 컴파일하기 위한 Makefile을 작성 디바이스 드라이버 모듈과 응용 프로그램을 컴파일 기존 디바이스 드라이버와 디바이스 파일을 테스트한 후 삭제 ① ② ③
문자형 LCD 디바이스 드라이버 작성 생성한 디바이스 드라이버와 응용 프로그램을 타겟 시스템으로 전송 디바이스 드라이버를 커널로 적재하고 필요한 디바이스 파일을 생성한 후 테스트 ① ② ③
Dot Matrix LED들을 매트릭스 형태로 배선시킨 구조 LED를 점등해 원하는 글씨나 그림을 나타내는 디바이스 5개의 열에는 주소 버스가 연결, 7개의 행에는 데이터 버스가 연결됨 0x1180_0000 0x1190_0000 0x11A0_0000 0x11B0_0000 0x11C0_0000
도트 매트릭스 디바이스 드라이버 프로그램 작성 도트 매트릭스 디바이스 드라이버 작성 도트 매트릭스 디바이스 드라이버 프로그램 작성 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
도트 매트릭스 디바이스 드라이버 작성 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);
도트 매트릭스 디바이스 드라이버 작성 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);
도트 매트릭스 디바이스 테스트 프로그램 작성 도트 매트릭스 디바이스 드라이버 작성 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 }
도트 매트릭스 디바이스 드라이버 작성 도트 디바이스 프로그램 컴파일하기 위한 Makefile을 작성 디바이스 드라이버 모듈과 응용 프로그램을 컴파일 기존 디바이스 드라이버를 테스트한 후 디바이스 드라이버와 디바이스 파일을 삭제 ① ② ③
도트 매트릭스 디바이스 드라이버 작성 생성한 디바이스 파일과 응용프로그램을 타겟 시스템으로 전송 디바이스 드라이버를 커널로 적재하고 새로운 디바이스 파일을 만든 후 응용프로그램으로 테스트 ① ② ③