Presentation is loading. Please wait.

Presentation is loading. Please wait.

임베디드 리눅스 시스템 (using EMPOS II)

Similar presentations


Presentation on theme: "임베디드 리눅스 시스템 (using EMPOS II)"— Presentation transcript:

1 임베디드 리눅스 시스템 (using EMPOS II)
한백전자 기술연구소 (소프트웨어 개발팀) 작 성 : 양 근 배

2 임베디드 시스템과 리눅스 임베디드 시스템 개발 구조 EMPOS II 하드웨어/소프트웨어 구성
부트로더 분석(EMPOS-BOOT) 리눅스 메모리 관리 리눅스 프로세스 관리 리눅스 커널 리눅스 파일 시스템 소프트웨어 개발 환경 설치 응용 프로그램 작성 디바이스 드라이버

3 임베디드 시스템과 리눅스 임베디드 시스템의 정의 정해진 특정 기능을 수행하기 위해 하드웨어와 소프트웨어가 내장된 전자제어 시스템을 말한다. 즉 단순 회로만으로 구성된 장치가 아닌 마이크로 프로세서가 내장되어 있고, 이러한 마이크로프로세서를 운영하여 원하는 작업을 수행 및 관리하는 프로그램이 포함된 시스템을 의미한다. 다양한 응용 분야에 적용 PDA(Personal Digital Assistant ) 각종 전자 제품 가정 자동화 시스템 공장 자동화 시스템

4 임베디드 시스템의 도입 임베디드 운영체제 시스템의 규모가 커짐 - Multi Tasking
임베디드 시스템과 리눅스 임베디드 시스템의 도입 시스템의 규모가 커짐 - Multi Tasking Network나 multimedia가 시스템의 기본으로 자리 잡음 - Networking, GUI, Audio, Video,… 임베디드 시스템이 해야 할 일이 많아 지고 복잡해짐 순차적인 프로그램이 어렵게 됨 임베디드 시스템에도 운영체제의 개념이 필요하게 됨 임베디드 운영체제 Real Time OS(RTOS) - VxWorks, pSOS, VRTX 일반 임베디드 OS - Embeded linux, Windows CE

5 기존 상용 임베디드 OS의 단점 크기가 너무 크고 커널의 재구성이 비교적 용이하지 않다. - 다양한 시스템을 구성하기 힘들다.
임베디드 시스템과 리눅스 기존 상용 임베디드 OS의 단점 크기가 너무 크고 커널의 재구성이 비교적 용이하지 않다. - 다양한 시스템을 구성하기 힘들다. - 이동형 장비의 자원 한계의 벽에 이루기가 쉽다. 초기 구입비와 사용료(로열티)가 너무 비싸다. - 대중화 상용화에 걸림돌이 될 수 있다. 커널이 오픈 소스가 아니다. - 개발자도 한 사람의 사용자, OS에 대한 기술 축적불가 일반인에게 잘 알려져 있지 않다.

6 리눅스 특징 멀티유저, 멀티 태스킹 시스템. CPU의 최적화 효율적인 가상 메모리
임베디드 시스템과 리눅스 리눅스 특징 멀티유저, 멀티 태스킹 시스템. CPU의 최적화 효율적인 가상 메모리 동적 공유 라이브러리 (라이브러리 모듈의 존재) 뛰어난 네크워킹(네트웍 서버로서의 탁월성) 유연한 사용자 환경(X-Windows의 공개버전인 XFree86) 가상 콘솔의 제공(여러 개의 가상 콘솔을 사용) POSIX와 완변한 호환

7 리눅스의 장점 리눅스는 오래되고 많은 사람이 사용한다. - 검증이 되었고, 안정적이고 다양한 기능을 수용 할 수 있다.
임베디드 시스템과 리눅스 리눅스의 장점 리눅스는 오래되고 많은 사람이 사용한다. - 검증이 되었고, 안정적이고 다양한 기능을 수용 할 수 있다. open source, open architecture이다. - 수많은 개발자에 의하여 발전된다. - 개발자 필요에 의하여 변경 가능하며 문제점 해결 할 수 있다. 소규모 모듈단위로 설계되어 있다 - 구조 변경 및 재구성이 용이하다. Real Time운영을 지원한다. - 상용 OS에 열세였던 RealTime성을 확보. 다양한 분야에 적용 가능 GUI의 불필요 원격 관리의 용의성(네트웍을 통한 시스템의 관리 유지보수 가능) 리부팅의 불필요(커널 UP 제외) 바이러스및 보안에 안전 뛰어난 어플리 케이션(컴파일러, 편집기, 기타 유틸리티) 상대적으로 작은 커널 크기(PDA등에 로드 가능)

8 리눅스의 한계 품질 보증 프로그램의 부제 체계적이지 못한 문서화 버그 존재 확률이 많은 커널 멀티 미디어 기능이 약함
임베디드 시스템과 리눅스 리눅스의 한계 품질 보증 프로그램의 부제 체계적이지 못한 문서화 버그 존재 확률이 많은 커널 멀티 미디어 기능이 약함 - MS Windows에 비해 멀티미디어 웹브라우징 기능이 약함

9 임베디드 시스템 개발 구조

10 임베디드 시스템 개발 임베디드 시스템의 개발 하드웨어 OS개발 또는 포팅 응용 프로그램 개발 임베디드 시스템 개발 구조
디바이스 드라이버 응용 프로그램 개발 하드웨어

11 임베디드 리눅스의 흐름 임베디드 시스템 개발 구조 전원 ON 부트로더 로딩 부트로더 개발/수정 커널 로딩 커널 개발/수정
루트파일시스탬 로딩 Shell/Init 프로세서 파일시스템 작성

12 HOST TARGET 일반적인 임베디드 S/W 개발 환경 구성 Target Server Debug Agent GUI
임베디드 시스템 개발 구조 일반적인 임베디드 S/W 개발 환경 구성 HOST GUI Development Tools Simulation Environment Target Server TARGET Debug Agent Embeded Application Core OS Kernel Library Sub-system

13 EMPOS-II HW/SW 구성

14 EMPOS-II HW/SW 구성 하드웨어 자원
Memory : 128 Mbyte SDRAM, 32-Mbyte Flash memory. 1 Mbyte SRAM PCMCIA slot 1개, Compact slot 1개 PS2 Keyboard, Mouse controller Ethernet : 10/100 M LAN91C111 Primary/Secondary Ethernet controller Touch-screen panel controllers : Burr Brown ADS7846 Audio CODEC : Cirrus CS4202 TFT LCD panel USB Client port 1 Port IrDA (infrared) transceiver 1 Port Full-Function UART 1 Port Bluetooth UART l Port SD(Secure Digital memory Card ) or MultiMediaCard Slot 1개 I2C to 24C16 EEPROM Epson RTC 4513 Real Time Clock Module Intel SA-1111 companion 칩 확장용 Expansion 1 Port 7세그먼트 LED 4 Digit LED * 8 EA Keyboard 스위치 * 8 EA 20 x2 TEXT LCD * 1EA

15 EMPOS-II HW/SW 구성 하드웨어 블럭도

16 소프트웨어 구성 디바이스 모듈 구성 EMPOS-II HW/SW 구성 부트로더 : EMPOS-BOOT v0.1
리눅스 커널 : linux rmk4-pxa2-empx1 파일 시스템 : ramdisk-16m(ext2) GUI : QT/E-2.3.2, Qtopia (jffs) 개발 툴 : GNU Toolkit, Visual Esto 디바이스 모듈 구성 커널 삽입 디바이스 - TFT LCD, PCMIA/CF, PS2 Keyboard, Touch Screen - AC97 Audio, IrDA, FFUART, MMC 등 모듈 형태 디바이스 - SMC91111 Primary/Secondary Ethernet Driver(커널 소스에 포함) - Prism2 Wireless Driver - ide Disk Dirver - Text LCD Driver - LED, Button Driver - 7Segment LED Driver - GPIO Input , Output Driver

17 부트로더 분석(EMPOS-BOOT)

18 일반 리눅스 BootLoader EMPOS
부트로더 분석 일반 리눅스 BootLoader LILO(LInux LOader) 하드 디스크의 MBR에서 동작 여러 O/S를 선택적으로 부팅 EMPOS EMPOS_boot Flash 0 block에서 동작 Linux Booting Command line Kernel/root filesystem을 Downloading Ram에서 Flash로 writing

19 부트로더의 역할 여러 부트로더들 부트로더 분석
hardware 초기화 - Memory setting - CPU Clock setting - GPIO setting - Serial setting - MAC address 획득 및 Ethernet port setting Flash 에서 RAM으로 memory copy - kernel image copy - ramdisk image copy - 부트로더 자신 copy Kernel booting Command mode 제공 포팅의 편의를 위한 Debug 모드 제공 여러 부트로더들 blob, Redboot, ppcboot, armboot, bootldr 등

20 부트로더 분석 부트로더 흐름도

21 부트로더 분석 * 소스 파일 Makefile : make 유틸리티에 사용되는 컴파일 스크립트
start.S : 처음 시작하는 코드로써 래지스터 세팅을 담당한다. main.c : 전체적인 부트로더 시퀀스를 통제한다. commans.c : 몇가지를 제외한 대부분의 명령어를 처리한다. lib.c : 소스에서 사용하는 여러 라이브러리 성격의 함수를 제공한다. flash.c : flash 메모리에 데이터를 저장하는 역할을 한다. serial.c : FFUART 초기화 및 모니터링을 위한 기본 함수를 제공한다. time.c : 부트로더에서 사용하는 타이머를 담당한다. smc91111.c : 네트워크 디바이스파일로써 저수준 네트워크 통신을 담당한다. net.c : bootp, tftp와 smc91111.c와의 중간 다리 역할을 한다. bootp.c : bootp 패킷의 구성과 전달을 담당한다. tftp.c : tftp 패킷의 구성과 전달을 담당한다. * 해더 파일 ld-xscale : 링커 스크립트로 링커의 모듈 결합에 사용된다. bootp.h : bootp.c와 관련된 해더. commands.h : commands.c와 관련된 해더. config.h : 보드의 래지스터 및 환경설정을 담당한다. flash.h : flash.c 와 관련된 해더. header.h : 네트워크 패킷 구성에 사용되는 패킷의 구조를 제공한다. lib.h : lib.c 와 관련된 해더. main.h : main.c 와 관련된 해더. net.h : net.c와 관련된 해더. reg.h : Xscale PXA255와 관련된 여러 래지스터의 주소. serial.h : serial.c와 관련된 해더. smc91111.h : smc91111.c와 관련되 해더. tftp.h : tftp.c와 관련된 해더 time.h : time.c와 관련된 해더 types.h : 변수 타입 및 필요 항목 정의

