ECE30076 Embedded System Programming - LED Device Driver

Similar documents
교육지원 IT시스템 선진화

untitled

PowerPoint 프레젠테이션

PowerPoint 프레젠테이션

교육지원 IT시스템 선진화

PowerPoint 프레젠테이션

PowerPoint 프레젠테이션

PowerPoint 프레젠테이션

Microsoft PowerPoint - lab14.pptx

PowerPoint 프레젠테이션

슬라이드 1

Microsoft PowerPoint - IOControl [호환 모드]

2009년 상반기 사업계획

Chapter #01 Subject

KEY 디바이스 드라이버

Microsoft Word doc

<4D F736F F F696E74202D FB8DEB8F0B8AE20B8C5C7CE205BC8A3C8AF20B8F0B5E55D>

슬라이드 1

임베디드시스템설계강의자료 6 system call 2/2 (2014 년도 1 학기 ) 김영진 아주대학교전자공학과

PowerPoint 프레젠테이션

Microsoft PowerPoint - lab15.pptx

디바이스드라이버 (Device Driver) Driver is literally a subject which drive a object. 응용프로그램에서하드웨어장치를이용해서데이터를직접읽고쓰거나제어해야하는경우에디바이스드라이버를이용 하드웨어를제어하는프로그램과애플리케이션에서

PowerPoint 프레젠테이션

<4D F736F F F696E74202D205BBAB0C3B75D20B8AEB4AABDBA20B5F0B9D9C0CCBDBA20B5E5B6F3C0CCB9F620B8F0B5A82E >

PowerPoint 프레젠테이션

PowerPoint 프레젠테이션

Microsoft Word doc

Chap 7

제1장 Unix란 무엇인가?

PowerPoint 프레젠테이션

Embeddedsystem(8).PDF

제1장 Unix란 무엇인가?

<4D F736F F F696E74202D20B8B6C0CCC5A9B7CEC7C1B7CEBCBCBCAD202839C1D6C2F7207E203135C1D6C2F >

임베디드시스템설계강의자료 6 system call 1/2 (2014 년도 1 학기 ) 김영진 아주대학교전자공학과

<4D F736F F F696E74202D20B8AEB4AABDBA20BFC0B7F920C3B3B8AEC7CFB1E22E BC8A3C8AF20B8F0B5E55D>

제12장 파일 입출력

chap7.key

Microsoft PowerPoint - chap12 [호환 모드]

6주차.key

10.

1장. 유닉스 시스템 프로그래밍 개요

Adding a New Dev file

/chroot/lib/ /chroot/etc/

(Microsoft PowerPoint - Device Driver [\310\243\310\257 \270\360\265\345])

슬라이드 1

(Microsoft PowerPoint - Device Driver [\310\243\310\257 \270\360\265\345])

PowerPoint 프레젠테이션

Microsoft PowerPoint - 10-EmbedSW-11-모듈

K&R2 Reference Manual 번역본

