FND 디바이스 드라이버 Lecture #13
목 차 7-Segment FND 구동 원리 디바이스 드라이버 프로그램 시 필요한 함수 FND 디바이스 드라이버 fnd-driver.c FND 응용 프로그램 fnd-app.c FND 디바이스 드라이버 시험
발광다이오드(LED) LED(Light Emitting Diode) 화합물 반도체의 PN접합 다이오드로 양단에 전압의 차를 가하면 빛을 방출하는 발광소자 그림 (A)와 같이 2개의 다리가 나와있는데 긴 쪽이 anode(+)이며 짧은 쪽이 cathode(-)이다 약 2.5V정도의 전압차가 2개의 다리 양단에 걸리면 빛을 방출하는 데, 보통 디지털소자의 출력이 5V이므로 그림 (B)와 같이 저항을 직렬로 연결하여 다이오드를 보호한다 그림 (A) 그림 (B)
7-Segment LED (1) 7-Segment LED FND 라고도 불리는데, 숫자나 문자를 표시하는데 사용되는 7개의 발광다이오드(LED)의 모임 공통 애노드(Common Anode) 형 : 다이오드의 애노드를 공통 단자로 사용한다 애노드 단자에 5V를 주고 캐소드의 각 단자 a~g 까지 0V를 주면 다이오 드에 전류가 흐르게 되어 발광한다 다이오드의 파손 방지를 위해 저항을 연결 한다 Common Anode 형
7-Segment LED (2) 7-Segment LED 공통 캐소드(Common Cathode) 형 : 다이오드의 캐소드를 공통 단자로 사용한다 캐소드를 접지 시키고, 다이오드의 애노드 단자에 5V를 주면 전류가 흐 른다 다이오드의 파손 방지를 위해 저항을 연결 한다 Common Cathode 형
7-Segment LED Array (1) Common Cathode 형 7-Segment LED 4 ARRAY 공통단자가 캐소드형으로 com0, com1, com2, com3로 4개 있으며, 애노드 단자 a,b,c,d,e,f,g,dp는 공통으로 사용한다 LED를 제어하기 위한 전체 핀의 개수를 줄일 수 있는 장점이 있으 나 컨트롤은 조금 복잡해진다
7-Segment LED Array (2) Common Cathode 형 7-Segment LED 4 ARRAY Com0=0, Com1=Com2=Com3=1인 경우, 입력 a,b,c,d,e,f,g중의 어 느 하나가 1이면 가장 왼쪽에 해당되는 Segment LED가 발광한다
7-Segment LED Array (3) PXA255-FPGA Board – 7-Segment LED 6 Array
7-Segment LED Array (4) FND 포트의 물리 주소 FND digit 및 segment 위치와 데이터 bit 0xC0000002 FND digit 및 segment 위치와 데이터 bit digit 부분(dig1~dig6)에는 0을, segment(a~dp) 부분에는 1을 write 하면 주어진 digit의 segment에 불이 켜짐 e.g) FND의 digit 3에 숫자 3(=segment abcdg)을 출력하려면 0xC0000002 번지에 0x4FFB을 출력하면 됨 FND dp g f e d c b a x dig6 dig5 dig4 dig3 dig2 dig1 bit 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
7-Segment LED Array (5) FND를 이용한 데이터 표현 예: Common Cathod 단자 Anode 단자
PXA255-FPGA – FND 회로 구성 (1)
PXA255-FPGA – FND 회로 구성 (2)
PXA255-FPGA – FND 회로 구성 (3)
PXA255-FPGA – FND 회로 구성 (4)
디바이스 드라이버 프로그램 시 필요한 함수 get_user(void *x, const void *addr) 사용자 영역의 *addr의 값을 커널 영역인 x로 sizeof(addr) 만큼 복사 put_user(void *x, const void *addr) 커널 영역의 *x의 값을 사용자 영역인 addr로 sizeof(addr) 만큼 복사 copy_to_user(void *to, void *from, unsigned long size) 커널 영역의 from에서 size 만큼을 사용자 영역의 to로 복사 copy_from_user(void *to, void *from, unsigned long size) 사용자 영역의 from에서 size 만큼을 커널 영역의 to로 복사 I/O로 부터 값을 읽는 함수 __u8 inb(unsigned int port) __u16 inw(unsigned int port) __u32 inl(unsigned int port) I/O에 값을 쓰는 함수 void outb(__u8 data, unsigned int port) void outw(__u16 data, unsigned int port) void outl(__u32 data, unsigned int port)
FND Device Driver – 매크로/전역 변수 (fnd_driver.c) #include <asm-arm/hardware.h> #include <asm-arm/uaccess.h> #include <asm-arm/io.h> #include <asm-arm/ioctl.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/errno.h> #include <linux/types.h> #include <linux/ioport.h> #include <linux/delay.h> #include <linux/sched.h> #include <linux/init.h> #include <linux/version.h> #define IOM_FND_MAJOR 260 // ioboard fnd device major number #define IOM_FND_NAME "FNDS“ // ioboard fnd device name #define IOM_FND_ADDRESS 0x0C000002 // pysical address
FND Device Driver – 매크로/전역 변수 (fnd_driver.c) int iom_fnd_open(struct inode *, struct file *); int iom_fnd_release(struct inode *, struct file *); ssize_t iom_fnd_write(struct file *, const char *, size_t, loff_t *); unsigned char Getsegcode(int x); //Global variable static int fnd_usage = 0; static unsigned short *iom_fnd_addr; static struct file_operations iom_fnd_fops = { open: iom_fnd_open, write: iom_fnd_write, release: iom_fnd_release, };
FND Device Driver – open/release (fnd_driver.c) int iom_fnd_open(struct inode *minode, struct file *mfile) { if(fnd_usage != 0) return -EBUSY; fnd_usage = 1; return 0; } int iom_fnd_release(struct inode *minode, struct file *mfile) fnd_usage = 0;
FND Device Driver – Getsegcode (fnd_driver.c) unsigned char Getsegcode(int x) { char code; switch (x) { case 0x0 : code = 0x3f; break; case 0x1 : code = 0x06; break; case 0x2 : code = 0x5b; break; case 0x3 : code = 0x4f; break; case 0x4 : code = 0x66; break; case 0x5 : code = 0x6d; break; case 0x6 : code = 0x7d; break; case 0x7 : code = 0x07; break; case 0x8 : code = 0x7f; break; case 0x9 : code = 0x6f; break; case 0xA : code = 0x77; break; case 0xB : code = 0x7c; break; case 0xC : code = 0x39; break; case 0xD : code = 0x5e; break; case 0xE : code = 0x79; break; case 0xF : code = 0x71; break; default : code = 0; break; } return code;
FND Device Driver – write (fnd_driver.c) ssize_t iom_fnd_write(struct file *inode, const char *gdata, size_t length, loff_t *off_what) { const char *tmp = gdata; unsigned char value,cathode = 0xff; int i; unsigned char fnd_buff[4]; memset( fnd_buff, '0', sizeof(fnd_buff) ); if (copy_from_user(fnd_buff, tmp, length))// 3byte receive from application return -EFAULT; for(i = 0; i < 6; i++){ if(i %2) value = Getsegcode((fnd_buff[i/2]>>4) & 0xf); else value = Getsegcode(fnd_buff[i/2] & 0xf); outw ( (unsigned short)((value << 8)|(cathode & ~(0x1 << (5-i)))), iom_fnd_addr ); } return length;
FND Device Driver – init/cleanup (fnd_driver.c) int __init iom_fnd_init(void) { int result; result = register_chrdev(IOM_FND_MAJOR, IOM_FND_NAME, &iom_fnd_fops); if(result < 0) { printk(KERN_WARNING"Can't get any major\n"); return result; } iom_fnd_addr = ioremap(IOM_FND_ADDRESS,0x02); printk("init module, %s major number : %d\n",IOM_FND_NAME, IOM_FND_MAJOR); return 0; void __exit iom_fnd_exit(void) // fnd clear outw(0x00FE, iom_fnd_addr); outw(0x00FD, iom_fnd_addr); outw(0x00FB, iom_fnd_addr); outw(0x00F7, iom_fnd_addr); outw(0x00EF, iom_fnd_addr); outw(0x00DF, iom_fnd_addr); iounmap(iom_fnd_addr); if(unregister_chrdev(IOM_FND_MAJOR, IOM_FND_NAME)) printk(KERN_WARNING"%s DRIVER CLEANUP FALLED\n", IOM_FND_NAME);
FND Device Driver – init/cleanup (fnd_driver.c) MODULE_LICENSE("GPL"); module_init(iom_fnd_init); module_exit(iom_fnd_exit);
FND Device Driver – Test Application Program (test_fnd.c) #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <fcntl.h> int main(int argc, char **argv) { int dev; unsigned long buff; if(argc <= 1) { printf("please input the parameter!\n"); printf("ex)./test_fnd 0x123456\n"); printf("ex)./test_fnd 123456\n"); return -1; } dev = open("/dev/FNDS", O_WRONLY); if (dev != -1){ if(argv[1][0] == '0' && (argv[1][1] =='x'||argv[1][1] == 'X')) buff = (unsigned long)strtol(&argv[1][2], NULL,16); else buff = (unsigned long)strtol(&argv[1][0], NULL,16); write(dev,&buff,3); close(dev); else{ printf( "Device Open ERROR!\n"); exit(-1); return(0);
FND Device Driver – Makefile #Makefile for a basic kernel module obj-m := fnd_driver.o KDIR :=/root/pxa255-pro3/kernel/linux-2.6.21 PWD :=$(shell pwd) all: driver app driver: $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules app: arm-linux-gcc -o test_fnd test_fnd.c clean: rm -rf *.ko rm -rf *.mod.* rm -rf *.o rm -rf test_fnd rm -rf Module.symvers
FND Device Driver – Testing 타겟보드를 부팅하고 드라이버 모듈과 테스트 프로그램을 nfs 마 운트 디렉토리로 복사한 후에 아래와 같이 진행한다. # insmod ./fnd_driver.ko init module, FNDS major number : 260 # mknod /dev/FNDS c 260 0 # ./test_fnd 123456