22 부트로더 분석 매모리 맵

23 부트로더 명령어 부트로더 분석 boot : 램상에 존재하는 커널을 부팅한다.
reset : 롬상에 존재하는 부트로더를 재시작한다. bootp : bootp를 통해 호스트로 부터 IP를 할당 받는다. setip : host와 target의 IP를 설정한다. macwrite : Primary/Secondary Ethernet의 MAC주소를 설정한다. tftp : tftp를 통한 데이터를 전송받는다. download : 시리얼을 통한 데이터를 전송받는다. read : 특정 메모리 위치의 값을 읽어 온다 write : 특정 메모리 위치의 값을 변경 한다. flash : 전송 받은 데이터를 플래쉬에 저장한다. erase : 플래쉬에 저장되어 있는 데이터를 삭제한다. status : 메모리맵/래지스터/이더넷설정등을 출력한다. help : 도움말을 출력한다. test : 사용자 태스트 함수를 제공한다.

24 소스 분석 실습과제 부트로더 분석 Makefile ld-xscale config.h start.S main.c serial.c
부트로더를 컴파일할 툴체인 리눅스 호스트에 설치한다. 처음 출력되는 Copyright 정보에 자신의 정보를 추가한다. IO 초기화 부분을 수정하여, TextLCD 글자를 변경한다. 태스트 함수를 수정해서, 버튼 입력을 출력한다. 수정된 부트로더를 컴파일하여 보드에 포팅한다.

25 리눅스 매모리 관리

26 세그먼트 방식 리눅스 매모리 관리 디스크립터 테이블 세그먼트 세그먼트 셀렉터 프로그램 블가능한 래지스터 2017-02-26

27 세그먼트 디스크립터 세그먼트 디스크립터에 기록된 내용 리눅스 매모리 관리
세그먼트의 특징을 기술하는 8바이트의 디스크립터로 GDT나 LDT에 저장된다. GDT(Global Descriptor Table) : 하나만 존재 LDT(Local Descriptor Table): 프로세스마다 존재 세그먼트 디스크립터에 기록된 내용 세그먼트가 시작하는 선형 주소를 포함한 32비트의 Base 필드 과립도를 나타내는 G플래그(0-> 세그먼트 크기가 Byte, 1-> 4096을 곱한 크기) 세그먼트 길이를 바이트 단위로 나타내는 20 비트 크기의 Limit 필드 (G :0 -> 1부터 1MB, G:1 -> 4KB ~ 4GB) 시스템 플래그 S(S:0 ->커널 자료구조를 포함한 시스템 세그먼트, S:1 -> 일반 코드, 데이터 포함하는 세그먼트) 세그먼트 종류, 접근권한을 나타내는 4비트 Type 필드(0: 커널만이 접근) 코드포함, 데이터 포함을 나타내는 플래그 운영체제가 사용하는 AVL플래그(리눅스에서는 무시)

28 세그먼트 디스크립터의 종류 코드 세그먼트 디스크립터 데이터 세그먼트 디스크립터 작업 상태 세그먼트 디스크립터
리눅스 매모리 관리 세그먼트 디스크립터의 종류 코드 세그먼트 디스크립터 GDT, LDT 모두에 존재 가능, S플래그를 1로 설정한다 데이터 세그먼트 디스크립터 GDT, LDT 모두에 존재 가능, S플래그를 1로설정(ex: 스텍 세그먼트등) 작업 상태 세그먼트 디스크립터 프로세서의 래지스터 상태를 저장하기 위해 사용, GDT에만 존재, S플래그 0 지역 디스크립터 테이블(LDTD) LDT에 포함한 세그먼트의 참조를 나타낸다, GDT에만 존재, S플래그 0

29 리눅스 매모리 관리 세그먼트 셀렉터 논리 주소를 선형 주소로 변환을 위해 사용(세그먼트 래지스터)의 내용이 바뀌었을경우 다음 세그먼트를 찾기위해 사용 세그먼트 셀럭터의 필드 구성 GDT, LTD에 있는 세그먼트 디스크립터 엔트리를 구별하는 인덱스 TI (Table, Indicator) : 세그먼트가 GDT, LTD중 어디에 존재함을 나타낸다(TI:0->GTD, TI:1 -> LTD) 권한 수준(세그먼트가 로드되었을 때 권한수준)

30 패이징 방식 리눅스 매모리 관리 31 22 21 12 11 0 디렉토리 테이블 옵셋 페이지 페이지 디렉토리 페이지 테이블
디렉토리 테이블 옵셋 페이지 페이지 디렉토리 페이지 테이블