Poison null byte Excuse the ads! We need some help to keep our site up. List 1 Conditions 2 Exploit plan 2.1 chunksize(p)!= prev_size (next_chunk(p) 3

vi 사용법

untitled

좀비프로세스 2

Microsoft Word - MPC850 SPI Driver.doc

Microsoft PowerPoint - [2009] 02.pptx

ABC 11장

lecture4(6.범용IO).hwp

강의10

교육지원 IT시스템 선진화

Chap 6 모듈프로그래밍및 디바이스드라이버구현

Microsoft PowerPoint APUE(File InO).pptx

The Pocket Guide to TCP/IP Sockets: C Version

RaspberryPi 커널컴파일및커널모듈 1 제 13 강 커널컴파일및커널모듈 커널컴파일가상주소 (mmap() 함수 ) 에의한디바이스제어커널모듈및커널모듈테스트커널모듈에의한입출력디바이스제어 (LED, BTN) 커널모듈을커널에포함하기

본 강의에 들어가기 전

<4D F736F F F696E74202D20BBB7BBB7C7D15F FBEDFB0A3B1B3C0B05FC1A638C0CFC2F72E BC8A3C8AF20B8F0B5E55D>

Microsoft PowerPoint APUE(Intro).ppt

(Asynchronous Mode) ( 1, 5~8, 1~2) & (Parity) 1 ; * S erial Port (BIOS INT 14H) - 1 -

Microsoft PowerPoint - 09-Pipe

Microsoft PowerPoint - chap13-입출력라이브러리.pptx

11장 포인터

Microsoft PowerPoint APUE(File InO)

Mango220 Android How to compile and Transfer image to Target

Microsoft PowerPoint - chap2


망고100 보드로 놀아보자 -13

BMP 파일 처리

1217 WebTrafMon II

Microsoft PowerPoint APUE(File InO).ppt

API 매뉴얼

Sena Technologies, Inc. HelloDevice Super 1.1.0

Microsoft PowerPoint - ch09_파이프 [호환 모드]

2009년 상반기 사업계획

Microsoft PowerPoint - chap02-C프로그램시작하기.pptx

04디바이스드라이버

Microsoft PowerPoint - o8.pptx

슬라이드 1

The Pocket Guide to TCP/IP Sockets: C Version

Microsoft Word - KPMC-400,401 SW 사용 설명서

Microsoft PowerPoint - chap06-2pointer.ppt

Microsoft PowerPoint - 3ÀÏ°_º¯¼ö¿Í »ó¼ö.ppt

<443A5C4C C4B48555C B3E25C32C7D0B1E25CBCB3B0E8C7C1B7CEC1A7C6AE425CBED0C3E0C7C1B7CEB1D7B7A55C D616E2E637070>

Chap06(Interprocess Communication).PDF

1장. 유닉스 시스템 프로그래밍 개요

untitled

SYN flooding

[8051] 강의자료.PDF

< E20C6DFBFFEBEEE20C0DBBCBAC0BB20C0A7C7D12043BEF0BEEE20492E707074>

커알못의 커널 탐방기 이 세상의 모든 커알못을 위해서

Microsoft PowerPoint - Lecture_Note_7.ppt [Compatibility Mode]

2009년 상반기 사업계획

Transcription:

Module 12: LED 제어디바이스드라이버 ESP30076 임베디드시스템프로그래밍 (Embedded System Programming) 조윤석 전산전자공학부

주차별목표 하드웨어제어를위한디바이스드라이버작성방법알아보기 LED 제어용디바이스드라이버작성하기 ioremap 을이용한 LED 제어디바이스드라이버 mmap 을이용한 LED 제어디바이스드라이버 2

디바이스구분 문자디바이스 (Character device) 자료의순차성을지닌장치로버퍼를사용하지않고바로읽고쓸수있는장치 직렬포트, 병렬포트, 마우스, PC 스피커, 터미널등 블록디바이스 (Block device) 버퍼캐시 (cache) 를통해블록단위로입출력되며, 랜덤액세스가가능하고, 파일시스템을구축할수있음 플로피디스크, 하드디스크, CD-ROM, RAM 디스크등 네트워크디바이스 (Network device) 네트워크통신을통해네트워크패킷을주고받을수있는디바이스 Ethernet, PPP, ATM, ISDN, NIC (Network Interface Card) 등 3

디바이스드라이버작성하려면 하드웨어에대한분명한이해가있어야함 소프트웨어구조에대한이해 예를들어직렬디바이스 (UART) 에대한 device driver 를작성한다면다음의사항들을분명히알아야함 ( 일부나열 ) UART 는세종류의레지스터를가지고있음 Data registers, control registers, status registers 하나의디바이스주소에하나이상의디바이스레지스터들이있을수있음 디바이스는 control register 의 bit 들을설정함으로써초기화하거나, 설정을변경할수있음 디바이스는 control register 의 bit 들을리셋함으로써 close 하거나리셋을할수있음 4

디바이스드라이버작성하려면 Control register 비트들은 UART 의모든동작을제어할수있음 따라서 control register 의각비트들의목적정확히알아야함 Status register 비트들은디바이스의현재상태 (status) 에대한정보를가지고있고, action 이일어날때마다해당플래그의값들이변경됨 ( 예 )TRH 버퍼레지스터의내용이모든전송된후새로전송할비트가생긴다고할경우, 두상태사이에 transmitter empty flag 의설정이변함 Status register 에서각 status flag 의목적이무엇인지정확히알아야함 각레지스터에대한주소를알아야함 예를들어 IBM PC 의경우 Timer : 0x0040 ~ 0x005F Serial COM1: 0x03F8 ~ 0x03FF Serial COM2: 0x02F8 ~ 0x02FF 5

file_operations 구조체 6 struct file_operations { struct module *owner; loff_t (*llseek) (struct file *, loff_t, int); ssize_t (*read) (struct file *, char *, size_t, loff_t *); ssize_t (*write) (struct file *, const char *, size_t, loff_t *); int (*readdir) (struct file *, void *, filldir_t); unsigned int (*poll) (struct file *, struct poll_table_struct *); int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); int (*mmap) (struct file *, struct vm_area_struct *); int (*open) (struct inode *, struct file *); int (*flush) (struct file *); int (*release) (struct inode *, struct file *); int (*fsync) (struct file *, struct dentry *, int datasync); int (*fasync) (int, struct file *, int); int (*lock) (struct file *, int, struct file_lock *); ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, loff_t *); ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *); ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); };

