14
This presentation is the property of its rightful owner.
Sponsored Links
1 / 57

14 주차 . 디바이스 드라이버의 응용 PowerPoint PPT Presentation


  • 150 Views
  • Uploaded on
  • Presentation posted in: General

14 주차 . 디바이스 드라이버의 응용. 수원과학대학교 정보통신과. 14.1 디바이스와 주소. 디바이스의 주소 지정 방식 전용 입출력 방식 (dedicated I/O 혹은 isolated I/O) 메모리 사상 입출력 방식 (memory mapped I/O). PXA270 디바이스의 주소공간. 커널이 가상 주소를 사용해 컴퓨팅 자원에 접근하므로 ARM 아키텍처의 디바이스에 접근하려면 물리 주소를 가상 메모리 공간으로 사상해야 작업 가능

Download Presentation

14 주차 . 디바이스 드라이버의 응용

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


14

14주차. 디바이스 드라이버의 응용

수원과학대학교 정보통신과


14

14.1 디바이스와 주소

  • 디바이스의 주소 지정 방식

    • 전용 입출력 방식(dedicated I/O 혹은 isolated I/O)

    • 메모리 사상 입출력 방식(memory mapped I/O)

수원과학대학 정보통신과


Pxa270

PXA270 디바이스의 주소공간

  • 커널이 가상 주소를 사용해 컴퓨팅 자원에 접근하므로 ARM 아키텍처의 디바이스에 접근하려면 물리 주소를 가상 메모리 공간으로 사상해야 작업 가능

  • 디바이스의 접근은 시스템 모드에서 수행되므로 디바이스를 위한 가상 주소는 커널 공간임

  • 응용 프로그램은 커널 공간을 직접 제어할 수 없으며 커널도 사용자 공간을 직접 다룰 수 없음

  • 따라서 디바이스 드라이버가 사용자와 커널 공간 사이에 데이터를 전송하려면 시스템호출과 같은 함수를 사용해야 함

수원과학대학 정보통신과


14

타겟 시스템의 디바이스 구성

수원과학대학 정보통신과


14

타겟 시스템 디바이스들의 물리주소

수원과학대학 정보통신과


14

디바이스 드라이버 제작 과정

  • 디바이스 드라이버 소스 코드 작성

  • 응용 프로그램 소스 코드 작성

  • 디바이스 드라이버와 응용 프로그램의 컴파일

  • 호스트 시스템에서 타겟 시스템으로 디바이스 드라이버와 응용 프로그램을 전송

  • 디바이스 드라이버를 타겟 시스템 커널에 적재

  • 타겟 시스템에서 응용 프로그램을 수행하여 테스트

수원과학대학 정보통신과


Led 1

LED 디바이스 드라이버 [1]

LED 포트를 GND로 만들면 불이 켜지고

3V를 가하면 불이 꺼진다.

수원과학대학 정보통신과


Led 2

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을 기록하면 꺼진다.

수원과학대학 정보통신과