31 패이지 디렉토리/테이블 엔트리 구조 리눅스 매모리 관리 10 bit : 1024개의 앤트리 포함 가능
12 bit : 4096 byte 데이터 포함 1024*1024 *4096 =2**32개의 메모리 셀 주소 지정 가능 패이지 디렉토리/테이블 엔트리 구조 Present 플래그 (주메모리에 존재여부) Accessed플래그 (페이지 프래임에 접근할 때마다 1) Dirty 플래그 (썻을 경우:1) Read/Write 플래그(접근 권한) User/Supervisor 플래그(접근 권한 수준, 보호정책) PCD/PWT 플래그 (하드웨어 케시가 페이지 태이블을 다루는 방법 제시) Pase Size 플래그 (페이지 디렉토리 엔트리에만 적용 (1: 페이지프래임은4MB, 확장 패이징)

32 확장 패이징 하드웨어 보호 정책 세그먼트 유닛 패이징 유닛 권한 수준 0 ~ 4 User/Supervisor 접근 권한
리눅스 매모리 관리 확장 패이징 중간 페이지 태이블이 불필요, 메모리 절약 메모리 단편화 하드웨어 보호 정책 세그먼트 유닛 패이징 유닛 권한 수준 0 ~ 4 User/Supervisor 접근 권한 읽기/쓰기/시행 읽기/쓰기

33 커널이 프로세스에게 0x20000000 ~0x2003ffff 까지 선형 주소 공간을 할당을 할 경우
리눅스 매모리 관리 커널이 프로세스에게 0x ~0x2003ffff 까지 선형 주소 공간을 할당을 할 경우 0x2003ffff( ) 0x80, 0x63

34 프로세스가 선형 주소 0x20021406의 값을 읽으려고 할경우 패이징 유닛 처리
리눅스 매모리 관리 프로세스가 선형 주소 0x 의 값을 읽으려고 할경우 패이징 유닛 처리 디렉토리 필드 0x80은 페이지 디렉토리 0x80 엔트리를 선택 (이곳에 패이지 태이블의 위치존재) 테이블 필드 0x21은 페이지 테이블의 0x21째 엔트리 선택 (이곳에 패이지 프래임의 위치 존재) 패이지 프레임의 오프셋 필드 0x406값을 선택 만약 엔트리의 Present 플래그가 0이면 주메모리에 존재 하지 않으므로 패이지 예외 발생

35 페이지 프레임 0 : BIOS가 POST과정에서 인식한 시스템 하드웨어 설정 저장 용도
리눅스 매모리 관리 예약된 페이지 프레임 일반적인 리눅스는 커널을 램의 0x 부터 시작하여 설치하며 이전부분에 해당하는 페이지 프레임은 동적으로 할당되거나 스왑되지 않으며 다음처럼 사용된다. 페이지 프레임 0 : BIOS가 POST과정에서 인식한 시스템 하드웨어 설정 저장 용도 0x000a0000 ~000fffff : BIOS 함수와 ISA 그래픽 카드의 내부 메모리 메핑 용도 프로세스 페이지 테이블 32bit 프로세서에서는 4G의 선형 주소 공간을 가질수 있다 (0x /0x400/0x400/0x400) PAGE_OFFSET 매크로는 0xc 값을 보통 갖는다.(커널 영역과 프로세스 영역 분리)

36 리눅스 프로세스 관리

37 멀티 프로그램 운영체제의 필수 개념으로 실행 상태에 있는 프로그램 인스턴스
리눅스 프로세스 관리 프로세스 멀티 프로그램 운영체제의 필수 개념으로 실행 상태에 있는 프로그램 인스턴스 프로세스 디스크립터 커널이 프로세스의 정보를 사용할수 있도록 프로세스의 모든 정보를 저장한다 state 필드 : 현재의 프로세스 상태 프로세스 ID : pid, pgrp, uid, euid, suid 프로세스 관계 : next_task, next_run, p_optr, p_pptr 파일 정보 : files_struct, fs_struct 시그널 정보 : sigpending, signal, blocked, sigaction 메모리 정보 :mm object, start_code, vm_area-struct,pgd 스케줄링 정보 : semsleeping, semundo 시행 파일 포멧 : personaliy, binfmt 자원 사용량 통계: utime, stime,rlimit

38 리눅스 프로세스 관리 state nead_reched counter priority tty_struct next_task
prev_task next_run prev_run 프로세스완 연관된 tty fs_struct p_optr …….. 현재 디랙토리 files_struct tty 파일 디스크립터 포인터 mm_struct tss 메모리 영역 디스크립터 포인터 signal_struct fs files 수신한 시그널 mm signal_lock sig ……..

39 프로세스 상태 state 필드에서 나타낸다. TASK_RUNNING : 프로세스가 CPU에서실행 중이거나 기다리는 중
리눅스 프로세스 관리 프로세스 상태 state 필드에서 나타낸다. TASK_RUNNING : 프로세스가 CPU에서실행 중이거나 기다리는 중 TASK_INTERRUPIBLE : 프로세스가 인터럽트 가능 대기상태일경우, 기다리던 자원을 할당받거나, 시그널이 전달되면 TASK_RUNNING으로 전위(대기상태) TASK_UNINTERRUPTIBLE : 위와 비슷하지만 프로세스에 시그널을 전달해도 상태가 바뀌지 않는다. 거의 사용X, 장치 파일등을 열고 방해없이 완료해야할경우 사용(대기상태) TASK_STOPPED : SIGSTOP, SIGTSTP, SIGTTIN을 받았을경우 프로세스는 중단 특정프로세스가 다른 프로세스를 감시 할수 있다(디버거의 ptrace()등) TASK_ZOMBIE : 프로세스가 종료되었지만 부모 프로세스가 자식 프로세스의 정보를 가져가지 않을경우

40 TASK_UNINTERRUPTIBLE
리눅스 프로세스 관리 프로세스 상태 전의 Suspended signal ptrace TASK_RUNNING (running) TASK_STOPPED exit TASK_ZOMBIE Resume signal ptrace scheduling sleep on Interruptible_sleep_on preempt wait TASK_RUNNING (ready) TASK_INTERRUPTIBLE TASK_UNINTERRUPTIBLE (asleep) NULL wake_up wake_up_interruptable

41 리눅스 프로세스 관리 PC pid = fork() fork 전 Wait((int*)0) PC execl(“bin/ls”..)

42 #include <unistd.h> int docommand(char * command) { pid_t pid
리눅스 프로세스 관리 #include <unistd.h> int docommand(char * command) { pid_t pid if((pid =fork()) <0) return (-1); if(pid ==0) /* 자식 */ { execl(“/bin/sh”, “sh”, “-c”, command, (char *)0); peror(“execl”); exit(1); } /* 부모의 코드 */ wait((int *)0); return (0);

43 리눅스 프로세스 관리 프로세스 리스트 prev_task init_task next_task
prev_task task next_task …… prev_task task next_task task_struck task_struck task_struck RUNNING RUNNING RUNNING …… RUNNING RUNNING RUNNING Running_queue_head …… current

44 프로세스 종료 리눅스 프로세스 관리 모든 프로세스 종료는 do_exit() 함수가 처리하며 다음과 같은 작업을 한다.
프로세스 디스크립터의 PF_EXITING 플래그를 설정하여 프로세스가 종료중임을 나타냄 필요하면 sem_exit() 함수를 호출하여 세마포어 큐에서 프로세스 디스크립터 제거 필요하면 del_timer() 함수를 호출하여 동적 타이머 큐에서 프로세스 디스크림터 제거 __exit_num(), __exit_files(), __exit_fs(), __exit_sighand()를 호출하여 각각 페이징, 파일시스템, 열린 파일 디스크립터, 시그널 처리등과 관련된 프로세스 자료구조를 점검하여 더 이상 필요없는 자료구조를 제거 프로세스 디스크립터의 state 플래그를 TASK_ZOMBIE로 설정 프로세스 디스크립터의 exit_code 필드를 프로세스 종료 코드로 설정(exit()시스템콜에 넘어온 값이나 커널에 넘겨진 값이다) exit_notify() 함수를 호출하여 부모 프로세스와 자식 프로세스 모두의 친족관계를 갱신, 종료되는 프로세스의 자식은 모두 init 프로세스의 자식이 된다 schedule() 함수를 호출하여 실행할 새로운 프로세스를 선택한다

45 프로세스 제거 리눅스 프로세스 관리 부모 프로세스는 wait()함수를 호출하여 자식 프로세스가 정상적으로 종료되었
는지 알수 있다. release()함수를 호출하여 좀비 프로세스의 프로세스 디스크 립터를 해제한다. free_uid()함수를 호출하여 지금까지 만든 프로세스 개수를 하나 줄인다. add_free_taskslot() 함수를 호출하여 해제하려는 프로세스 디스크립터를 가리키는 task 엔트리를 해제한다. nr_task 변수값을 감소시킨다. uuhash_pio()함수를 호출하여 pidhash 해쉬태이블에서 프로세스 디스크립터를 제거한다. REMOVE_LINKS 매크로를 호출하여 프로세스 목록에서 프로세스 디스크립터를 제거 free_task_struct() 함수를 호출하여 프로세스 디스크립터와 커널 모드 스택으로 사용되었던 8KB 메모리를 해제한다

46 리눅스 커널

47 커널이란 커널의 기능 프로세스 관리(Pocess Management) 메모리 관리(Memory Management)
리눅스 커널 커널이란 운영체제를 구성하고 있는 핵심(core)로써 타겟보드의 시스템 구동에 필요한 환경 설정과 수행되는 프로그램들을 스케줄링하는 소프트웨어이다. 커널의 기능 프로세스 관리(Pocess Management) 메모리 관리(Memory Management) 파일 시스템 관리(File System Management) 디바이스 관리(Device Management) 네트워크 관리(Network Management)

48 리눅스 커널

49 커널 컴파일/포팅 (실습과제) 커널 소스 확보 (linux-2.4.19)
리눅스 커널 커널 컴파일/포팅 (실습과제) 커널 소스 확보 (linux ) arm, pxa, empx 패치 확보 (rmk4-pxa2-empx1) 압축해제, 패치 적용 make empos_config : 컴파일 환경을 EMPOS 보드에 맞게 설정 make oldconfig (menuconfig) : 설정된 환경을 소스에 적용 make dep : 파일 의존성 검사 make clean (make distclean) : 이미 컴파일된 오브젝트 삭제 make zImage : 압축된 커널이미지 생성 make modules : 모듈 형태로 선택된 항목 컴파일(smc91111) 생성된 이미지를 tftp서비스 디랙토리로 복사 tftp zImage kernel (부트로더 명령어) flash kernel (부트로더 명령어) reset (부트로더 명령어)

50 리눅스 파일 시스템

51 리눅스 파일 시스템 파일 시스템이란 디스크의 섹터와 트랙 그리고 실린더 등을 논리적으로 사용하기 위하여, 불록 단위로 읽고 쓰는 메커니즘을 말한다. 파일 시스템의 구조 /root bin boot dev etc home lib mnt proc root tmp usr var sbin user1 user2 include local src

52 파일 시스템의 구조 리눅스 파일 시스템 / : 루트 디렉토리
/boot : 부팅 과정에 필요한 모든 구성 요소들이 포함되어 있다 /bin : 실행 파일이 모여 있다 /dev : 디바이스 드라이버들이 존재 /etc : 리눅스 운영에필요한 설정파일 및 초기화 스크립트등이 저장 /etc/passwd : 사용자 정보를 포함하는 문서 /etc/fstab : mount –a명령으로 마운트되는 파일시스템과 스왑목록 /etc/init : 부팅시 커널의 처음 프로세스 /etc/profile : 쉘에 의해 로그인 할때 실행되는 파일 /home : 사용자의 홈디랙토리 /lib : 공유 라이브러리 모듈 저장 /root : 시스템 관리자인 root의 홈디랙토리 /sbin : 시스템 관리를 위한 실행 유틸리티 저장 /usr : 공유 가능한 대부분의 프로그램 설치

53 리눅스 파일 시스템 ext2 파일시스템의 특성 예상되는 시스템의 평균 파일 크기에 따라 시스템 관리자는 최적의 블록 크기를(1024 ~ 4096바이트) 선택이 가능 저장할 파일수를 예상한 값에 따라 파티션에 대한 아이노드 수를 선택할수 있다.(디스크 공간 최적화) 디스크 불럭을 그룹으로 분할(탐색시간 절약) 파일의 사용 전에 디스크 데이터 블록을 미리 할당(파일 크기 증가시 인접위치에 예약되므로 단편화를 줄일수 있다.) 심볼릭 링크를 지원한다. 시스템 중단으로 인한 영향을 최소화한다. 부트 과정에서 파일 시스템 상태에 대해 일관성 검사를 자도으로 지원 변경 할수 없는 파일, 추가만 가능한 파일등을 지원 어떤 방식의(SVR4: 프로세스 그룹ID, BSD:디랙토리ID 물려 받는다)마운트 옵션 포함

54 디스크 자료 구조 리눅스 파일 시스템 부트불럭 불럭 그룹 0 …… 불럭 그룹 n 그룹 디스크립터 (1) 데이터 블록
비트맵 (1) 아이노드 비트맵 (1) 아이노드 태이블 (n) 수퍼 블록 (1) 데이터 블록 (n)

55 수퍼 블록에 저장 내용 그룹 디스크립터 비트맵 아이노드 테이블 리눅스 파일 시스템
총 아이노드의 수, 파이시스템 크기, 불록 크기, 단편 크기, 그룹당 아이노드수, 마지막 마운트한 시간, 마지막 쓰기 시간등 그룹 디스크립터 각 블록그룹은 자신만의 그룹 디스크립터르 포함하며 다음 정보를 가지고 있다. 불럭 비트맵의 블록번호, 아이노드 비트맵의 블록번호, 그룹안의 아이노드수등 비트맵 비트의 연속으로 값이 0인경우 대응하는 아이노드또는 비트맵이 비었다는 의미 아이노드 테이블 아이노드는 모두 128바이트로 같으며 1024 바이트 블록은 8개 4096 바이트블럭은 32개를 포함하고 아이노드를 나타내는 ext2_inode 구조체는 다음과 같은 정보를 가지고 있다. 파일유형, 접근 권한, 파일 길이, 소유자 식별자, 마지막 접근 시간, 아이노드 마지막 변경시간, 하드링크의 수등

56 1) BIOS가 시스템 이상여부 태스트 -> 부트로더에서 수행
리눅스 파일 시스템 리눅스의 부팅 과정 1) BIOS가 시스템 이상여부 태스트 -> 부트로더에서 수행 2) 부팅할 드라이브 선택 -> 커널의 플래쉬 위치 선택 3) 선택된 드라이브의 MBR읽어 드림 ->수행 불필요 4) MBR의 파티션 태이블을 읽어 부팅할 파티션을 선택 -> 수행 불필요 5) 커널 로드 -> 커널을 램상으로 복사 6) 커널 압축 해제/ 재배치 7) 장착된 하드웨어 검사, 장치 드라이버 설정 8) 파일 시스템 검사 -> 램디스크, jffs이미지에 포함 9) 파일 시스템 마운트 10) /etc/inittab에서 init실행을 위한 설정 내용 확인 11) /sbin/init 실행(PID가 1이됨) 12) /etc/rc.d/rc.sysinit실행(hostname,시스테 점검, 모듈 로딩) 13) /etc/rc.d/rc실행 (runlevel에 따른 스크립트 실행) 14) /etc/rc.d/rc.local(매번 실행할 내용 입력) 15) /etc/rc.d/rc.serial (시리얼 포트 초기화) 16) login