Device Driver 에서사용하는함수들 open() 해당디바이스에연산을가하기위해해당디바이스파일을열기위한함수. 사용수증가 read() 해당디바이스로부터데이터를얻은데이터를커널영역에서사용자영역으로복사하기위한함수 write() 사용자영역의데이터를커널영역으로복사하기위한함수 release() 해당드라이버가응용프로그램에의해닫힐때호출하는함수. 사용수감소 ioctl() 읽기 / 쓰기이외의부가적인연산을위한인터페이스 - 디바이스설정및하드웨어제어 ( 향상된문자드라이버작성가능 ) 7

LED Anode (+) Cathode (-) Cathode (-) Anode (+) Symbol Appearance Active-HIGH Active-LOW 8

연결도파악 9

회로도에서 LED 연결부분찾기 확장보드 (PC100) 에있는 8 개 LED 구동 10

LED_CS0 11

VHDL 코드 entity PC100_Decode is Port ( Xm0ADDR : in STD_LOGIC_VECTOR (20 downto 17);... CPLD_CS5 : in STD_LOGIC; LED_CS0 : out STD_LOGIC; LED_CS1 : out STD_LOGIC; KEY_CS2 : out STD_LOGIC;... end PC100_Decode; architecture Behavioral of PC100_Decode is begin LED_CS0 <= '0' when (XnRESET = '1' and CPLD_CS5 = '0' and Xm0ADDR(20 downto 17) = "0000") else '1'; LED_CS1 <= '0' when (XnRESET = '1' and CPLD_CS5 = '0' and Xm0ADDR(20 downto 17) = "0001") else '1'; KEY_CS2 <= '0' when (XnRESET = '1' and CPLD_CS5 = '0' and Xm0ADDR(20 downto 17) = "0010") else '1'; end Behavioral; 12

CPLD 회로 물리주소 0xA000_0000 를가상주소로변환 unsigned short *srom_bank5; srom_bank5 = ioremap(0xa8000000, 0x1000); *(srom_bank5) 의형태로물리주소에접근 데이터에값쓰기 *(srom_bank5) = 0xAAAA; // 1010_1010_1010_1010(2) 물리주소 0xA8000000 에 0xAAAA 가쓰여짐 AP(PV210) 에의해서 Xm0CSn5 가 LOW 로떨어짐 물리주소 0xA8000000 을통해서 0xAAAA 데이터를받은 SROM 컨트롤러는 Xm0ADDR[15:0] 에 0x0000 를출력하고 Xm0DATA[15:0] 에 0xAAAA 를출력 13

Memory Address Map 14

Device Specific Address Space (Ref) S5PV210 CPU User Manual (S5PV210_Usernamual_Rev1.0.pdf) p.23~24 15

SROM Interface SROM 인터페이스에할당된특정주소접근시 AP(Application Processor, PV210) 내부에존재하는 SROM 컨트롤러가칩셀렉트동작을자동으로수행 구분 시작주소 마지막주소 크기 동작하는 CS SROM Bank 0 0x8000_0000 0x87FF_FFFF 128MB Xm0CSn0 SROM Bank 1 0x8800_0000 0x8FFF_FFFF 128MB Xm0CSn1 SROM Bank 2 0x9000_0000 0x97FF_FFFF 128MB Xm0CSn2 SROM Bank 3 0x9800_0000 0x9FFF_FFFF 128MB Xm0CSn3 SROM Bank 4 0xA000_0000 0xA7FF_FFFF 128MB Xm0CSn4 SROM Bank 5 0xA800_0000 0xAFFF_FFFF 128MB Xm0CSn5 16

CPLD_CSn5 / Xm0CSn5 17

Xm0CSn5 in PC100 Achro-210T PC100( 확장보드 ) 18

Xm0CSn5 in S5PV210(CPU) 19

Xm0CSn5 20

SROM_CSn[5] 21 (Ref) S5PV210 CPU User Manual (S5PV210_Usernamual_Rev1.0.pdf) p.23~24

74HC574 74HC574 8 개의 D flip-flop 으로구성 22

CPU 와 PC100 간의 AB/DB 연결 23

mmap vs ioremap mmap() 과 ioremap() 디바이스의메모리일부를현재프로세스의메모리영역으로 mapping 하는방법 ioremap() 해당메모리의물리주소를커널의가상주소에매핑 mmap() 응용프로그램의가상주소에해당메모리의물리주소를매핑 응용프로그램 하드웨어 디바이스드라이버 mmap() ioremap() 물리주소에매핑된프로세스의가상주소 매핑해제 : munmap() 물리주소영역 매핑해제 : iounmap() 물리주소에매핑된커널의가상주소 24

mmap() vs ioremap() mmap() 응용프로그램에서 I/O 장치의 physical address 에직접접근하고자할때사용 즉사용자레벨에서커널레벨 ( 디바이스접근 ) 로직접접근 ioremap() 커널에서 I/O 장치의 physical address 에직접접근하고자할때사용 커널수준 (Device driver 내 ) 에서직접커널수준 ( 디바이스접근 ) 으로접근 Device driver 내에서작성시드라이버코드내에 mmap 대신 ioremap 사용 코드를작성할때 ioremap 을사용해서하는것이 safe 한프로그램을만드는관점에서는정석임 Mmap 의장점은응용프로그램에서직접 I/O 장치로접근함으로속도가빠름. 25

ioremap 함수를이용한 LED 제어 확장보드 (PC100) 에있는 8 개의 LED 제어 응용프로그램 #./ioremap_led_test 7 D7 LED 의불이켜짐 Argument 의값이 0 이면 8 개 LED off, 9 이면모두 ON 드라이버작성관련하여 LED 의물리주소는 0xA800_0000 임 Major 번호는 246 번으로할당하는것으로함 (major.h 에서할당되지않은번호선택함 ) 드라이버소스파일명 : ioremap_led_dd.c 디바이스노드이름은 iom_led 로함 26

LED 구동디바이스드라이버 (ioremap_led_dd.c) root@esp:~# mkdir /root/work/dd/led_ioremap root@esp:~# cd /root/work/dd/led_ioremap root@esp:~/work/dd/led_ioremap# vi ioremap_led_dd.c 27 /* LED Driver using ioremap function */ #include <linux/kernel.h> #include <linux/module.h> #include <linux/fs.h> #include <linux/init.h> #include <asm/io.h> /* outb() */ #include <asm/uaccess.h> /* copy_from_user() */ #define DEV_NAME "iom_led" #define IOM_LED_MAJOR_NUM 246 #define IOM_LED_ADDRESS 0xA8000000 /* physical addr for LED's */ MODULE_LICENSE("GPL"); static int ledport_usage = 0; static unsigned char *iom_led_addr; int init_iom_led(void); void cleanup_iom_led(void); module_init(init_iom_led); /* % insmod */ module_exit(cleanup_iom_led); /* % rmmod */ int iom_led_open (struct inode *, struct file *); int iom_led_release (struct inode *, struct file *); ssize_t iom_led_write (struct file *, const char *, size_t, loff_t *);

ioremap_led_device.c (2) struct file_operations iom_led_fops = {.owner = THIS_MODULE,.open = iom_led_open,.release = iom_led_release,.write = iom_led_write, }; int major_num = 0; int iom_led_open (struct inode *inode, struct file *filp) { if( ledport_usage!= 0 ) return -EBUSY; ledport_usage = 1; return 0; } int iom_led_release (struct inode *inode, struct file *filp) { ledport_usage = 0; return 0; } ssize_t iom_led_write (struct file *filp, const char *buf, size_t count, loff_t *f_pos) { unsigned char led_data; } 28 if (copy_from_user(&led_data, buf, count)) outb(led_data, (unsigned int)iom_led_addr); return count; return -EFAULT;

ioremap_led_device.c (3) int init init_iom_led(void) { int major_num; major_num = register_chrdev(iom_led_major_num, DEV_NAME, &iom_led_fops); if ( major_num < 0 ) { printk(kern_warning"%s: can't get or assign major number %d\n", DEV_NAME, IOM_LED_MAJOR_NUM); return major_num; } iom_led_addr = ioremap(iom_led_address, 0x1); } printk("success to load the device %s. Major number is %d\n", DEV_NAME, IOM_LED_MAJOR_NUM); return 0; void exit cleanup_iom_led(void) { iounmap(iom_led_addr); } unregister_chrdev(iom_led_major_num, DEV_NAME); printk("success to unload the device %s...\n", DEV_NAME); 29

LED 구동응용프로그램 (ioremap_led_test.c) root@esp:~/work/dd/led_ioremap# vi ioremap_led_test.c 30 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #define LED_DEV "/dev/iom_led" unsigned char led_hex_data[] = {0x00, 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f, 0xff}; int main(int argc, char *argv[]) { int fd; int led_index; if ( argc!= 2 ) { printf("usage: %s number (ex) %s 2 [0:9]..\n", argv[0], argv[0]); return -1; } led_index = atoi(argv[1]); if (led_index < 0 led_index > 9 ) { printf("invalid Range!! (%d)\n", led_index); return -1; }

ioremap_led_test.c (2) fd = open(led_dev, O_WRONLY); if ( fd < 0 ) { printf("device open error (%s)...!!\n", LED_DEV); return -1; } } write (fd, &led_hex_data[led_index], sizeof(led_hex_data[led_index])); close (fd); return 0; 31