Fnd 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 [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

수원과학대학 정보통신과


14

키 매트릭스

KEYOUT 물리주소

= 0x11D000000

  • KEY 검출 방법

    • KEYOUT0에 1값을 출력하고 KEYIN0~KEYIN3을 차례대로 읽음

    • 이 때 어떤 키가 눌려지면 대응하는 KEYIN의 값이 1로 검출되고 그렇지 않으면 0값이 검출됨

    • 위 과정을 KEYOUT1, 2, 3에 대해 반복

  • 예를 들어 KB1을 눌렀을 경우, KEYOUT3에 1을 출력했을 때 KEYIN을 읽으면 KEYIN0의 값이 1로 검출됨.

KEYIN 물리주소

= 0x11E000000

수원과학대학 정보통신과


Lcd 1

문자 LCD [1]

  • 16문자씩 2라인으로 표시. 폰트는 5*7도트.

  • LCD 컨트롤러에는 DR(data register)와 IR(instruction register)가 있음

  • LCD 물리주소

    • LCD 데이터: 0x12300000

    • LCD 제어명령: 0x12380000

수원과학대학 정보통신과


Lcd 2

문자 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 주소 사용

수원과학대학 정보통신과


Dot matrix 1

0x1180_0000

0x1190_0000

0x11A0_0000

0x11B0_0000

0x11C0_0000

Dot Matrix [1]

  • LED들을 매트릭스 형태로 배선시킨 구조

  • LED를 점등해 원하는 글씨나 그림을 나타내는 디바이스

  • 5개의 열에는 주소 버스가 연결, 7개의 행에는 데이터 버스가 연결됨

데이터 버스 연결

주소 버스 연결

수원과학대학 정보통신과


Dot matrix 2

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

수원과학대학 정보통신과


14

실습 프로그램 다운 받기

  • 리눅스 기본 웹브라우저인 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           (압축풀기)

수원과학대학 정보통신과


14

타겟 보드의 파일 시스템 초기화

  • 왜? 타켓보드에서 타인이 앞서 실습한 결과를 없애기 위해

  • 호스트에서

    • cp /embed/hybus/images/rootfs.img /tftpboot

  • 타겟에서

    • hybus> tftp rootfs.img root

    • hybus> flash root

수원과학대학 정보통신과


14 1 led

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 led1

실습 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 led2

실습 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 led3

실습 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 led4

실습 14-1 LED 디바이스 드라이버 작성

  • 디바이스 드라이버와 응용프로그램을 컴파일

  • 생성한 모듈(led.ko)과 응용 프로그램(test_led)을 타겟 시스템으로 전송

  • 타겟 시스템에서 디바이스 드라이버를 적재→응용 프로그램 테스트

수원과학대학 정보통신과


14 2 fnd

실습 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 fnd1

실습 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 fnd2

실습 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 fnd3

실습 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 fnd4

실습 14-2 FND 디바이스 드라이버 작성

  • FND 디바이스 드라이버 프로그램을 컴파일하기 위한 Makefile 작성

  • 디바이스 드라이버와 응용프로그램을 컴파일

    • make

    • arm-linux-gcc –o test_fnd test_fnd.c

  • 기존 디바이스 드라이버를 테스트한 후에 삭제

수원과학대학 정보통신과


14 2 fnd5

실습 14-2 FND 디바이스 드라이버 작성

  • 새로 생성한 디바이스 드라이버(fnd.ko)와 응용 프로그램(test_fnd)을 타겟 시스템으로 전송

  • 응용프로그램을 실행한 후 임의의 숫자들을 입력해 결과를 관찰

수원과학대학 정보통신과


14

실습 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

실습 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

실습 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

실습 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

실습 14-3 키 매트릭스 디바이스 드라이버 작성

  • Makefile을 작성

  • 디바이스 드라이버 모듈과 응용 프로그램을 컴파일

    • make

    • arm-linux-gcc –o test_key test_key.c

  • 기존 디바이스 드라이버를 테스트

수원과학대학 정보통신과


14

실습 11-3 키 매트릭스 디바이스 드라이버 작성

  • 생성한 디바이스 파일(key.ko)과 응용프로그램(test_key)을 타겟 시스템으로 전송

  • 기존 디바이스 드라이버를 삭제하고 새 디바이스 드라이버를 커널로 적재하고 새로운 디바이스 파일을 만든 후 응용프로그램으로 테스트

수원과학대학 정보통신과


14 4 lcd

실습 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 lcd1

실습 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 lcd2

실습 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 lcd3

실습 14-4 문자형 LCD 디바이스 드라이버 작성

  • 문자 LCD 디바이스 드라이버 프로그램을 컴파일하기 위한 Makefile을 작성

  • 디바이스 드라이버 모듈과 응용 프로그램을 컴파일

    • make

    • arm-linux-gcc –o test_clcd test_clcd.c

  • 기존 디바이스 드라이버와 디바이스 파일을 테스트한 후 삭제

수원과학대학 정보통신과


14 4 lcd4

실습 14-4 문자형 LCD 디바이스 드라이버 작성

  • 생성한 디바이스 드라이버(clcd.ko)와 응용 프로그램(test_clcd)을 타겟 시스템으로 전송

  • 디바이스 드라이버를 커널로 적재하고 필요한 디바이스 파일을 생성한 후 테스트

수원과학대학 정보통신과


14

실습 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

실습 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

실습 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

실습 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

실습 14-5 도트 매트릭스 디바이스 드라이버 작성

  • 도트 디바이스 프로그램 컴파일하기 위한 Makefile을 작성

  • 디바이스 드라이버 모듈과 응용 프로그램을 컴파일

    • make

    • arm-linux-gcc –o test_dot test_dot.c

  • 기존 디바이스 드라이버를 테스트한 후 디바이스 드라이버와 디바이스 파일을 삭제

수원과학대학 정보통신과


14

실습 14-5 도트 매트릭스 디바이스 드라이버 작성

  • 생성한 디바이스 파일(dot.ko)과 응용프로그램(test_dot)을 타겟 시스템으로 전송

  • 디바이스 드라이버를 커널로 적재하고 새로운 디바이스 파일을 만든 후 응용프로그램으로 테스트

수원과학대학 정보통신과


1 key driver

실습문제 1번 Key Driver 개선

  • 문제점: 교재의 키 드라이버는 키를 한번 눌러도 여러번 누른 것으로 인식됨

  • 개선: 키를 계속 누르고 있어도 한 번 누른 것으로 인식시킨다. 즉, 한번 눌렀다가 뗀 후 다시 눌러야 새로운 키로 인식시킨다.

수원과학대학 정보통신과


Review

[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

수원과학대학 정보통신과


Review1

[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

수원과학대학 정보통신과


Review2

[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);

수원과학대학 정보통신과


Review3

[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 }

수원과학대학 정보통신과


14

부록 B.1 주요 커널 함수 및 변수

  • 아키텍처 종류에 따른 데이터형 바이트 수

  • 데이터 전달 함수

수원과학대학 정보통신과


14

부록 B.2 시그널 함수

  • 시그널은 프로세스 간 통신을 위한 방법중의 하나로, 하나 이상의 프로세스에 비동기적인 사건을 알리기 위해 사용

    • 디바이스, 오류 상황, 인터럽트 키 사용 등의 경우 발생

  • 사용자 프로그램에서 사용하는 시그널 함수의 형식

    • signum: 처리할 시그널 이름

    • handler() : 해당 시그널이 전달될 때 호출

  • 디바이스 드라이버에서 사용자 프로그램에 시그널을 보내는 함수의 형식

    • pid : 시그널을 받을 사용자 프로세스의 식별자

    • priv : 우선 순위로 <linux>/kernel/signal.c에 정의되어 있음

수원과학대학 정보통신과


14

  • 시그널 사용법

수원과학대학 정보통신과


14

부록 B.3 커널 타이머

  • 타이머 인터럽트: 주기적으로 인터럽트를 발생시켜 반복해서 처리해야 할 작업에 사용

  • 타이머 인터럽트는 HZ(아키텍처에 의존적인 값)로 설정

  • 타이머 인터럽트가 발생하면 스케줄러에 의해 새로운 작업을 스케줄하고 jiffies(운영체제가 부팅된 시점부터 발생한 클록 회수) 값을 증가

  • 커널 타이머를 사용해 특정 작업을 정해진 시간에 실행

  • “jiffies ≧ timerexpires” 조건을 만족할 때 타이머에 등록한 함수를 실행

    • expires는 jiffies와 타이머 간격을 합한 값

수원과학대학 정보통신과


14

  • 커널 타이머의 사용법

수원과학대학 정보통신과


14

실습문제 2번

  • 키 매트릭스를 누르면 숫자가 LCD에 나타나도록 응용 프로그램을 작성하고 테스트 해보시오.

    • test_key.c와 test_clcd.c의 조합

KEY MATRIX 배열

LCD

수원과학대학 정보통신과


14

창작 Show

(1) LED show (여러가지 패턴으로 깜빡이기)

(2) FND를 이용한 타이머 (숫자 올라가기)

(3) CLCD 배너 (흐르는 문자열)

(4) Dot Matrix show (깜빡이는 심장)

(5) 기타…

  • 공통 힌트: gcc에서 시간 delay  sleep()

    • 예) sleep(1); 1초 지연

    • sleep(0.1); 0.1초 지연

수원과학대학 정보통신과


  • Login