57 리눅스 파일 시스템 램디스크 램디스크 생성 dd if=/dev/zero of=./empos.ramdisk.fs count=4096 bs=1024 mkfs -t ext2 empos.ramdisk.fs 램디스크 수정 - gunzip ramdisk-16m.gz - mount –oloop ramdisk-16m dir_name JFFS mkfs.jffs2 -o usr.jffs -e 0x r tmpdir

58 개발 환경 설치

59 개발 프로그램 설치 필요한 rpm 설치 -minicom, bootp, tftp, 설치 GNU 툴체인설치
개발 환경 설치 개발 프로그램 설치 필요한 rpm 설치 -minicom, bootp, tftp, 설치 GNU 툴체인설치 - cross-tools.tgz를 /usr에 해제후 패스설정 Visual ESTO 설치 - 압축해제후 ./install.sh 실행 기타 프로그램 - gcc , tmake, mkfs.jffs2 등

60 minicom 환경 설정(minicom –s)
개발 환경 설치 minicom 환경 설정(minicom –s) Serial port setup - A 항목을 /dev/ttyS0로 바꾼다. - E 항목을 N1으로 바꾼다 - F, G 항목을 No로 설정한다

61 bootp 환경 설정 /etc/bootptab /etc/hosts 개발 환경 설치 .default:\
:hd=/tftpboot:bf=null:\ :sm= empos :ht=1:ha=0x000B8A000001:tc=.default empos.hanback.co.kr empos

62 bootp 환경 설정 service bootps { /etc/xinetd.d/bootp disable =no
개발 환경 설치 bootp 환경 설정 /etc/xinetd.d/bootp service bootps { disable =no flags =REUSE NAMEINARGS socket_type =dgram protocol =udp wait =yes user =root server =/usr/sbin/bootpd server_args =-s }

63 tftp 환경 설정 service tftp { /etc/xinetd.d/tftp disable =no
개발 환경 설치 tftp 환경 설정 /etc/xinetd.d/tftp service tftp { disable =no socket_type =dgram protocol =udp wait =yes user =root server =/usr/sbin/in.tftpd server_args =-s /tftpboot }

64 nfs 환경 설정 /nfs_resource 192.168.123.200 (rw, no_root_squash)
개발 환경 설치 nfs 환경 설정 /etc/exports /nfs_resource (rw, no_root_squash)

65 응용프로그램

66 컴파일 방법 간단한 프로그램 작성 응용 프로그램
크로스 컴파일 툴 체인이 설치한 후 기존의 Makefile안에서 컴파일 명령어 “xxx”를 arm-linux-xxx로 바꾸어 주면된다. 단순한 하나의 파일을 컴파일하기 위해선 “arm-linux-gcc –o hello hello.c” 사용할 수도 있다. 간단한 프로그램 작성 #include <stdio.h> int main(void) { printf(“Hello Embedded World\n”); return 0; }

67 hello.c 컴파일 방법 파일 타입 file ./hello
응용 프로그램 hello.c 컴파일 방법 gcc –o hello hello.c (i386에서) arm-linux-gcc –o hello hello.c (arm에서) 파일 타입 실행 파일을 파일 타입을 살펴 봄으로서 어뗜 CPU에서 동작되는지를 알수있다. file ./hello hello: ELF 32-bit LSB executable, ARM, version 1 (ARM), for GNU/LINUX ,Dynamically linked (used shared libs), not stripped

68 int munmap(void *start, size_t length);
응용 프로그램 mmap(), munmap() 함수 파일이나 장치 디바이스를 메모리에 메핑시키는 함수 즉 열린 파일 기술자를 통해 액세스되는 파일의 내용과 관련된 메모리의 구역에 대한 포인터를 생성한다. mmap(), munmap()함수의 원형은 다음과 같다. void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset) int munmap(void *start, size_t length); start : 특정 메모리 어드레스를 요청하기위해서 length : 메모리 세그먼트의 길이 설정 offset : 파일 데이터의 시작을 변경 fd : 파일 기술자

69 Flags : 페이지에 가해지는 변경이 다른 곳에 반영되는 방법을 설정한다.
응용 프로그램 prot : 메모리 보호모드를 설정한다. PROT_READ : 페이지 읽기 허락 PROT_WRITE : 페이지 쓰기 허락 PROT_EXEC : 페이지 실행 PROT_NONE : 페이지 접근 불가 Flags : 페이지에 가해지는 변경이 다른 곳에 반영되는 방법을 설정한다. MAP_PRIVATE : 다른 프로세스와 대응 영역을 공유하지않는다. MAP_FIXED : 지정된 주소 이외의 다른 주소를 선택하지 않는다. MAP_SHARED: 객체에 대응 시키는 다른 프로세스와 대응 영역 을 공유한다.

70 응용 프로그램에서 I/O를 제어하기위한 방법
open 함수를 사용하여 열린 기술자 획득한다. mmap()함수를 사용하여 제어할 I/O의 포인터 획득한다. 포인터에서 값을 읽거나 원하는 값을 쓴다. munmap()함수를 사용하여 메모리 공간 해제한다. close()함수를 이용하여 열린 기술자 반환한다. fd = open(“/dev/mem”,O_RDWR); addr = mmap(NULL,1,PROT_WRITE,MAP_SHARED,fd,ADDRESSOFLED); addr = 0xaa; munmap(addr,1); close(fd)

71 응용 프로그램 분석 “Hello world” 출력 프로그램 Led/button 제어 프로그램
웹을 통한 led출력 cgi프로그램 웹을 통한 7egment 출력 cgi 프로그램 웹을 통한 text LCD 출력 프로그램

72 디바이스 드라이버

73 디바이스 드라이버

74 문자 디바이스(character device)
디바이스 드라이버 문자 디바이스(character device) 파일 시스템에서 노드 형태로 존재 대부분 순차적인 접근만을 허용 블록 디바이스(block device) 버퍼를 이용하여 파일 시스템의 구축이 가능 대부분 정해진 크기의 블록 단위의 데이터 이동 네트워크 디바이스(network device) 파일 형태가 아닌 특별한 인터페이스 사용 스트림 기반이 아닌 패킷 단위의 접근

75 디바이스 파일(device file) 디바이스 파일의 생성 : mknod 주번호와 부번호 디바이스 드라이버를 접근하는 통로
장치 파일의 inode는 장치 유형(type),주번호(major number), 부번호(minor number)로 구성된다. 디바이스 파일의 생성 : mknod Mknod /dev/file_name [c|b] major_number minor_number 주번호와 부번호 주번호 : 커널이 디바이스와 연관된 드라이버를 구분하는 데 사용 부번호 : 드라이버가 각 디바이스를 구분하는 데 이용

76 문자형 디바이스의 골격 디바이스 드라이버 #include <linux/kernel.h>
#include <linux/module.h> #include <linux/init.h> Header Files int device_open( … ) { … } int device_release( … ) { … } ssize_t device_write( … ) { … } ssize_t device_read( … ) { … } Function Prototypes static struct file_operations device_fops = { ssize_t (*read) (…); ssize_t (*write) (…); int (*open) (…); int (*release) (…); }; File Operation int init_module(void) { … } 모듈 설치시 초기화 수행 void cleanup_module(void) { … } 모듈 제거시반환 작업수행

77 디바이스 드라이버 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); };

78 read(), write(), ioctl(), …
디바이스 드라이버 init_module() 디바이스 드라이버 등록 메모리 할당 및 초기화 cleanup_module() 디바이스 드라이버 제거 할당된 I/O메모리 영역 반환 open(), release() 디바이스 카운트 증가 및 감소 usage 카운트 체크 및 증가 감소 read(), write(), ioctl(), … 디바이스 드라이버의 목적에 따른 일을 함 사용자 공간과 커널공간의 테이터 전송 메모리에 값을 쓰거나 읽음

79 포인터를 사용 포인터는 곧 번지이다. 포인터을 이용하여 값을 쓰는 방법 포인터을 이용하여 값을 읽는 방법 디바이스 드라이버
unsigned char *addr; addr = (unsigned char *)(0xf ); *addr = 0xaa; 포인터을 이용하여 값을 읽는 방법 unsigned char *addr; char ch; addr = (unsigned char *)(0xf ); ch = *addr;

80 C에서 제공되는 함수를 사용 메모리로부터 값을 읽는 함수 _u8 inb(unsigned int port);
디바이스 드라이버 C에서 제공되는 함수를 사용 메모리로부터 값을 읽는 함수 _u8 inb(unsigned int port); _u16 inw(unsigned int port); _u32 inl(unsigned int port); 메모리에 값을 쓰는 함수 void outb(_u8 data, unsigned int port); void outw(_u16 data, unsigned int port); void outl(_u32 data, unsigned int port);