컴파일 % vi Makefile obj-m = ioremap_led_dd.o CC = arm-linux-gcc KDIR = /root/download/kernel-2.6.35 PWD = $(shell pwd) TEST_TARGET = ioremap_led_test TEST_SRCS = $(TEST_TARGET).c all: module test_pgm module: $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules test_pgm: $(CC) $(TEST_SRCS) -o $(TEST_TARGET) clean: rm -rf *.ko rm -rf *.o rm -rf *.symvers *.order rm -rf $(TEST_TARGET) % make 32

실행 타겟보드에서실행 Host 컴퓨터의 /root 디렉토리를 NFS 로연결 # cd /root/nfs/work/dd/led_ioremap # insmod ioremap_led_dd.ko # mknod /dev/iom_led c 246 0 #./ioremap_led_test 2 #./ioremap_led_test 9 #./ioremap_led_test 0 33

LED driver 구동원리 % insmod 디바이스드라이버프로그램 (ioremap_led_dd.c) 커널내모듈적재 iom_led_init() 사용자프로그램 (ioremap_led_test.c) main() iom_led_open() 1. call 2. return 디바이스열기 open() 성공 실패 드라이버동작 iom_led_write() 3. call 4. return 시스템콜 write() iom_led_release() 5. call 6. return 디바이스닫기 close() 커널내모듈제거 % rmmod iom_led_exit() 종료 34

