CLCD + 키메트릭스 조합

2011, Dec 19    

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.
결과물