81 모듈에서 사용하는 테이터 전송함수 get_user(void *x, const void *addr)
디바이스 드라이버 모듈에서 사용하는 테이터 전송함수 get_user(void *x, const void *addr) *addr의 값을 커널 영역인 x로 sizeof(addr)만큼 복사한다. put_user(void *x, const void *addr) *x의 값을 user영역인 addr로 sizeof(addr)만큼 복사한다. copy_to_user(void *to, void *from, unsigned long size) copy_from_user(void *to, void *from, unsigned long size)

82 디바이스 드라이버를 컴파일 하기위해서는 일반 어플리케이션 컴파일 방법에 약간의 옵션들을 추가 하면 된다.
다음은 디바이스 드라이버를 컴파일하기위한 기본적인 과정이다 $ arm-linux-gcc -D__KERNEL__ -DMODULE -I/working/kernel/linux /include -Wall -O2 –o driver.o –c driver.c __KERNEL__ : 헤더파일에게 이소스가 사용자 모드가 아닌커널 모드로에서 실행된다는 것을 알려준다. - MODULE : 헤더 파일에게 이 코드가 모듈임을 알려준다.

83 디바이스 드라이버 디바이스 드라이버를 커널에 로딩하는 방법 디바이스 드라이버의 리스트를 보는 방법
$ insmod driver.o 디바이스 드라이버의 리스트를 보는 방법 $ lsmod 디바이스 드라이버를 커널에서 제거하는 방법 $ rmmod driver 디바이스 파일을 만드는 방법 아래와 같은 명령을 이용하여 디바이스 드라이버를 커널에 삽입한다. insmod driver.o 여기서 driver.o는 테스트로 작성된 디바이스 드라이버 파일명이다. 위와 같이 콘솔에서 insmod driver.o를 실행 시키면 다음과 같은 시스템콜이 타겟 보스의 커널에서 수행 되어 드라이버를 커널에 삽입한다. (1)sys_create_module()을 사용하여 디바이스 드라이버를 적재하기 위한 매모리를 활당한다. (2)sys_get_kernel_syms()를 이용하여 driver.o안에 있는 심볼을 커널에 등록한다. (3)마지막으로 sys_init_module()을 사용하여 driver.o를 메모리에 적재한다. 이 과정에서 driver.o안에 있는 init_module()이 실행되고 그 안에 있는 커널 함수인 register_chrdev()가 수행되어 디바이스 드라이버 이름과 메이저 번호와 file_operations 구조체를 커널 변수인 chrdevs에 등록한다. 위와 같이 디바이스 드라이버를 커널에 삽입했으면 다음 해야 하는 일은 드라이버에 대응하는 특수 장치 파일(노드)을 만드는 일이다. 다음은 콘솔에서 특수 장치 파일을 만드는 명령이다. mknod /dev/device c 주번호 부번호 위의 명령에 의해 커널에서 수행 되는 일은 다음과 같다. mknod 명령은 커널의 sys_mknod()를 호출하고 이 함수는 다음과 같은 일을 수행한다. (1)먼저 /(루트)에서 시작해서 dev 디렉트리까지의 경로를 찾아 ledioport라는 이름의 dentry를 만들고 루트에 연결한다. (2)inode 하나를 만들고 dentry의 d_inode에 연결한다. (3)inode의 i_mode와 i_rdev에 S_IFCHR 과 (주번호<<8|부번호)을 기록한다. (4)inode의 i_fop에 def_chr_fops의 주소값을 기록하여 이를 통해 open메소드에 chrdev_open()이 연결되도록 한다. 위와 같이 커널에 디바이스 드라이버를 삽입하고 이것에 대응하는 특수장치 파일을 만들어야 어플리케이션의 디바이스 드라이버 사용이 가능하다. $ mknod /dev/driver c 주번호 부번호

84 응용프로그램에서 디바이스 드라이버를 사용하는 방법
1. open함수를 이용하여 특수 장치 파일을 연다. dev = open(“/dev/device”,O_WRONLY); 2. 디바이스 드라이버에서 제공하는 함수를 이용하여 디바이스를 제어한다. write(dev,&buff,1); 3. close함수를 이용하여 특수 장치 파일을 닫는다. 아래와 같은 명령을 이용하여 디바이스 드라이버를 커널에 삽입한다. insmod driver.o 여기서 driver.o는 테스트로 작성된 디바이스 드라이버 파일명이다. 위와 같이 콘솔에서 insmod driver.o를 실행 시키면 다음과 같은 시스템콜이 타겟 보스의 커널에서 수행 되어 드라이버를 커널에 삽입한다. (1)sys_create_module()을 사용하여 디바이스 드라이버를 적재하기 위한 매모리를 활당한다. (2)sys_get_kernel_syms()를 이용하여 driver.o안에 있는 심볼을 커널에 등록한다. (3)마지막으로 sys_init_module()을 사용하여 driver.o를 메모리에 적재한다. 이 과정에서 driver.o안에 있는 init_module()이 실행되고 그 안에 있는 커널 함수인 register_chrdev()가 수행되어 디바이스 드라이버 이름과 메이저 번호와 file_operations 구조체를 커널 변수인 chrdevs에 등록한다. 위와 같이 디바이스 드라이버를 커널에 삽입했으면 다음 해야 하는 일은 드라이버에 대응하는 특수 장치 파일(노드)을 만드는 일이다. 다음은 콘솔에서 특수 장치 파일을 만드는 명령이다. mknod /dev/device c 주번호 부번호 위의 명령에 의해 커널에서 수행 되는 일은 다음과 같다. mknod 명령은 커널의 sys_mknod()를 호출하고 이 함수는 다음과 같은 일을 수행한다. (1)먼저 /(루트)에서 시작해서 dev 디렉트리까지의 경로를 찾아 ledioport라는 이름의 dentry를 만들고 루트에 연결한다. (2)inode 하나를 만들고 dentry의 d_inode에 연결한다. (3)inode의 i_mode와 i_rdev에 S_IFCHR 과 (주번호<<8|부번호)을 기록한다. (4)inode의 i_fop에 def_chr_fops의 주소값을 기록하여 이를 통해 open메소드에 chrdev_open()이 연결되도록 한다. 위와 같이 커널에 디바이스 드라이버를 삽입하고 이것에 대응하는 특수장치 파일을 만들어야 어플리케이션의 디바이스 드라이버 사용이 가능하다. close(dev);

85 디바이스 드라이버 Hello 디바이스 드라이버 Init_module(), cleanup_module()
printk문을 이용하여 콘솔에 어떤 함수가 실행되는지 알려준다. hello.c #include <linux/module> #include <linux/kernel.h> #include <linux/init.h> int init_module(void) { printk(“Hello, Kernel!\n”); } void cleanup_module(void) { printk(“Good-bye, Kernel!\n”); 아래와 같은 명령을 이용하여 디바이스 드라이버를 커널에 삽입한다. insmod driver.o 여기서 driver.o는 테스트로 작성된 디바이스 드라이버 파일명이다. 위와 같이 콘솔에서 insmod driver.o를 실행 시키면 다음과 같은 시스템콜이 타겟 보스의 커널에서 수행 되어 드라이버를 커널에 삽입한다. (1)sys_create_module()을 사용하여 디바이스 드라이버를 적재하기 위한 매모리를 활당한다. (2)sys_get_kernel_syms()를 이용하여 driver.o안에 있는 심볼을 커널에 등록한다. (3)마지막으로 sys_init_module()을 사용하여 driver.o를 메모리에 적재한다. 이 과정에서 driver.o안에 있는 init_module()이 실행되고 그 안에 있는 커널 함수인 register_chrdev()가 수행되어 디바이스 드라이버 이름과 메이저 번호와 file_operations 구조체를 커널 변수인 chrdevs에 등록한다. 위와 같이 디바이스 드라이버를 커널에 삽입했으면 다음 해야 하는 일은 드라이버에 대응하는 특수 장치 파일(노드)을 만드는 일이다. 다음은 콘솔에서 특수 장치 파일을 만드는 명령이다. mknod /dev/device c 주번호 부번호 위의 명령에 의해 커널에서 수행 되는 일은 다음과 같다. mknod 명령은 커널의 sys_mknod()를 호출하고 이 함수는 다음과 같은 일을 수행한다. (1)먼저 /(루트)에서 시작해서 dev 디렉트리까지의 경로를 찾아 ledioport라는 이름의 dentry를 만들고 루트에 연결한다. (2)inode 하나를 만들고 dentry의 d_inode에 연결한다. (3)inode의 i_mode와 i_rdev에 S_IFCHR 과 (주번호<<8|부번호)을 기록한다. (4)inode의 i_fop에 def_chr_fops의 주소값을 기록하여 이를 통해 open메소드에 chrdev_open()이 연결되도록 한다. 위와 같이 커널에 디바이스 드라이버를 삽입하고 이것에 대응하는 특수장치 파일을 만들어야 어플리케이션의 디바이스 드라이버 사용이 가능하다.