mmap 함수를이용한 LED 제어 확장보드 (PC100) 에있는 8 개의 LED 를 1 초간격으로번갈아가며켜지도록 LED 를제어하는프로그램을작성. Ct 기 +C 를누르면프로그램종료됨 LED 연결분석 SROM bank5 에연결됨 CPU 의 address bus Xm0ADDR[12:9]= 0000 이어야함 PC100 확장보드의 Xm0ADDR[20:17] 이 CPU Xm0ADDR[12:9] 에연결됨 따라서 LED 에접근하기위한주소는 0xA000_0000 임 35

void *mmap() led_addr = mmap( NULL, LED_MAP_SIZE, PROT_READ PROT_WRITE, MAP_SHARED, fd, LED_PHY_ADDR ); void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); 메모리의내용을파일이나디바이스에대응하기위해사용하는시스템콜 void *addr, // 물리적장치에대해메모리로시작할위치, 보통 0 (NULL) size_t length, // 물리적장치의크기, 즉확보될메모리의크기. Addr부터 length 만큼매핑 int prot, // 읽기 / 쓰기와같은메모리의특성 ( 헤더파일 : <sys/mman.h>) PROT_EXEC: 페이지에실행될수있음 PROT_READ: 페이지는읽기가능 PROT_WRITE: 페이지는쓰기가능 PROT_NONE: 페이지를접근할수없음 int flags, // 다른프로세스와공유할지여부 MAP_FIXED MAP_SHARED: 다른프로세스와공유하며, 사용하는모든프로세스는동등한권한을가짐. 따라서공유하는프로세스로인한데이터동기화가필요하며, 이를위해 msync(), munmap() 등이사용됨 MAP_PRIVATE: 혼자만사용할경우. MAP_SHARED와 MAP_PRIVATE 둘중하나는반드시사용해야함 int fd, // 물리적장치의디스크립터 off_t offset // 보통 0 36

