CLCD + 키메트릭스 조합
1.Make

			
2.comfile_led

			
3.
		run

			
4.
		소스코드
Makefile
| 
 KDIR    := /home/hwanseung/270/kernel/linux-2.6.11-h270-tku_v1.1-app 
 obj-m    := clcd_key.o 
 build:     make -C $(KDIR) SUBDIRS=$(PWD) modules 
 
 clean:     rm -rf *.o *.ko *.mod.c  | 
Clcd_key.c
| 
 #include <linux/module.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/init.h> #include <linux/fs.h> 
 #include <linux/delay.h> #include <linux/poll.h> 
 #include <asm/uaccess.h> 
 #include <asm/hardware.h> #include <asm/io.h> 
 #define CLCD_MAJOR           238 #define CLCD_NAME           "CLCD" 
 #define FPGA_CLCD_WR_ADD    (0x12300000) #define FPGA_CLCD_RS_ADD    (0x12380000) #define CLCD_CMD_ADDR     (*((volatile unsigned char *)(mem_base_wr))) #define CLCD_DATA_ADDR     (*((volatile unsigned char *)(mem_base_rs))) 
 static void *mem_base_wr, *mem_base_rs; static unsigned long mem_addr_wr, mem_addr_rs, mem_len; 
 #define KEY_MAJOR           233 #define KEY_NAME            "KEY" #define SCAN_NUM           4 
 #define FPGA_KEY_OUT            (0x11D00000) #define FPGA_KEY_IN            (0x11E00000) 
 #define KEYOUT        (*(volatile unsigned char *)mem_key_out) #define KEYIN       (*(volatile unsigned char *)mem_key_in) 
 static void *mem_key_out, *mem_key_in; 
 //전역변수 선언 static struct timer_list key_timer_str; static unsigned char key_data; static pid_t id; static int n = 1; 
 static void lcd_init(void)         // LCD 초기화 {   CLCD_CMD_ADDR = 0x38;    // 8-비트, 2 라인, 5x8    iounmap(mem_base_wr);   mdelay(300);   CLCD_CMD_ADDR = 0x0e;    // LCD 디스플레이 ON, 커서 ON   mdelay(100);   CLCD_CMD_ADDR = 0x02;    // 커서를 홈으로 이동   mdelay(100);   CLCD_CMD_ADDR = 0x01;    // 화면 정리   mdelay(100); } 
 static void string_out(char *str) {   char *s;   int i=0; 
   printk("%s\n", str);   lcd_init();   for (s=str; *s; s++) {     CLCD_DATA_ADDR = *s;     if(i == 15) {                  // 출력할 문자가 0 ~ 15열을 초과하므로       udelay(100);               // 2번 행에 문자를 출력       CLCD_CMD_ADDR = 0xC0;    // D7=1, D6=1, D5 ~ D0는 모두 1     }     udelay(100);     i++;   } } 
 int clcd_open (struct inode *inode, struct file *filp) {   return 0;                   // success } 
 int clcd_release (struct inode *inode, struct file *filp) {   return 0; } 
 ssize_t clcd_write (struct file *filp, const char *buf, size_t count, loff_t *f_pos) {   char data[32]; 
   memset(data, 0 , 32);   copy_from_user(data, buf, count);   string_out(data);   return 0; } 
 struct file_operations clcd_fops = {   .owner     = THIS_MODULE,   .write    = clcd_write,   .open        = clcd_open,   .release    = clcd_release, }; 
 
 int key_open (struct inode *inode, struct file *filp) {   return 0; } 
 int key_release (struct inode *inode, struct file *filp) {   del_timer(&key_timer_str);                // 타이머 리스트에서 타이머 제거   return 0; } 
 ssize_t key_read (struct file *filp, char *buf, size_t count, loff_t *f_pos) {   copy_to_user(buf, &key_data, sizeof(key_data));  // 커널 영역에서 사용자 영역으로   return 0;                                        // 복사 } 
 void timer_function(unsigned long data) {   unsigned int i, in, out; 
   for(i=0;i<4;i++){     out = (1 << i);     KEYOUT = out;     in = ((KEYIN) & (0x0F));     out =((out) << 4);     if (in != 0) {       key_data = ((out) | (in));       kill_proc(id, SIGUSR1, 1);     // 커널에서 시그널을 응용프로그램에게 전달     }   }    /* if (n > SCAN_NUM)       n = 1;     else     n++; */   key_timer_str.expires = jiffies + (HZ/100);  // 타이머의 만기 기간 설정   add_timer(&key_timer_str);                 // 타이머를 타이머 리스트에 추가 } 
 ssize_t key_write (struct file *filp, const char *buf, size_t count, loff_t *f_pos) {   get_user(id,(int*)buf);                          // user id 값 저장   init_timer(&key_timer_str);                     // 타이머 초기화   key_timer_str.expires = jiffies + (HZ/100);   key_timer_str.data = (unsigned long)n;   key_timer_str.function = &timer_function;   add_timer(&key_timer_str);                    // 타이머를 타이머 리스트에 추가   return 0; } 
 struct file_operations key_fops = {   .owner    = THIS_MODULE,   .read        = key_read,   .write    = key_write,   .open        = key_open,   .release    = key_release, }; 
 
 static int clcd_key_init(void) {   int result; 
   result = register_chrdev(CLCD_MAJOR, CLCD_NAME, &clcd_fops);   if (result < 0) {         printk(KERN_WARNING " can't get major \n");         return result;   }   mem_addr_wr =  FPGA_CLCD_WR_ADD;   mem_addr_rs =  FPGA_CLCD_RS_ADD;   mem_len  =  0x1000; 
   mem_base_wr = ioremap_nocache ( mem_addr_wr, mem_len);   if( !mem_base_wr) {         printk("Error mapping clcd_wr memery");         return -EBUSY;   }        mem_base_rs = ioremap_nocache ( mem_addr_rs, mem_len);   if( !mem_base_rs) {         printk("Error mapping clcd_rs memery");         return -EBUSY;   }   printk("FPGA %s MAJOR %d\n",CLCD_NAME, result);   return 0; 
   unsigned long mem_addr_out, mem_addr_in, mem_len; 
   result = register_chrdev(KEY_MAJOR, KEY_NAME, &key_fops);   if (result < 0) {     printk(KERN_WARNING"Failed to register the driver. \n");     return result;   }   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_in, mem_len);     if(!mem_key_in) {         printk(" Error mapping key_in memory\n");         return -EBUSY;     }   printk("FPGA %s MAJOR %d\n", KEY_NAME, KEY_MAJOR);   return 0; } 
 static void clcd_key_exit(void) {   unregister_chrdev(CLCD_MAJOR, CLCD_NAME);   iounmap(mem_base_wr);   iounmap(mem_base_rs); 
   unregister_chrdev (KEY_MAJOR, KEY_NAME); 
 
 } 
 MODULE_LICENSE("GPL"); module_init(clcd_key_init); module_exit(clcd_key_exit); 
  | 
Test_clcd_key.c
| 
 #include <stdio.h> #include <stdlib.h> #include <signal.h> 
 #include <unistd.h> 
 #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> 
 
 #include <linux/delay.h> 
 static int dev; static unsigned char vkey; 
 static char lcdDev[] = "/dev/CLCD"; static int  lcdFd = -1; 
 #define     MAXCHR  32 
 void keysignal(int sig)                       // ½Ã±×³ÎÀ» ¹Þ¾ÒÀ» ¶§ ½ÇÇàµÉ {   read(dev, &vkey, 1);   printf("SIGNAL occur!!!!\n"); } 
 int main(void) {   pid_t id; 
   int n;   char buf[MAXCHR];        if ((dev = open("/dev/KEY", O_RDWR)) < 0) {     printf("return Value is %d\n",dev);     perror("open failed /dev/KEY");     close(dev);     exit(-1);   } 
   lcdFd = open(lcdDev, O_RDWR);   if (lcdFd < 0) {     fprintf(stderr, "cannot open CLCD (%d)", lcdFd);     exit(2);   } 
    (void) signal (SIGUSR1, keysignal);     // keysignal ÇÔ¼ö¸¦    id = getpid();                          // µð¹ÙÀ̽º µå¶óÀ̹ö¿¡°Ô    write(dev, &id, 4);                     // ÇÁ·Î¼¼¼ ID¸¦    printf("press the push button!\n");  (void) signal (SIGUSR1, keysignal);    while(1) {     if(vkey != 0) {     sprintf(buf,"vkey is 0x%x\n", vkey);         write(lcdFd, buf, MAXCHR);         vkey=0;      }   }   close(dev);   return 0; }  | 
5.
		결과물