86 디바이스 드라이버 Makefile CC = arm-linux-gcc
KERNELDIR = /working/kernel/linux rmk4-pax2-empx1 INCLUDEDIR = -I$(KERNELDIR)/include –I./ CFLAGS = -D__KERNEL__ -DMODULE –Wall –O2 –I$(INCLUDEDIR) MODULE_OBJS = hello.o MODULE_SRCS = hello.c $(MODULE_OBJS) : $(CC) $(CFLAGS) –c $(MODULE_SRCS) clean: rm –f *.o 아래와 같은 명령을 이용하여 디바이스 드라이버를 커널에 삽입한다. insmod driver.o 여기서 driver.o는 테스트로 작성된 디바이스 드라이버 파일명이다. 위와 같이 콘솔에서 insmod driver.o를 실행 시키면 다음과 같은 시스템콜이 타겟 보스의 커널에서 수행 되어 드라이버를 커널에 삽입한다. (1)sys_create_module()을 사용하여 디바이스 드라이버를 적재하기 위한 매모리를 활당한다. (2)sys_get_kernel_syms()를 이용하여 driver.o안에 있는 심볼을 커널에 등록한다. (3)마지막으로 sys_init_module()을 사용하여 driver.o를 메모리에 적재한다. 이 과정에서 driver.o안에 있는 init_module()이 실행되고 그 안에 있는 커널 함수인 register_chrdev()가 수행되어 디바이스 드라이버 이름과 메이저 번호와 file_operations 구조체를 커널 변수인 chrdevs에 등록한다. 위와 같이 디바이스 드라이버를 커널에 삽입했으면 다음 해야 하는 일은 드라이버에 대응하는 특수 장치 파일(노드)을 만드는 일이다. 다음은 콘솔에서 특수 장치 파일을 만드는 명령이다. mknod /dev/device c 주번호 부번호 위의 명령에 의해 커널에서 수행 되는 일은 다음과 같다. mknod 명령은 커널의 sys_mknod()를 호출하고 이 함수는 다음과 같은 일을 수행한다. (1)먼저 /(루트)에서 시작해서 dev 디렉트리까지의 경로를 찾아 ledioport라는 이름의 dentry를 만들고 루트에 연결한다. (2)inode 하나를 만들고 dentry의 d_inode에 연결한다. (3)inode의 i_mode와 i_rdev에 S_IFCHR 과 (주번호<<8|부번호)을 기록한다. (4)inode의 i_fop에 def_chr_fops의 주소값을 기록하여 이를 통해 open메소드에 chrdev_open()이 연결되도록 한다. 위와 같이 커널에 디바이스 드라이버를 삽입하고 이것에 대응하는 특수장치 파일을 만들어야 어플리케이션의 디바이스 드라이버 사용이 가능하다.

87 디바이스 드라이버 드라이버 컴파일 드라이버 수행 $make $insmod hello.o Using hello.o
Hello, Kernel! $lsmod Module size Used by hello (unsed) $rmmod hello Good-bye, Kernel! 아래와 같은 명령을 이용하여 디바이스 드라이버를 커널에 삽입한다. insmod driver.o 여기서 driver.o는 테스트로 작성된 디바이스 드라이버 파일명이다. 위와 같이 콘솔에서 insmod driver.o를 실행 시키면 다음과 같은 시스템콜이 타겟 보스의 커널에서 수행 되어 드라이버를 커널에 삽입한다. (1)sys_create_module()을 사용하여 디바이스 드라이버를 적재하기 위한 매모리를 활당한다. (2)sys_get_kernel_syms()를 이용하여 driver.o안에 있는 심볼을 커널에 등록한다. (3)마지막으로 sys_init_module()을 사용하여 driver.o를 메모리에 적재한다. 이 과정에서 driver.o안에 있는 init_module()이 실행되고 그 안에 있는 커널 함수인 register_chrdev()가 수행되어 디바이스 드라이버 이름과 메이저 번호와 file_operations 구조체를 커널 변수인 chrdevs에 등록한다. 위와 같이 디바이스 드라이버를 커널에 삽입했으면 다음 해야 하는 일은 드라이버에 대응하는 특수 장치 파일(노드)을 만드는 일이다. 다음은 콘솔에서 특수 장치 파일을 만드는 명령이다. mknod /dev/device c 주번호 부번호 위의 명령에 의해 커널에서 수행 되는 일은 다음과 같다. mknod 명령은 커널의 sys_mknod()를 호출하고 이 함수는 다음과 같은 일을 수행한다. (1)먼저 /(루트)에서 시작해서 dev 디렉트리까지의 경로를 찾아 ledioport라는 이름의 dentry를 만들고 루트에 연결한다. (2)inode 하나를 만들고 dentry의 d_inode에 연결한다. (3)inode의 i_mode와 i_rdev에 S_IFCHR 과 (주번호<<8|부번호)을 기록한다. (4)inode의 i_fop에 def_chr_fops의 주소값을 기록하여 이를 통해 open메소드에 chrdev_open()이 연결되도록 한다. 위와 같이 커널에 디바이스 드라이버를 삽입하고 이것에 대응하는 특수장치 파일을 만들어야 어플리케이션의 디바이스 드라이버 사용이 가능하다.

88 디바이스 드라이버 EMPOSII에 커널에(linux rmk4-pax2-empx1/arch/arm/mach-pax/empos_x255.x)설정된 디바이스의 가상 메모리 맵 static struct map_desc empos_x255_io_desc[] __initdata = { /* virtual physical length domain r w c b */ {0xf , 0x , 0x , DOMAIN_IO, 0, 1, 0, 0}, /* empos status flash block*/ {0xf , 0x , 0x , DOMAIN_IO, 0, 1, 0, 0 }, /* pcmcia status */ {0xf , 0x , 0x , DOMAIN_IO, 0, 1, 0, 0 }, /*nport */ {0xf , 0x , 0x , DOMAIN_IO, 1, 1, 0, 0}, /*7 Segment */ {0xf , 0x , 0x , DOMAIN_IO, 1, 1, 0, 0}, /*7 Segment */ {0xf , 0x , 0x , DOMAIN_IO, 0, 1, 0, 0}, /*Push button */ {0xf , 0x , 0x , DOMAIN_IO, 1, 1, 0, 0}, /* LED */ {0xf , 0x , 0x , DOMAIN_IO, 1, 1, 0, 0}, /*Text LCD */ {0xf , 0x , 0x , DOMAIN_IO, 0, 1, 0, 0}, /* Primary ETHERNET */ { 0xf , 0x , 0x , DOMAIN_IO, 0, 1, 0, 0 }, /* Secondary ETHERNET */ LAST_DESC };

89 디바이스 드라이버 EMPOSII의 LED의 회로 구성도 콘트롤 레지스터의 데이터 비트의 구조
74HC373은 D-type Latch이어서 테이터를 항상 가지고 있다.

90 디바이스 드라이버 프로그램 구조 init_module(), cleanup_module() 디바이스 드라이버 등록 및 해제
I/O 메모리 활당 및 해제 open(), release() 디바이스 카운트 증가 및 감소 usage 카운트에 따른 디바이스 접근 방식 write() get_user()함수를 이용하여 사용자 공간의 데이터를 전송 전송 받은 데어터를 LED에 적용시킴 아래와 같은 명령을 이용하여 디바이스 드라이버를 커널에 삽입한다. insmod driver.o 여기서 driver.o는 테스트로 작성된 디바이스 드라이버 파일명이다. 위와 같이 콘솔에서 insmod driver.o를 실행 시키면 다음과 같은 시스템콜이 타겟 보스의 커널에서 수행 되어 드라이버를 커널에 삽입한다. (1)sys_create_module()을 사용하여 디바이스 드라이버를 적재하기 위한 매모리를 활당한다. (2)sys_get_kernel_syms()를 이용하여 driver.o안에 있는 심볼을 커널에 등록한다. (3)마지막으로 sys_init_module()을 사용하여 driver.o를 메모리에 적재한다. 이 과정에서 driver.o안에 있는 init_module()이 실행되고 그 안에 있는 커널 함수인 register_chrdev()가 수행되어 디바이스 드라이버 이름과 메이저 번호와 file_operations 구조체를 커널 변수인 chrdevs에 등록한다. 위와 같이 디바이스 드라이버를 커널에 삽입했으면 다음 해야 하는 일은 드라이버에 대응하는 특수 장치 파일(노드)을 만드는 일이다. 다음은 콘솔에서 특수 장치 파일을 만드는 명령이다. mknod /dev/device c 주번호 부번호 위의 명령에 의해 커널에서 수행 되는 일은 다음과 같다. mknod 명령은 커널의 sys_mknod()를 호출하고 이 함수는 다음과 같은 일을 수행한다. (1)먼저 /(루트)에서 시작해서 dev 디렉트리까지의 경로를 찾아 ledioport라는 이름의 dentry를 만들고 루트에 연결한다. (2)inode 하나를 만들고 dentry의 d_inode에 연결한다. (3)inode의 i_mode와 i_rdev에 S_IFCHR 과 (주번호<<8|부번호)을 기록한다. (4)inode의 i_fop에 def_chr_fops의 주소값을 기록하여 이를 통해 open메소드에 chrdev_open()이 연결되도록 한다. 위와 같이 커널에 디바이스 드라이버를 삽입하고 이것에 대응하는 특수장치 파일을 만들어야 어플리케이션의 디바이스 드라이버 사용이 가능하다.