mmap 을이용한 LED 구동 (led_mmap.c) root@esp:~# mkdir /root/work/dd/led_mmap root@esp:~# cd /root/work/dd/led_mmap root@esp:~/work/dd/led_ioremap# vi led_mmap.c #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <fcntl.h> #include <sys/mman.h> /* PROT_WRITE */ #include <signal.h> /* SIGINT */ #define LED_MAP_SIZE 0x1000 /* 페이지크기 (4096) 의정수배 */ #define LED_PHY_ADDR 0xA8000000 /* led 의 physical address */ #define LED (*((volatile unsigned char *)(led_addr + 0))) // LED 를표시하기위한값 // 0000(0) 1110(1) 1101(2) 1011(3)... unsigned char val[] = { 0x00, 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f}; void *led_addr; // 메모리가매핑될포인터 int quit = 0; void quit_signal(int sig) { // Ctrl + C 에의해중지되게하기위해시그널을사용한다. quit = 1; } 37

led_mmap.c (2) int main (int argc, char *argv[]) { int fd; static unsigned char led; } 38 // 주의 : O_SYNC 플래그를지정해야캐시되지않는다. fd = open( "/dev/mem", O_RDWR O_SYNC ); if (fd == -1) { perror("open(\"/dev/mem\")"); exit(1); } // MAP_SIZE 에해당하는페이지만큼의영역을매핑한다. led_addr = mmap( NULL, LED_MAP_SIZE, PROT_WRITE, MAP_SHARED, fd, LED_PHY_ADDR ); if (led_addr == MAP_FAILED) { perror("mmap()"); exit(2); } signal(sigint, quit_signal ); // <ctrl+c> 를누르면종료되게 signal 을등록한다. printf("\npress <ctrl+c> to quit.\n\n"); while(!quit) { LED = (val[led++ % 9]); sleep(1); } LED = 0xff; if (munmap(led_addr, LED_MAP_SIZE) == -1) { // 할당받았던매핑영역을해제한다. perror("munmap()"); exit(3); } close(fd); return 0;

컴파일및실행 [ 호스트 ] % arm-linux-gcc -o led_mmap led_mmap.c [Achro-210T] # cd ~/nfs/work/dd/led_mmap #./led_mmap 39