91 디바이스 드라이버 GPIO란 General Purpose Input/Output pins으로 입력이나 출력으로 프그그램 되거나 인터럽트 소스로 사용될 수 있다. - GPIO 기능별 레지스터 정리 심벌 기능 GPLR GPIO 포트 핀의 상태를 보여준다. GPDR GPIO 포트 핀의 방향을 설정한다. GPSR GPIO 포트 핀이 output일 때 해당 비트를 셋 한다. GPCR output 핀이 셋 된 것을 clear한다 GRER GPIO 포트 핀이 input일 때 rising-edge를 감지한다. GFER GPIO 포트 핀이 input일 때 falling-edge를 감지한다. GEDR GRER이나 GFER로 설정된 값에 따른 결과를 설정한다. GAFR GPIO 핀을 alternate function로 전환한다. GPIO(General Purpose Input/Output)란 28개로 이루어진 port pins으로 어플리케이션의 목적에 따라 input이나 output의 신호를 발생하거나 획득을 원할 목적으로 사용되는 것이다. 전체 28개의 GPIO를 위한 GPIO port pin이 존재하며, 각각의 pin은 input이나 output으로 프로그램 되거나 혹은 인터럽트 소스로 사용될 수 있다. - GPIO에 관련한 레지스터 물리적 어드레스심벌기능0x GPLRGPIO 포트 핀의 상태를 보여준다.0x GPDRGPIO 포트 핀의 방향을 설정한다.0x GPSRGPIO 포트 핀이 output일 때 해당 비트를 셋한다.0x CGPCRoutput 핀이 셋된 것을 clear한다0x GRERGPIO 포트 핀이 input일 때 rising-edge를 감지한다.0x GFERGPIO 포트 핀이 input일 때 falling-edge를 감지한다.0x GEDRGRER이나 GFER로 설정된 값에 따른 결과를 설정한다.0x CGAFRGPIO 핀을 alternate function으로 전환한다. 위의 GPIO를 사용하기 위한 방법은 다음과 같다. GPDR로 포트 핀의 방향을 설정한다. 포트 핀의 방향을 output으로 설정했을 때는 GPSR로 해당 비트를 셋하거나 GPCR로 셋된 포트 핀을 0으로 만든다. 포트 핀의 방향이 input으로 설정되었을 때는 GEDR로 해당 비트의 값을 읽을 수 있다. 다음으로 이 GPIO핀을 통하여 인터럽트를 받아 보는 설명이다. 인터럽트란 장치가 디바이스 드라이버의 주의를 끌고 어떻게 동작할 필요가 있는지 알려주는 방법이므로 장치 디바이스 드라이버를 만들기 위한 중요한 부분 중에 하나이다. 프로그램에서 인터럽트를 받는 방법은 아래와 같다. request_irq()를 이용하여 자신만의 irq를 요청한다. set_GPIO_IRQ_edge()를 이용하여 GPIO 포트번호와 감지할 상태를 설정한다. enable_irq()로 인터럽트를 활성화 시킨다. 모든 사용이 끝났을 때 disable_irq()와 free_irq()를 사용하여 irq를 제거한다. 현재 타겟 보드에는 GPIO포트의 0번이 LCD의 오른쪽 맨 아래에 있는 핀이고 나머지는 네트워크 쪽이나 LCD쪽으로 빠져나가 있다. 여기서는 이 GPIO0번을 이용하여 인터럽트를 감지하는 디바이스 드라이버를 만들기 위해 아래와 같이 소스 파일을 작성한다.

92 디바이스 드라이버 - GPIO 레지스터 정리 Register type GPIO[31:0] GPIO[63:32]
GPLR GPLR0 GPLR1 GPLR2 GPSR GPSR0 GPSR1 GPSR2 GPCR GPCR0 GPCR1 GPCR2 GPDR GPDR0 GPDR1 GPDR2 GRER GRER0 GRER1 GRER2 GFER GFER0 GFER1 GFER2 GEDR GEDR0 GEDR1 GEDR2 GAFR GAFR0_U GAFR0_L GAFR1_U GAFR1_L GAFR2_U GAFR2_L GPIO(General Purpose Input/Output)란 28개로 이루어진 port pins으로 어플리케이션의 목적에 따라 input이나 output의 신호를 발생하거나 획득을 원할 목적으로 사용되는 것이다. 전체 28개의 GPIO를 위한 GPIO port pin이 존재하며, 각각의 pin은 input이나 output으로 프로그램 되거나 혹은 인터럽트 소스로 사용될 수 있다. - GPIO에 관련한 레지스터 물리적 어드레스심벌기능0x GPLRGPIO 포트 핀의 상태를 보여준다.0x GPDRGPIO 포트 핀의 방향을 설정한다.0x GPSRGPIO 포트 핀이 output일 때 해당 비트를 셋한다.0x CGPCRoutput 핀이 셋된 것을 clear한다0x GRERGPIO 포트 핀이 input일 때 rising-edge를 감지한다.0x GFERGPIO 포트 핀이 input일 때 falling-edge를 감지한다.0x GEDRGRER이나 GFER로 설정된 값에 따른 결과를 설정한다.0x CGAFRGPIO 핀을 alternate function으로 전환한다. 위의 GPIO를 사용하기 위한 방법은 다음과 같다. GPDR로 포트 핀의 방향을 설정한다. 포트 핀의 방향을 output으로 설정했을 때는 GPSR로 해당 비트를 셋하거나 GPCR로 셋된 포트 핀을 0으로 만든다. 포트 핀의 방향이 input으로 설정되었을 때는 GEDR로 해당 비트의 값을 읽을 수 있다. 다음으로 이 GPIO핀을 통하여 인터럽트를 받아 보는 설명이다. 인터럽트란 장치가 디바이스 드라이버의 주의를 끌고 어떻게 동작할 필요가 있는지 알려주는 방법이므로 장치 디바이스 드라이버를 만들기 위한 중요한 부분 중에 하나이다. 프로그램에서 인터럽트를 받는 방법은 아래와 같다. request_irq()를 이용하여 자신만의 irq를 요청한다. set_GPIO_IRQ_edge()를 이용하여 GPIO 포트번호와 감지할 상태를 설정한다. enable_irq()로 인터럽트를 활성화 시킨다. 모든 사용이 끝났을 때 disable_irq()와 free_irq()를 사용하여 irq를 제거한다. 현재 타겟 보드에는 GPIO포트의 0번이 LCD의 오른쪽 맨 아래에 있는 핀이고 나머지는 네트워크 쪽이나 LCD쪽으로 빠져나가 있다. 여기서는 이 GPIO0번을 이용하여 인터럽트를 감지하는 디바이스 드라이버를 만들기 위해 아래와 같이 소스 파일을 작성한다.

93 디바이스 드라이버 GPIO를 사용하기 위한 방법 GPDR로 포트 핀의 방향 설정한다.
포트 핀의 방향을 출력으로 설정했을 때는 GPSR로 해당 비트를 셋하거나 GPCR로 셋된비트를 clear한다. 포트 핀의 방향을 입력으로 설정했을 때는 GEDR로 해당 비트 값을 읽을 수 있다. GPIO핀을 통해 인터럽트를 받는 방법 request_irq()를 이용하여 자신만의 irq를 요청한다. Set_GPIO_IRQ_edge()를 이용하여 GPIO 포트번호와 감지할 상태를 설정한다. Enable_irq로 인터럽트를 활성화 시킨다. 모든 사용이 끝났을 때 disable_irq()와 free_irq()를 사용하여 irq를 제거한다. GPIO(General Purpose Input/Output)란 28개로 이루어진 port pins으로 어플리케이션의 목적에 따라 input이나 output의 신호를 발생하거나 획득을 원할 목적으로 사용되는 것이다. 전체 28개의 GPIO를 위한 GPIO port pin이 존재하며, 각각의 pin은 input이나 output으로 프로그램 되거나 혹은 인터럽트 소스로 사용될 수 있다. - GPIO에 관련한 레지스터 물리적 어드레스심벌기능0x GPLRGPIO 포트 핀의 상태를 보여준다.0x GPDRGPIO 포트 핀의 방향을 설정한다.0x GPSRGPIO 포트 핀이 output일 때 해당 비트를 셋한다.0x CGPCRoutput 핀이 셋된 것을 clear한다0x GRERGPIO 포트 핀이 input일 때 rising-edge를 감지한다.0x GFERGPIO 포트 핀이 input일 때 falling-edge를 감지한다.0x GEDRGRER이나 GFER로 설정된 값에 따른 결과를 설정한다.0x CGAFRGPIO 핀을 alternate function으로 전환한다. 위의 GPIO를 사용하기 위한 방법은 다음과 같다. GPDR로 포트 핀의 방향을 설정한다. 포트 핀의 방향을 output으로 설정했을 때는 GPSR로 해당 비트를 셋하거나 GPCR로 셋된 포트 핀을 0으로 만든다. 포트 핀의 방향이 input으로 설정되었을 때는 GEDR로 해당 비트의 값을 읽을 수 있다. 다음으로 이 GPIO핀을 통하여 인터럽트를 받아 보는 설명이다. 인터럽트란 장치가 디바이스 드라이버의 주의를 끌고 어떻게 동작할 필요가 있는지 알려주는 방법이므로 장치 디바이스 드라이버를 만들기 위한 중요한 부분 중에 하나이다. 프로그램에서 인터럽트를 받는 방법은 아래와 같다. request_irq()를 이용하여 자신만의 irq를 요청한다. set_GPIO_IRQ_edge()를 이용하여 GPIO 포트번호와 감지할 상태를 설정한다. enable_irq()로 인터럽트를 활성화 시킨다. 모든 사용이 끝났을 때 disable_irq()와 free_irq()를 사용하여 irq를 제거한다. 현재 타겟 보드에는 GPIO포트의 0번이 LCD의 오른쪽 맨 아래에 있는 핀이고 나머지는 네트워크 쪽이나 LCD쪽으로 빠져나가 있다. 여기서는 이 GPIO0번을 이용하여 인터럽트를 감지하는 디바이스 드라이버를 만들기 위해 아래와 같이 소스 파일을 작성한다.

94 디바이스 드라이버 다음은 EMPOS II에서 사용하고 있는 GPIO의 일부분. 74HC373은 D-type Latch이어서
테이터를 항상 가지고 있다.

95 디바이스 드라이버 프로그램 구조 init_module(), cleanup_module() 디바이스 드라이버 등록 및 해제
open(), release() 디바이스 카운트 증가 및 감소 GPIO인터럽트 등록 및 해제 read() interrupt_sleep_on()함수를 이용하여 인터럽트가 발생하기까지 기다린 후 데이터를 복사하여 응용 프로그램에 전달. button_interrupt() 인터럽트가 발생하면 이 함수가 실행 wake_up_interruptible()함수를 사용하여 자고 있는 interrupt_sleep_on() 함수를 깨운다. 아래와 같은 명령을 이용하여 디바이스 드라이버를 커널에 삽입한다. insmod driver.o 여기서 driver.o는 테스트로 작성된 디바이스 드라이버 파일명이다. 위와 같이 콘솔에서 insmod driver.o를 실행 시키면 다음과 같은 시스템콜이 타겟 보스의 커널에서 수행 되어 드라이버를 커널에 삽입한다. (1)sys_create_module()을 사용하여 디바이스 드라이버를 적재하기 위한 매모리를 활당한다. (2)sys_get_kernel_syms()를 이용하여 driver.o안에 있는 심볼을 커널에 등록한다. (3)마지막으로 sys_init_module()을 사용하여 driver.o를 메모리에 적재한다. 이 과정에서 driver.o안에 있는 init_module()이 실행되고 그 안에 있는 커널 함수인 register_chrdev()가 수행되어 디바이스 드라이버 이름과 메이저 번호와 file_operations 구조체를 커널 변수인 chrdevs에 등록한다. 위와 같이 디바이스 드라이버를 커널에 삽입했으면 다음 해야 하는 일은 드라이버에 대응하는 특수 장치 파일(노드)을 만드는 일이다. 다음은 콘솔에서 특수 장치 파일을 만드는 명령이다. mknod /dev/device c 주번호 부번호 위의 명령에 의해 커널에서 수행 되는 일은 다음과 같다. mknod 명령은 커널의 sys_mknod()를 호출하고 이 함수는 다음과 같은 일을 수행한다. (1)먼저 /(루트)에서 시작해서 dev 디렉트리까지의 경로를 찾아 ledioport라는 이름의 dentry를 만들고 루트에 연결한다. (2)inode 하나를 만들고 dentry의 d_inode에 연결한다. (3)inode의 i_mode와 i_rdev에 S_IFCHR 과 (주번호<<8|부번호)을 기록한다. (4)inode의 i_fop에 def_chr_fops의 주소값을 기록하여 이를 통해 open메소드에 chrdev_open()이 연결되도록 한다. 위와 같이 커널에 디바이스 드라이버를 삽입하고 이것에 대응하는 특수장치 파일을 만들어야 어플리케이션의 디바이스 드라이버 사용이 가능하다.

96 디바이스 드라이버 TextLCD 디바이스 IOCTL()함수 읽기/쓰기외의 부가적인 연산을 위한 인터페이스
읽기/쓰기외의 부가적인 연산을 위한 인터페이스 디바이스 설정및 하드웨어 제어 함수 호출 Int ioctl(int fd, int cmd, …); fd : 파일 기술자 cmd : 명령 번호 … : 명령에 따른 인수 명령 번호 시스템에서 유일한 번호 정의 메크로 _IO(base,command) : 데이터 이동이 없다. _IOR(base,command) : 커널에서 응용 프로그램으로 데이터 이동 _IOW(base,command) : 응용 프로그램에서 커널로 데이터 이동 _IOWR(base,command) : 양방향 데이터 이동

97 디바이스 드라이버 디바이스 드라이버에서 ioctl 사용방법 함수 선언
int (*ioctl)(struct inode *inode,struct file *file,unsigned int cmd, unsigned long gdata); cmd : 명령 번호 gdata : 함수 호출시 넘겨 받는 인수 함수 구현 switch(cmd) { case: TEXTLCD_COMMAMD_SET: ... break; case: TEXTLCD_FUNCTION_SET: }

98 디바이스 드라이버 Text lcd모듈은 8bit 마이크로프로세서가 내장되어 있고 2개의 레지스터가 존재한다.
Instruction Register(IR) Text lcd 모듈의 환경설정. Data Register(DR) Text lcd 모듈에 글자를 표시하기 위한 데이터 값이 들어가는 레지스터. 텍스트 lcd를 사용하기 위해서는 Instruction Register(IR)에 명령을 셋하고 Data Register(DR)에 표시하고자 하는 데이터 값을 쓰면 된다. Text lcd 모듈에서 데이터 라인이 8비트이고 제어 비트가 3비트 이므로 디바이스 드라이버에서는 하위 8비트는 데이터라인으로 묶고 상위 3비트는 제어라인으로 사용한다.

99 디바이스 드라이버 - 텍스트 LCD모듈의 제어 명령표 기 능 제어 신호 제어 명령 Executed Time RS R/W D7
1.64mS Clear Display 1 Return Home 40uS Entry Mode Set I/D S Display on/off Control D C Cursor or Display Shift S/C R/L Function Set D/L N F Set CG RAM Address CG RAM Address Set DD RAM Address DD RAM Address Read Busy Flag and Address BF Address Counter Data Write to CG RAM or DD RAM Write Address Data Read to CG RAM or DD RAM Read Address 텍스트 모듈의 설명서를 참조하여 제어신호 E가 클럭 형태로 쓰인다는 것을 알려준다. Write Timing이나 read timing에 관련된 타이밍도 참조… 텍스트 LCD 모듈의 제어 명령은 위와 같으며 이들 명령을 디바이스 드라이버에서 텍스트 LCD에 해당하는 주소에 특정 값을 Write하면 된다. 위의 각 기능에 따른 세부 사항은 다음과 같다. Clear Display 전체 화면을 지우고 어드레스 카운터를 DD(Display Data) RAM 어드레스를 0으로 하여 커서를 home으로 위치한다. Return Home DD RAM의 내용은 변경하지 않고 커서를 home위치로 한다. Entry Mode Set 데이터를 read하거나 write할 경우에 커서의 위치를 증가(I/D=1)시킬 것 인가 감소(I/D)시킬 것 인가를 결정하며, 또한 화면을 쉬프트 할 것인지(S=1) 아닌지(S=0)를 결정한다. Display ON/OFF control 화면 표시를 ON/OFF 하거나(D), 커서를 ON/OFF 하거나(C), 커서를 깜빡이게 할 것인가(B)의 여부를 지정한다. Cursor or Display Shift 화면(S/C=1) 또는 커서(S/C=0)를 오른쪽(R/L=1) 또는 왼쪽(R/L=0)으로 쉬프트한다. Function Set 인터페이스에서 데이터의 길이를 8비트(DL=1) 또는 4비트(DL=0)으로 지정하고, 화면 표시 행수를 2행(N=1) 또는 1행(N=0)으로 지정하며, 문자의 폰트를 5x10 dot(F=1) 또는 5x7 dot(F=0)로 지정한다. Set CG(Character Generator) RAM Address CG RAM의 어드레스를 지정한다. 이후에 송수신하는 데이터는 CG RAM 데이터이다. Set DD(Display Data) RAM Address DD RAM의 어드레스를 지정한다. 이후에 송수신하는 데이터는 DD RAM 데이터이다. Read Busy Flag and Address LCD 모듈이 내부 동작중임을 나타내는 Busy Flag(BF) 및 어드레스 카운터 내용을 read 한다.

100 디바이스 드라이버 - Text LCD의 Write 타이밍도 Read timing과 write timing도의 차이점은
R/W 가 read일때 는 high이고 write 일때는 low이다.

101 디바이스 드라이버 Text LCD모듈의 초기화하는 방법 Function Set(이진수:001x xx00)을 보낸다.
Display ON/OFF Control(0000 1xxx)을 보낸다. Entry Mode Set( xx)을 보낸다. DD RAM 주소를 보낸다. 문자 데이터를 연속으로 보낸다. 제어 비트 RS, R/W, E는 Text lcd 타이밍도를 맞추어 제어해 준다.

102 디바이스 드라이버 프로그램 구조 init_module(), cleanup_module() 디바이스 드라이버 등록 및 해제
I/O 메모리 활당 및 해제 open(), release() 디바이스 카운트 증가 및 감소 usage 카운트에 따른 디바이스 접근 방식 write() copy_from_user()를 이용하여 사용자 공간의 데이터를 전송 전송 받은 데어터를 Text Lcd에 적용시킴 Ioctl() 명령에 따른 Text Lcd 제어 아래와 같은 명령을 이용하여 디바이스 드라이버를 커널에 삽입한다. insmod driver.o 여기서 driver.o는 테스트로 작성된 디바이스 드라이버 파일명이다. 위와 같이 콘솔에서 insmod driver.o를 실행 시키면 다음과 같은 시스템콜이 타겟 보스의 커널에서 수행 되어 드라이버를 커널에 삽입한다. (1)sys_create_module()을 사용하여 디바이스 드라이버를 적재하기 위한 매모리를 활당한다. (2)sys_get_kernel_syms()를 이용하여 driver.o안에 있는 심볼을 커널에 등록한다. (3)마지막으로 sys_init_module()을 사용하여 driver.o를 메모리에 적재한다. 이 과정에서 driver.o안에 있는 init_module()이 실행되고 그 안에 있는 커널 함수인 register_chrdev()가 수행되어 디바이스 드라이버 이름과 메이저 번호와 file_operations 구조체를 커널 변수인 chrdevs에 등록한다. 위와 같이 디바이스 드라이버를 커널에 삽입했으면 다음 해야 하는 일은 드라이버에 대응하는 특수 장치 파일(노드)을 만드는 일이다. 다음은 콘솔에서 특수 장치 파일을 만드는 명령이다. mknod /dev/device c 주번호 부번호 위의 명령에 의해 커널에서 수행 되는 일은 다음과 같다. mknod 명령은 커널의 sys_mknod()를 호출하고 이 함수는 다음과 같은 일을 수행한다. (1)먼저 /(루트)에서 시작해서 dev 디렉트리까지의 경로를 찾아 ledioport라는 이름의 dentry를 만들고 루트에 연결한다. (2)inode 하나를 만들고 dentry의 d_inode에 연결한다. (3)inode의 i_mode와 i_rdev에 S_IFCHR 과 (주번호<<8|부번호)을 기록한다. (4)inode의 i_fop에 def_chr_fops의 주소값을 기록하여 이를 통해 open메소드에 chrdev_open()이 연결되도록 한다. 위와 같이 커널에 디바이스 드라이버를 삽입하고 이것에 대응하는 특수장치 파일을 만들어야 어플리케이션의 디바이스 드라이버 사용이 가능하다.

103 참고문헌 Intel PXA255 Processor Develper’s Manual
Hanback Electronics EMPOS II SW/HW Manual Understanding the Linux KERNEL ARM Architecture Reference Manual Unix 시스템 프로그래밍 Beginning Linux Programming Add-on Linux Kernel


Download ppt "임베디드 리눅스 시스템 (using EMPOS II)"

Similar presentations


Ads by Google