반응형

ARM Processor 개요


  • ARM


  영국의 ARM(Advanced RISC Machines)회사는 RISC 프로세서를 설계하고 라이센싱하는 회사입니다. 그 중에서 ARM社의 주요 사항은 ARM 아키쳐를 개발 및 CPU를 디자인 합니다. ARM Processor는 로드 및 저장 아키텍처를 구현하므로 일반적인 RISC 프로세서입니다. 로드 및 저장 명령어만 메모리에 액세스할 수 있고 데이터 처리 명령어는 레지스터 내용에 대해서만 작동합니다. ARM에서 구현된  Thumb®, Thumb-2, NEON™, VFP 또는 Wireless MMX 명령어 등의 여러 명령어들에 의해 정리되고, 실행 됩니다.

  ARM社는 직접 processor 반도체를 제조해 판매하지 않습니다. 대신 설계한 processor를 Intellectual property(IP) 형태로 제공하며, 이에 대한 license를 판매합니다. ARM processor IP는 일종의 설계도로, 여러 반도체 회사들이 여기에 필요한 주변장치들을 추가해 System On Chip(Soc) 형태로 반도체를 제조해 판매합니다.

  ARM processor의 가장 큰 장점은 성능에 비해 전력 소비량이 작다는 것입니다. 때문에 스마트폰이나 PDA 같은 비교적 큰 computing power가 필요하지만 전력 소비량이 작아야 하는 휴대용 기기 또는 임베디드 분야에서 많이 사용합니다.


  • 용어정리


  ARM 관련 자료에는 ARM architecture, ARM core, ARM processor라는 용어들이 자주 나오는데, 각각의 의미는 다음과 같습니다. 먼저, ARM architecture는 명령어, 레지스터 구조, 메모리 구조 등의 processor 기본 구조와 동작원리에 대한 정의를 의미합니다. 그리고 이 ARM architecture에 따라 구현한 processor의 핵십 부분을 ARM core라고 합니다. 

  이 ARM core에 Cache, Memory Management Unit(이하 MMU), Memory Protection Unit(이하 MPU), Tightly Coupled Memory (이하 TCM), Bus Interface Unit (이하 BIU) 등의 핵심 주변장치들을 추가해놓은 것을 ARM processor라고 합니다. 아래 표는 ARM architecture와 그 architecture를 따르는 주요 ARM core 및 그 특징을 보여줍니다.



ARM architecture 별 특징과 구현 ARM core 예
Arichitecture특징Core
ARMv1
  • 첫 ARM processor
  • 26 bit addressing

ARM1

ARMv2
  • 32 bit multiplier
  • 32 bit coprocessor 지원

ARM2

ARMv2a
  • On-Chip cache
  • SWAP 명령 추가

ARM3

ARMv3
  • 32 bit addressing
  • CPSR과 SPSR regisger 분리
  • Mode 추가 (undefined mode, abort mode)
  • MMU 지원 (가상 메모리)

ARM6 ARM7DI

ARMv3M
  • Signed/unsigned long multiply 명령 추가

ARM7M

ARMv4
  • Signed/unsigned halfwords/bytes load-store 명령 추가
  • Mode 추가 (system mode)
  • 26 bit addressing 지원하지 않음
StrongARM
ARMv4T
  • Thumb 명령 추가

ARM7TDMI ARM9TDMI

ARMv5TE
  • ARMv4T의 확장판
  • 향상된 ARM과 Thumb state 간 전환 명령 추가
  • Digital Signal Processing(이하 DSP) 성능 향상을 위한 명령 추가 (Enhanced DSP 명령)

ARM9E ARM10E

ARMv5TEJ
  • Java bytecode 성능 향상을 위한 명령 추가 (Jazelle 기술)

ARM7EJ ARM926EJ

ARMv6
  • Multiprocessor 명령 개선
  • Unaligned and mixed endian 데이터 처리 지원
  • Multimedia 명령 추가

ARM11



ARM core는 특징에 따라 몇 개의 family로 구분합니다. 아래 표는 ARM core family와 그 familiy에 속하는 ARM core의 대략적인 특징을 보여줍니다.




ARM core family 별 특징
ARM7ARM9ARM10ARM11
파이프라인 단계3568
동작 주파수 (MHz)

(Worst case)

125220 ~ 250266 ~ 325400
전력 소비량 (mW/MHz)0.060.4

(+cache)

0.5

(+cache)

0.4

(+cache)

성능 (MIPS/MHz)0.91.11.31.2
구조Von NeumannHarvardHarvardHarvard
  • mW/MHz: 0.13 micron 공정일 경우
  • MIPS: Dhrystone 2.1

ARM architecture, ARM core, 또는 ARM processor 이름에 포함된 알파벳과 숫자의 의미는 다음과 같습니다.



ARM [a] [b] [T] [D] [M] [I] [E] [J] [F] [-S]

a : 속한 ARM core family

b : memory management unit, memory protection unit, cache, TCM 구성

T : Thumb 명령 지원

D : 디버그 기능 지원

M : 64 bit 결과를 내는 곱셈기 지원

I : In-Circuit Emulator(이하 ICE) 기능 지원

E : DSP 성능 향상을 위한 명령(Enhanced DSP 명령) 지원

J : Java bytecode 성능 향상을 위한 명령(Jazelle 기술) 지원

F : Vector Floating-Point(이하 VFP) 구조 지원

-S: Electronic Design Automation(이하 EDA) 도구로 synthesis 할 수 있음


  예를 들어, ARM926EJ-S의 “9”는 ARM 9 family에 속함을, “26”은 MMU와 cache 그리고 TCM 지원을, “E”는 DSP 성능 향상을 위한 명령(Enhanced DSP 명령) 지원을, J는 Java bytecode 성능 향상을 위한 명령(Jazelle 기술) 지원을, -S는 EDA 도구로 synthesis 할 수 있음을 의미합니다. 그리고 ARM 9 family 부터는 대부분 “T”, “D”, “M”, “I” 가 나타내는 기능들을 기본적으로 포함하기 때문에 이 알파벳들은 생략합니다.


  • Programmer's Model


  Programmer's model이란 프로그래머가 프로그램을 작성하기 위해 필요한 정보를 의미합니다. 명령어, 메모리 구조, 동작 모드, 레지스터, 예외처리 방법, 인터럽트 처리 방법 등이 이에 해당합니다. 이 programmer’s model은 ARM architecture에 따라 조금씩 달라집니다.


  • 명령어 집합, 명령어 집합 상태, 동작 모드


ARM Thumb instruction set


  ARM은 ARM instruction set과 Thumb instruction set이라는 두 종류의 명령어 집합(instruction set)을 지원한다. ARM instruction set에 속하는 명령어들은 모두 32비트 명령어입니다. Thumb instruction set에 속하는 명령어들은 모두 16비트 명령어입니다. 따라서 동일한 C언어 소스코드로 작성된 프로그램을 ARM 명령어 집합으로 컴파일 했을 때와 Thumb 명령어 집합으로 컴파일 했을 때에 생성되는 바이너리 이미지의 크기는 이상적인 상황에서 ARM 명령어 집합으로 컴파일하는 것이 Thumb 명령어 집합으로 컴파일 하는 것 보다 정확히 두 배 커야 합니다.

  물론 여러가지 최적화 기법을 컴파일러가 적용하기 때문에 실제로 ARM 명령어 집합의 바이너리 이미지가 Thumb 명령어 집합의 바이너리 이미지보다 두 배 큰 경우는 거의 생기지 않습니다.


Instruction Set State


  ARM은 명령어 집합이 두 개이므로 해당 명령어 집합을 실행하는 프로세서의 상태도 이에 연동되어 두 개이다. ARM 명령어 집합에 해당하는 32비트 명령어를 실행하는 프로세서의 상태를 ARM 상태(ARM state)라고 하고 마찬가지로, Thumb 명령어 집합에 해당하는 16비트 명령어를 실행하는 상태를 Thumb 상태(Thumb state)라고 합니다.

  당연히 ARM 상태와 Thumb 상태는 프로세서가 동작하는 중간에 서로 변경 가능하다. ARM 명령어 중에 BX나 BLX를 사용해서 ARM 상태에서 Thumb 상태로 변경할 수 있습니다. 서로 상태를 바꾸어가며 변경이 가능할 뿐 두 명령어 집합을 섞어서 사용할 순 없습니다. ARM 상태에서 ARM 명령어 집합의 명령을 수행하다가 Thumb 명령어가 나오면 반드시 프로세서의 명령어 수행 상태를 변경해야 합니다.

Cortex-A5에서는 추가로 두 가지 프로세서 상태가 더 존재 하는데, ThumbEE 상태와 Jazelle 상태입니다. ThumbEE 상태는 Thumb 명령어와는 다른 명령어로 프로그램이 실행되는 중간에 실행코드를 만들어 내며, 일종의 바이트 코드의 형태라고 보면 됩니다. Jazelle 상태는 1바이트 단위로 정렬되고 길이가 가변적인 Java 바이트 코드를 해석하기 위한 프로세서 동작 상태입니다.




반응형
반응형

전체적인 흐름분석도 벅차서 세부적인 코드분석은 하지 못했다..


Source Tree


 \arch\arm\cpu

각종 vendor별 CPU dependent Initialization code를 가진다.

 \arch\arm\cpu\arm7

entry point인 start.S 파일을 가진다. 

 \arch\arm\cpu\arm7
\exynos

 

 \arch\arm\include

cpu관련 c파일

 \board

각종 vendor별 board dependent Initialization code를 가진다.

 \board\samsung\wmdk5250

clock init, DMC init,.. 

 \common

 각종 명령어, user interface main routine, CLI

archtecture나 target board에 무관한 소프트웨어로 command구현되어 있다.

 \drivers

 각종 디바이스 드라이버를 가지고 있다. 

block , DMA, GPIO, I2C, input, MMC, MTD, net, PCI, RTC(real time clock dirver), serial,SPI, USB 등...

 \include

 u-boot header정보

 \include\config.mk

 컴파일 후 생성되는 파일로 보인다. ARCH, CPU, BOARD, VENDOR, SOC정보를 가짐.

 \include\configs\arndale5250.h

 보드에 대한 설정파일. 

 \lib 

 \net

 




부팅과정



SPL은 u-boot 의 기능 중 초기부분을 떼어서 만든거라고 봐도된다. 초기작업을 수행한 후 u-boot을 로딩한다. mcu에 따라 쓰는 것도 있고 안쓰기도 한다.


u-boot은 하드웨어 초기화를 수행한다음 최종적으로 kernel을 로딩한다.


출처 : http://processors.wiki.ti.com/index.php/The_Boot_Process




bootloader주요 기능


1. 하드웨어 초기화 : CPU clock ,Memory Timing, Interrupt, UART, GPIO등 초기화

코드상에서는 (lowlevel_init, board_init_f,board_init_r)  3가지 routine으로 분류하였다.

초기화라는 말이 상당히 추상적으로 들릴수도 있다. 짧은 지식으로 간단하게 말해보자면, cpu든 gpio든 ethernet이든 모두 구조체로 이루어져 있고, 이 구조체를 세팅해주는 작업이라고 하면 되려나?...


2. Image loading : flash memory에 있는 zImage, file system을 SDRAM으로 복사한다.


3. jump to kernel


전체적인 초기화 routine






임베디드관련 도서에서 u-boot의 흐름.
1. watch dog중지하고 interrupt disable을 수행
2. clock설정 :  PPL
3. 메모리 시스템 초기화
4. stack셋업 : c program을 위해서는 스택이 설정되어 있어야 한다.
5. IRQ, 예외처리 핸들러 설정, IRQ enable
6. C에서 사용되는 변수 초기화



arch\arm\cpu\armv7\start.S


reference : http://blog.naver.com/PostView.nhn?blogId=pjsin865&logNo=120108264029

위의 블로그를 가면 상세한 start.s를 볼 수 있다.





lds파일에 따르면, u-boot의 entry point는 _start 이다.
_start는 0x0번지에 위치하며, 가장 먼저 vector table를 세팅한다.

cpu_init_cp15를 호출한다. :  * Setup CP15 registers (cache, MMU, TLBs). The I-cache is turned on unless
 * CONFIG_SYS_ICACHE_OFF is defined.
disable MMU stuff and caches

board\samsung\smdk5250\lowlevel_init.S

start.S의 CPU_init_cirt는 lowlevel_init.S에 있는 lowlevel_init procdure를 호출한다.
(lowlevel_init은 2군데 있음. 진작 makefile 봤으면 쉽게 알았을탠데..)

ifneq ($(CONFIG_AM33XX)$(CONFIG_OMAP44XX) $(CONFIG_OMAP54XX)$(CONFIG_TEGRA20),)
arch\arm\cpu\armv7\lowlevel_init.S

board\samsung\smdk5250\lowlevel_init.S


-arch_timer_init[board\samsung\smdk5250\ ]
-tzpc_init[board\samsung\smdk5250\ ]
TZPC[TrustZone Protection Controller] 을 설정한다.
-monitor_init[board\samsung\smdk5250\ ]
-system_clock_init[board\samsung\smdk5250\ ]
 system clock 을 초기화한다.
-mem_ctrl_init[board\samsung\smdk5250\ ]
memory를 초기화한다.

arch\arm\cpu\armv7\start.S




ram상에 stack pointer를 설정.
board_init_f 호출한다.  
start.S 수행 종료됨.


arch\arm\lib\board.c 의 board_init_f 함수

board_init_f 역시 2군데 있음
arch\arm\lib\board.c 
board\samsung\smdk5250\Mmc_boot.c (ifdef CONFIG_SPL_BUILD) : u-boot호출하는 함수.


위 그림의 init_sequence에 있는 init함수를 수행한다.
DRAM bank사이즈 초기화,
dram config 설정 등을 수행.
start.S의 relocate_code함수 호출.


arch\arm\cpu\armv7\start.S 의 relocate_code procedure


u-boot을 ram으로 옮긴다.
마지막에  arch\arm\lib\board.c의 board_init_r 을 호출한다. 


arch\arm\lib\board.c 의 board_init_r함수

enable_caches, 
board_init : boot mode를 확인한다. 
gd->bd->bi_boot_params = (PHYS_SDRAM_1 + 0x100UL);
serial_initialize : s5p_serial_initialize in drivers\serial\serial_s5p.c
logbuff_init_ptrs
post_output_backlog
mem_malloc_init : 특정 영역의 메모리를 memset해준다. 근데 그 특정 영역이 DRAM에서 monitor copy??
arch_early_init_r
flash_init
nand_init
onenand_init
mmc_initialize: exynos_dwmci_init [drivers\mmc\exynos_dw_mmc.c] 함수를 호출한다.
AT91F_DataflashInit
env_relocate
arm_pci_init
stdio_init : 다시 다양한 init을 수행한다.
jumptable_init
api_init,
console_init_r.....등 다양한 위치에 있는 각종 init함수들을 호출한다.
arch_misc_init
misc_init_r
interrupt_init
enable_interrupts
board_late_init : mac주소를 ethaddr, usbethaddr에 등록한다.
bb_miiphy_init
eth_initialize : eth_device초기화
post_run
main_loop : 최종적으로 common\main.c의 main_loop함수로 이동.



common\main.c


하드웨어 초기화는 모두 완료되었다.

main loop는 사용자의 입력을 parsing하고, 해당 명령어를 수행한다.

최종적으로 kernel을 로딩한다.


http://www.crashcourse.ca/wiki/index.php/U-Boot_command/file_reference

위의 wiki에서 u-boot의 command확인가능하다.


dhcp는 boot image via network using DHCP/TFTP protocol

nfs는 boot image via network using NFS protocol

dcache는 enable or disable data cache 







출처 : http://jianna6.tistory.com

반응형
반응형

가) H/W 파악 Device Driver 점검

어떤핀이 어떤 소자에 연결되어있는지 CPU의 레지스터들은 어떤 존재하고, 어떻게 설정해야하는지, 화면출력은 어떤 디바이스를 통해서 하는건지 , 해상도는 어떤지 방식이며 무엇인지 어떤 디바이스들이 연결되고 드라이버는 있는지없는지 디바이스와 CPU가 연결된 방식은 무엇인지 먼저 H/W를 점검한다.


나) 레퍼런스 보드로 관련자료 수집 (회로도,데이터시트,검증된 BSP 등)

포팅하려는 OS가 이미올라간 보드의 회로도와 os관련 자료(bsp)를 확보하는 일이다. 이것을 확보하게 된다면 레퍼런스 보드와의 공통점과 차이점만 밝히면서 쉽게 포팅작업을 진행할수 있다.


다) BSP 포팅 (bootloader, kernel, file system)

Bootloader, kernel , filesystem 등을 Image,바이너리로 지원해주지 않는다면 BSP를 만들 Builder를 사용해야합니다. 참고로 Freescale Imx6 quad SABRE SD 보드에 필요한 BSP를 LTIB(Linux Target Image Builder)를 사용해서 u-Boot.bin, uImage 등을 만들어냈다. SD Card를 메모리로 사용하기때문에 dd 명령어로 부트로더와 커널이미지를 복사한후 file system를 세팅해서 마무리 지었다.


라) 각종 드라이버 (LCD)등에 대한 포팅

포팅과정중에 흔하게 수정하는것이LCD, GPIO등이다. LCD의 종류를 알지못해서 드라이버가 없는경우도 있어 수정 및 작성으로 새로 만들어야하는경우도 있지만 표준 VGA를 통해서 처리할수도있습니다. GPIO라 불리는 핀들은 General Perpose IO라 하여 범용으로 쓰이는 IO핀들이다. 번용이다보니 붙는 위치도 개수도 다양합니다. 그리고 레퍼런스에 없는 디바이스 드라이버는 따로 제작을 해야합니다.


마) 디버깅

OS를 만들었다면 돌려보고 프로그램도 구동하면서 문제가없는지 확인해야합니다.

반응형
반응형

U-Boot & 부트로더의 이해

부트로더는 시스템을 초기화하고 운영체제를 탑재하거나 실행하기 위해 시스템 초기화코드, 하드웨어 제어 프로그램, 네트워크, USB등의 프로토콜과 일부 파일 시스템을 관리한다.(BIOS와 비슷하다)



1.1 부트로더의 역할


(1) Target 초기화

전원이 입력되면 하드웨어와 소프트웨어 환경을 설정한다.

불필요한 하드웨어의 동작 중지, 시스템 클록 설정, 메모리 제어기 설정, MMU/MPU 설정 등

하드웨어 설정이 완료된 후 실제 프로그램 동작에 필요한 재 배치와 스택 영역 설정 및 C에서 사용하는 변수 영역을 설정하고 C로 작성된 함수를 호출 한다.


(2) Target 동작 환경 설정

BIOS CMOS 설정과 유사하다.(부트 방법, 네트워크 설정, IP 주소 설정 등)


(3) 시스템 운영체제 부팅

임베디드 시스템의 운영체제는 플래시 메모리에 탑재되어 있으므로 부팅시 주메모리에 탑재한 후 실행됨.

부트로더는 플래시 메모리에 있는 OS DRAM에 복사하고 제어권을 OS의 시작점으로 넘겨주는 기능을 함.


(4) 플래시 메모리 관리

보통 플래시 메모리에는 OS이미지와 부트로더가 탑재된다.


(5) 모니터 기능

시스템의 동작 상태 감시, 하드웨어 정상 동작 여부 검사, 메모리 검사와 POST(Power-On Self Test) 등의 기능


1.2 부트로더의 특징

부트로더는 하드웨어 의존성이 강하다.

부트로더를 작성하려면 프로세서의 구조와 특징 및 사용법을 알아야 한다.

부트로더의 시작 부분은 어셈블리어로 작성되기 때문에 명령어 사용법을 알고 있어야 한다.

플래시 메모리의 부트 섹터에 저장되어 유지되므로 크기가 작아야 한다.

좋은 오픈소스가 많으니 오픈 소스 부트로더를 사용하자.


1.3 부트로더의 종류

LILO, GRUB, Loadlin, EtherBoot, Blob, PMON, RedBoot, U-Boot

 

U-Boot 빌드와 설치

U-Boot는 다양한 기능을 가지는 부트로더로 하드웨어 초기화, 하드웨어 검사, 소프트웨어 다운로드 및 실행, 플래시 메모리 관리, 운영체제 부팅등의 기능을 제공한다.

U-Boot는 리눅스와 유사한 구조를 가지고 있으며, 일부는 리눅스 소스를 사용했다.


2.1 U-Boot 소스 설치

ftp://ftp.denx.de/pub/u-boot

소스를 받아 개발하고자 하는 보드에 맞게 포팅해야 한다.


2.2 U-Boot 소스 구성

u-boot top : U-Boot의 최상위 디렉토리. Makefile, board.cfg 등의 주요 파일을 가지고 있으며, 모든 U-Boot의 빌드 동작을 실행하는 디렉터리

arch : arm, mips, powerpc 등 프로세서 아키텍처별로 서로 다른 디렉터리를 구성하고 있다. 각 아키텍처에 따른 소스를 구성하는 디렉토리.

board : 각 제조사별 보드 관련 소스를 구현하는 디렉토리

common : U-Boot에서 공통적으로 사용되는 소스를 구현하는 디렉토리.

disk : DISK를 관리하기 위한 소스

doc : U-Boot 관련 문서를 가지고 있는 디렉토리

drivers: U-Boot에서 지원되는 다양한 장치들에 대한 드라이버를 구현한 디렉토리

examples : U-Boot에서 독립적으로 프로그램을 실행시키는 샘플코드를 포함한 디렉토리

fs : U-Boot에서 지원하는 다양한 파일시스템에 대한 소스를 구현한 디렉토리

include : U-Boot에서 사용되는 헤더 파일을 정리한 디렉토리. 특히 configs 디렉토리는 보드별 동작에 필요한 설정 헤더 파일을 가지고 있음

lib : U-Boot에서 사용되는 각종 라이브러리를 구현한 디렉토리

net : U-Boot에서 지원되는 UDP, IP, TFTP 등 네트워크 프로토콜을 구현한 디렉토리

post : POST를 구현한 디렉토리

tools: U-Boot 사용에 필요한 각종 호스트 유틸리티를 구현하는 디렉토리

 

2.3 U-boot 포팅에 필요한 디렉토리 및 소스 구성

u-boot top/Makefile : 빌드용 Makefile

/board.cfg : 지원되는 보드에 대한 각 옵션. 타겟 이름, 이키텍쳐, CPU, 보드이름, 벤더, SoC

arch/arm/config.mk : ARM 아키텍처에 대한 크로스 컴파일러 및 빌드 옵션을 지정함.

/cpu :  ARM 프로세서 디렉토리를 구현함

/include : ARM 프로세서 및 타겟 SoC 관련 헤더를 정의함

/lib : ARM 프로세서에서 일반적으로 사용되는 기능을 라이브러리로 구현함

board/samsung/dtk4412 : DTK4412 타겟 보드용 소스가 구현됨. 프로그램이 탑재되는 메모리의 위치 및 메모리의 배치를 지정하는 파일을 가지고 있음.

board/ti/beagle : beagle 보드에 대한 파일을 구현

drivers/block : 블록 디바이스 드라이버를 구현함

/mmc : mmc 드라이버를 구현

/mtd : NAND, OneNAND 등 메모리 장치를 블록 디바이스로 사용하기 위한 MTD 드라이버를 구현함.

/net : 각종 네트워크 장치 드라이버를 구현

/serial : 시리얼 디바이스 드라이버가 구현되어 있는 디렉토리.

/usb : usb 장치 드라이버를 구현

/..... : 기타 장치 드라이버가 있음

include/configs/dtk4412.h : configs/dtk4412.h 파일은 대상 보드가 동작하기 위한 각종 하드웨어 및 소프트웨어 설정값을 가짐. U-Boot를 포팅하는데 있어 매우 중요한 정보를 가짐.


U-Boot 포팅

3.1 U-Boot 포팅에 필요한 소스 및 타겟

u-boot top/boards.cfg, arch/arm/cpu, arch/arm/include, board/samsung/dtk4412, driver/mmc, driver/net, driver/serial, driver/usb, include/configs/dtk4412.h


3.2 U-Boot 초기화 동작의 이해

U-Boot는 시스템 리셋 키가 입력되거나 전원이 인가되면 실행되는 부트 코드 이다.

일반적으로 부트코드가 NOR 플래시에 저장되어 사용되는 경우 바로 플래시에서 동작하게 구현할 수 있다.

하지만, 대부분의 시스템은 NAND플래시나 SD/MMC와 같은 장치에 저장되어 있다. 이런 경우,대부분 저장장치의 부트코드를 실행 가능한 주 메모리(DRAM)으로 복사한 후 실행한다.

주메모리 초기화는 초기 설정이 필요없는 칩 내부의 SRAM에서 담당한다. 하지만 SRAM에 비해 U-Boot 코드가 상당히 크기 때문에 모든 코드를 SRAM으로 복사해서 사용할 수 없다. 따라서 클록이나 메모리 장치 초기화를 담당하는 코드와 메인 부트로더 코드를 복사하는 코드를 SRAM에 복사하여 사용한다. 이후 나머지 부트로더 코드를 복사하여 사용한다. 이에따라 BL1과 주U-Boot 코드로 나뉜다.


U-Boot 사용하여 시스템이 부팅되는 과정

전원인가 또는 리셋신호 구동 후 내부 ROM 코드 BL0 실행

BL0에서는 외부 핀 OM(Operating Mode)에 따라 부트 디바이스 선택

선택된 부트 디바이스의 초기 부트코드(BL1)을 내부 SRAM에 복사

SRAM BL1에서 U-Boot 부트 코드를 DRAM에 복사

제어권을 복사된 DRAM U-Boot 영역으로 변경, 변경 후에는 U-Boot 코드 실행


Exynos4412 U-Boot 소스는 어셈블리 파일 arch/arm/cpu/armv7/start.S로부터 시작된다. 이 파일의 앞부분에는 ARM 프로세서의 예외 처리 벡터가 있고 처음 시작은 reset 핸들러로 분기하여 실행된다. reset 핸들러는 SVC32 모드로 전환하고, 캐시 및 MMU의 사용을 중지한 다음에 보드 초기화를 실행한다.

 

 




원문 : ARM으로 배우는 임베디드 리눅스 시스템

반응형
반응형

■ S3C2443 지원 리스트 
▪ S3C2443의 LCD 컨트롤러는 시스템 메모리의 비디오 버퍼에서 외부의 LCD 드라이버에 LCD 이미지 데이터를 전송하는 로직으로 구성 
▪  LCD 컨트롤러 
   수평/수직 픽셀, 데이터 라인 너비, 인터페이스 타이밍, 리프레쉬 비율과 관련된 스크린 상에 요구되는 기능 지원 프로그래밍이 가능

 

 


■ OVERVIEW 
1. 2가지의 인터페이스 지원 
  (1) RGB Interface
  (2) i-80 System Interface


2. 디스플레이 컨트롤러 지원 내역 
  (1) 2 overlay Image
  (2) 다양한 컬러 포맷 
  (3) 16 단계 알파 블랜딩 
  (4) 컬러 키 
  (5) x-y 축 포지션 컨트롤 
  (6) 소프트 스크롤링 컨트롤 
  (7) 윈도우 크기 변경 등

 

 


■ LCD SUB BLOCK DISCRIPTION (ARM920T BUS INTERFACE)
- AHB (Advanced High-Performance Bus)

 

 

 

■ LCD SUB BLOCK DISCRIPTION (LCD CONTROLLER STRUCTURE)

 

 


1. VSFR
  ▪ 71개의 프로그래밍 레지스터 블록 / 2개의 256x25 Palette Memory 설정 가능


2. VDMA
  ▪ Frame Buffer에 저장 되어 있는 비디오 데이터를 VPRCS로 DMA 방식 전송 담당


3. VPRCS
  ▪ VDMA로 부터 받은 비디오 데이터를 LCD (Device)로 전송 
  ▪ 전송 전 적합한 데이터 포맷으로 변환 
  ▪ 전송 데이터 포트 : RGB_VD, VEN_VD, SYS_VD


4. VTIME
  ▪ Timing Checking 담당

 

 

 

 

■ S3C2443 – LCD Interface (RGB Interface)
* RGB Interface Signal

- SYNC 신호 제어 가능, 일반적인 R,G,B 인터페이스로서 사용자 제어 용이 
(1) RGB Data Signal
(2) Vertical / Horizontal Sync Signal
(3) Data Valid Signal
(4) Data Sync Clock Signal

 

 

 

 

 ■ S3C2443 – LCD Interface (CPU Interface)


* CPU Interface Signal (i80 – System Interface) 
-SYNC 신호 제어 불가능, 별도의 신호 셋팅 없이  Video Mux에서 모든 신호를 관리하며, 단순 Chipset 제어만 거침 
(1) Address Signal
(2) Data Signal
(3) Chip Select Signal
(4) Register / Status Indicating Signal

 

 

 

■ S3C2443 – PIN MAP (RGB Interface)

 

 

■ S3C2443 – Register Setting
* Register Option : Eboot 및 Kernel 단, Driver 단 에서 설정하게 되는 레지스터 설명

 

 

 

■ S3C2443 – Display Driver Structure & Description


 

(1) Eboot 내부 main.c – InitDisplay 함수 (Eboot Entry Point)
  * Eboot 상 LCD 구동을 위한 디스플레이 셋팅 목적 함수 
  * Eboot 단에서 관련 레지스트 셋팅이 LCD Module 과 SYNC 동작하게 되면 Eboot 단 로고 확인 가능

 

(2) Kernel 내부 Init.c – InitDisplay 함수(Kernel Entry Point)

  * Eboot 상에 존재하는 main.c와 동일 한 목적으로 작성 (디스플레이 셋팅 목적)
  * Kernel 단에서 관련 레지스트 셋팅이 LCD Module 과 SYNC 동작하게 되면 Window CE 진입 시 화면 동작 확인 가능(

 

(3) 참조 Header File 정보 
  * src/inc 디렉토리에 존재하는 display.h 헤더파일 참조 (레지스터 셋팅값의 대부분이 이 헤더파일 상에 정의 - 필수)
  * Local 헤더파일 참조하면 Error / 반드시 INC 전역 헤더파일 참조해야 LCD 레지스터 값이 적용이 됨 
    (Eboot 단 및 kernel 단 레지스트 셋팅을 동기화하기 위하여 inc 공용 헤더파일 측을 수정해야 함)
  * Eboot 단에서 레지스트 셋팅이 완료되어 Eboot LCD 동작을 확인 하여도, Kernel 단 셋팅이 틀어지면 CE상 동작 불가

 

(4) src/drivers/Display/S3C2443DISP.cpp – 드라이버 단 소스 파일 
  * Kernel 단에서 모든 동작 관련 셋팅 정의가 되며, 본 소스 파일 상에서는 GWES 기반의 동작 정의 
    (화면 회전 / 블랜더 효과 등 Application 기반의 동작 환경 설정이 가능)
  * src/inc 디렉토리에 존재하는 s3c2443_lcd.h 헤더파일 참조 
    (드라이버 단 동작 정의가 아닌 GWES 기반의 Application 동작 중 필요한 사이즈 및 기타 컬러 옵션 설정 가능)

 

 

 

-----------------------------------------------------------------------------------------------------------




S3C6410 PIP 동작구조 

 

 

S3C6410 PIP의 화면의 위치 선정

 

 

 

---------------------------------------------------------------------------------------------------


S3C6410의 Image Rotator 동작 구조

 

 S3C6410 Image Rotator 동작 원리

 

 

-----------------------------------------------------------------------------------------------------------


 

 

 

-----------------------------------------------------------------------------------------------------------

 

 

<S3C6410의 Overlay 및 Color Key 동작원리>

 

 

 

 

<S3C6410 Frame Buffer>

 

■ S3C6410의 프레임 버퍼 공간

   ◆ S3C6410에서는 기본적으로 Window 1Layer만 사용하여 화면 출력

   ◆ 각 Layer의 Size = 480 X 272 X 2(16/8)

                               = 255 Byte

   ※ 12MB 확보이유 : Post Processor 및 Rotator 등의 여러가지 출력 FrameBuffer와 공용 사용

 

 

 

  

-----------------------------------------------------------------------------------------------------------

 

■ NTSC

 - 초당 29.97 개의 비월 주사된 비디오 프레임으로 이루어짐
 - 각 프레임은 전체 신호인 525 라인 중에서 480 라인으로 구성되며 나머지는 동기 신호나 수직

    귀선 및 자막과 같은 다른 데이터의 전송을 위해 쓰인다
 
■ BT656 (ITU656)

 - 압축되지 않은 PAL 또는 NTSC 표준 화질 텔레비전을 스트리밍하기 위한 단순한 디지털 영상

    프로토콜을 정의
 - BT.656 스트림은 27 MHz 로 동작하는 픽셀 클럭 신호에 따라 동시에 8 비트를 병렬로 전송

 

■ Composite (Video)

 - 색 신호와 휘도 신호를 동시에 혼합
 - 일반적으로 노란색의 출력 단자
 - 음성선 2개와 붙어있는 것을 합쳐서 말하기도 하지만 정확히는 노란 영상선만을 의미
 - 구성 재질은 동축 RCA 케이블이며, 전송 가능한 최대 해상도는 NTSC (480i)
 - 아날로그 케이블 중에서도 화질은 최저수준
 - 서로 상이한 신호를 혼합해 표현하기 때문

 

■ S-Video (Video)

 

 - 화질 개선을 위하여 색 신호와 휘도 신호를 서로 분리
 - S-Video의 앞 굴자 S는 Separate의 약자
 - Y/C Connection이라 명칭 (Y = 휘도 정보, C = 색 정보)
 - 480i 해상도 전송 가능
 - Composite 방식에 비해 고화질

 

 


-----------------------------------------------------------------------------------------------------------



< WMB2443 Board의 NTSC와 RGB I/F 동시 출력 구조 >

 

1. S3C2443의 LCD Controller에서 640 X 480의 RGB I/F 로 출력

2. 640 X 480 Image를 TV Endoer 입력과 LCD 출력으로 분기

3. TV Encoder에서 입력된 RGB I/F 영상을 Scaling과 RGB to NTSC 처리과정 후 모니터에 출력

 

 

-----------------------------------------------------------------------------------------------------------



< S3C6410의 Post Processor를 이용한 PIP 기능 동작구조 및 원리 (Direct Mode) >

 

 

■ Preview Path를 통한 YCbCr420 Format 입력된 영상이 Preview DMA 을 통해 Camera Frame Buffer에 저장 (RGB)

 

■ Post Processor 를 사용하지 않고 LCD Window 0 Frame Buffer에 저장 (RGB565)

 

■ Display Controller에서 두 영상을 Overlay 하여 LCD로 출력

 

 

 

 

-----------------------------------------------------------------------------------------------------------


< S3C6410의 Post Processor를 이용한 PIP 기능 동작구조 및 원리 (FIFO Mode) >

 

 

■ Preview Path를 통한 YCbCr420 Format 입력된 영상이 Preview DMA 을 통해 Camera Frame Buffer에 저장 (RGB)

 

■ Post Processor에서 Source Image를 Scale 및 Video Fomat / 색 공간 변환 후 Display Controller Window 0 FIFO로 전송

 

■ Display Controller에서 두 영상을 Overlay 하여 LCD로 출력

 

 

 

 

-----------------------------------------------------------------------------------------------------------



 < S3C6410의 Post Processor를 이용한 PIP 기능 동작구조 및 원리 (DMA Mode) >

 

 

■ Preview Path를 통한 YCbCr420 Format 입력된 영상이 Preview DMA 을 통해 Camera Frame Buffer에 저장 (RGB)

 

■ Post Processor에서 Source Image Address를 Camera Frame Buffer 주소로 설정,

    Destination Image Address를 LCD Frame Buffer Window 0 Frame Buffer로 설정

 

■ WinCE의 Defalut 출력인 Window 1 Frame Buffer의 Image와 카메라의 영상이 저장된 Window 0 Frame Buffer를

    DMA를 이용하여 LCD 측으로 전송

 

■ Display Controller에서 두 영상을 Overlay 하여 LCD로 출력

 

  

-----------------------------------------------------------------------------------------------------------


■Porch 값의 의미                                                                       

- Vertical Back Porch (VBP)                  : 수직 신호 출력 대기 시간

Vertical Front Porch (VFP)                  : 수직 신호 출력 후 대기 시간

Vertical Sync Pulse Width (VSPW)      : 수직 신호 High Level 유지 시간

Horizontal Back Porch (HBP)            : 수평 신호 출력 대기 시간 

- Horizontal Front Porch (HFP)            : 수평 신호 출력 후 대기 시간

Horizontal Sync Pulse Width (HSPW)  : 수평 신호 High Level 유지 시간

 

 

  ■ Porch 값 적용 전 후의 Frame Buffer 화면                                        

- Porch 값 적용 전

 

- Porch 값 적용 후

 

-----------------------------------------------------------------------------------------------------------


■ S3C2443 CPU Interface Control Sequence                             

 

 

 

- Disable Video Oupput : 출력 정지

- Set Video Signal : Main LDI(S3C2443에서 CPU I/F 방식의 Display 듀얼 출력 지원)선택, 클럭 설정

- System Interface Control : CPU I/F의 제어 신호 동작 설정

                                        CS(Chip Select) - Active Low

                                        WR(Write) - Active Low

 

-----------------------------------------------------------------------------------------------------------


■ SPI Interface Timing                                                                           

 

- Transfer Start Bit에 의해 데이터 전송 시작을 알림

- Device ID Code에 의해 Device 확인 (Value = 0x1D)

- RS Bit 로 인해 Index Data와 Instruction Data 구분

- 16bit Data 전송

- Transfer End bit에의해 데이터 전송 종료 알림

  

-----------------------------------------------------------------------------------------------------------


■ I80 Interface Control Signal                                           



■ I80 Interface Bus Timing 분석                                       


 

- RS 신호 상태를 High에서 Low로 인가 상태에서 Register 주소 값을 전송하는 것을 알림

Low에서 High로 변화 시 Data 값을 입력 받는 Register 주소를 알림

- CS 신호 상태를 High에서 Low로 인가 상태에서 LDI을 Enable을 하여 Address을 활성화

- Write Enable를 High에서 Low로 인가 상태에서 LDI에 Write 할 것이라는 것을 알림

- Write Data 출력 (High = ‘1’, Low = ‘0’)


-----------------------------------------------------------------------------------------------------------



■ S3C2443의 Display Controller의 PAD                          

 

 

 

       - VIDSEL 값이 '1'이고 VIDOUT이 '10'일 경우 VCLK PAD에서는 CPU(I80) Interface의 WE(Write Enable) 신호 출력


       - VIDSEL 값이 '1'이고 VIDOUT이 '00'일 경우 VCLK PAD에서는 RGB Interface의 VCLK 신호 출력


       - SYS_CS0와 SYS_CS1은 I80 Interface에서는 듀얼 출력이 가능하기 때문에 CS(Chip Select)가 2개 존재


       - 이하 VLINE, VFRAM, VM, LEND, VD 동일

 

 

-----------------------------------------------------------------------------------------------------------


■ RGB와 CPU(I80) I/F 구성 비교                                 

 

 

- S3C2410 Display Controller의 I80 Interface 미지원으로 인한 LCD Module을 Memory Controller에 연결

     * LDI의 Register를 이용하여 LCD 초기화

     * Virtual Frame Buffer의 내용을 LCD 모듈 내 SRAM 측으로 전송

 

 

- S3C2443 Display Controller의 I80 Interface를 지원하기 때문에 Display Controller에 연결

     * Virtual Frame Buffer에 화면 구성

     * SDRAM의 Frame Buffer의 내용을 DMA을 통해 Display Controller 측으로 전송

     * Display Controller에서 LCD 모듈 측으로 데이터 전송 

-----------------------------------------------------------------------------------------------------------





■ LCD 인터페이스 종류                                                    
    - RGB 인터페이스
    - CPU 인터페이스 (I80, M68)
    - SPI 인터페이스
    - MDDI 인터페이스
    - MIPI 인터페이스

 

■ LCD 인터페이스 별 제어신호                                            
    - RGB 인터페이스
        * VSYNC (Vertical Sync)
        * HSYNC (Horizontal Sync)
        * ENABLE
        * DOTCLK (Clock)
        * 드라이버 IC 제어를 위한 Serial 인터페이스 사용

 

    - CPU 인터페이스
        * WR (Write) / RD (Read)
        * RS (Command / Data)
        * CS (Chip Select)
        * 드라이버 IC 내부 RAM 사용

 

    - SPI 인터페이스
        * SDI / SDO / SCL 등을 이용하여 데이터 전송

 

    - MDDI 인터페이스
        * 신호선을 감소한 Serial Link Type 인터페이스

 

■ RGB 인터페이스 상세 설명                                              
    - 동영상을 많이 사용하는 TFT-LCD에 주로 적용
    - CPU 인터페이스와는 달리 Display RAM이 필요 없음
    - VSYNC Enable 구간 앞/뒤에 Porch 값과 같은 Non-Display 영역 설정
    - 한개의 HSYNC 발생 시 여러개의 Clock을 가짐
    - Clock 수를 카운트하여 Enable 구간 설정 및 Enable 구간 Active 시 Data 표현
    - VSYNC : VFP, VBP, VSW는 HSYNC가 기준이 됨
    - HSYNC : HFP, HBP, HSW는 Dot Clock 기준이 됨
    - VSYNC, HSYNC, Dot Clock SYNC를 통하애 한 Frame 주파수가 결정 됨
    - 위와 같은 설정이 맞지 않을 시 LCD 화면 상 플리커 현상 발생 (화면 밀림)

 

■ CPU 인터페이스 상세 설명                                              
    - MPU 인터페이스 명칭
    - Intel 80 계열 혹은 Motorola 68 계열 제어신호에 따라 Data 전송 방식
    - RS 신호에 따라 Command와 Data가 분리되어 전송
    - CS : Chip Select 신호로서 Low일 때 Chip이 동작
    - WR : Write 신호로서 Low->High 상태일때 Data를 Display RAM에 기록
    - RS : Read 신호로서 Data를 읽어옴
    - Command 기록 시 : RS = Low / WR 신호를 Address와 Command Latch

----------------------------------------------------------------------------------------------------------------



■ RGB Interface의 LCD Module의 Clock 동기화                        

  

 

        -  LCD Module DCLK Frequency는 33.26MHz
        -  S3C6410 Display Controller의 Clock 신호 관련 Register 

            CLKSEL_F : CPU에서 공급하는 Clock(HCLK)으로 133Mhz 임 (즉, 소스 Clock)
            CLKDIR  : 소스 Clock을 CLKVAL_F Register 값으로 분배하여 사용

            CLKVAL_F : 소스 Clock 분배 값을 나타내는 Register


■ Porch값의 의미                                                          

- Vertical Back Porch (VBP)                  : 수직 신호 출력 대기 시간

Vertical Front Porch (VFP)                  : 수직 신호 출력 후 대기 시간

Vertical Sync Pulse Width (VSPW)      : 수직 신호 High Level 유지 시간

Horizontal Back Porch (HBP)            : 수평 신호 출력 대기 시간 

- Horizontal Front Porch (HFP)            : 수평 신호 출력 후 대기 시간

Horizontal Sync Pulse Width (HSPW)  : 수평 신호 High Level 유지 시간



출처 : http://blog.daum.net/insopack77/268

반응형
반응형

  컴퓨터에는 사용자가 컴퓨터로 값을 전달하고 제어를 위한 도구로 굉장히 다양한 종류의 입력 장치가 있습니다.

예를들어 키보드, 마우스, 터치패드, 터치스크린, 조이스틱 등 여러 입력 장치들이 필요에 따라 존재합니다.

 

  그 종류는 수행하고자 하는 기능에 따라 특수성에 맞춰 점점 늘어나고 다양해지고 있습니다.

늘어나는 장치들을 관리하기 위하여 다양화되는 입력 장치들을 관리하기 위해 커널 영역에서 커널 입력 서브 시스템을 통하여 정리 및 관리 합니다.

  

  커널 입력 서브 시스템을 이용하게 되면 물리적으로 구성이 다르더라도 기능이 유사한 입력 장치는 동일하게 다루며 드라이버를 추가 작성하고 관리하기 편하도록 추상화가 가능합니다.

 

  위와 같이 커널 입력 서브 시스템을 이용함으로써 하드웨어적으로 동작 및 구현 방식이 다르더라도 그 기능이 유사한 장치들은 다 같은 방식으로 처리 및 핸들링 하는 것입니다.

 

  즉, 키보드의 입력 방식이나 통신 방식이 서로 다르더라도 키보드라는 기능이 유사하기에 입력 기능을 동일하게 처리할 수 있다는 의미 입니다.

 

  커널 입력 서브 시스템 및 입력 드라이버는 사용자에게 디바이스를 통하여 입력된 값을 알리기 위한 이벤트 인터페이스를 제공합니다.

 

  입력 장치의 입력 이벤트들을 사용자 영역의 어플리케이션에 전달하기 위해서 /dev/input 하위의 노드나 다른 방식을 이용할 필요없이 입력 관련 인터페이스를 이용하여 사용자에게 입력을 알릴 수 있습니다.

 

  입력 드라이버에서 공통된 부분을 찾아낸 후 단순화하고 일관성있게 만드는 추상 개념을 제공합니다.

입력 하위시스템은 USB로 연결되는 마우스나, 키보드등 다양한 입력장치를 위해 USB HID라는 드라이버를 추상화하고 제공하여 좀 더 단순하고 일관성있게 작성 및 도움이 됩니다.

 

 

 

  위 그림은 입력 장치에 대한 커널 인터페이스 구성 그림입니다. 각각의 입력장치가 USB 형태는 모두 USB HID 인터페이스 드라이버를 통하여 연결되고, 다른 입력 장치들에 대해서는 각각의 통신 방식에 따라 입력 코어를 거쳐 입력 이벤트 드라이버로 전달되며 그 후 전달된 입력들을 입력 이벤트 드라이버에서 이벤트를 발생시킵니다.

 

  커널 내의 입력 드라이버는 입력 장치 드라이버와 입력 이벤트 드라이버로 두가지의 형태로 나누어져 있습니다.

 

    - 입력 장치 드라이버 : 하드웨어 영역의 장치들과 통신하며 해당 입력 장치의 기능을 세부 구현 및 기능 담당
    - 입력 이벤트 드라이버 : 입력 장치 드라이버의 이벤트 수신과 처리를 위하여 사용자 영역과 통신

 

  커널 내부 소스에서도 위와 같이 추상화 되어 분류되어 있음을 확인할 수 있습니다.  

 

 

  입력 디바이스 드라이버를 위한 참조 헤더는 /include/linux/input.h 입니다.

이 헤더에는 입력 디아비스 드라이버들의 추상화 및 이벤트 등의 전달을 위하여 필요한 매크로나 정의, 함수 등을 정의 한 것으로 위 헤더의 정의에 맞춰 드라이버를 설계합니다.

 

struct input_event {
        struct timevale time;
        __u16 type;
        __u16 code;
        __s32 value;

 

 위의 구조체는 input_event 구조체로 입력 이벤트를 발생시키기 위한 구조체 입니다. timeval 구조체의 time이란 변수는 타임스탬프(발생 시간)를 말하며, type은 이벤트의 형식을 말합니다. 절대 자표, 버튼등의 형식이 있으니, input.h를 찾아보시기 바랍니다. code 는 이벤트 코드로 그 이벤트에 해당하는 keycode를 말합니다 예를 들면 키보드의 backspace나 space등 여러 버튼을 구분 짓습니다. value 는 이벤트의 값을 말합니다. 키패드나 키보드 입력이 있을 시에 버튼이 on 이라면 1 off라면 0 등의 값을 나타냅니다.

 

 

  실제 드라이버를 작성하기 위해 필요로 되는 input.h의 기본 함수들을 나열하겠습니다.

//input_dev 구조체를 위한 메모리 할당/해제
     
struct input_dev *input_allocate_device(void);
void input_free_device(struct input_dev *dev);
     
     
     
     
//입력 디바이스 등록/해제
     
void input_register_device(struct input_dev *);
void input_unregister_device(struct input_dev *);
     
     
     
     
//input_dev 구조체에 추가 정보 설정 (터치스크린에서 필요)
     
static inline void input_set_abs_params(struct input_dev *dev, int axis, int min, int max, int fuzz, int flat);



//***이벤트를 이벤트 핸들러 디바이스 드라이버에 전달***
     
//기본 함수
     
void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value);
     
//버튼/키 이벤트 전달
     
static inline void input_report_key(struct input_dev *dev, unsigned int code, int value);
     
     
//상대적인 이동 크기 정보 이벤트 전달 (마우스에서 사용) 
     
static inline void input_report_rel(struct input_dev *dev, unsigned int code, int value);
     
//이동된 절대 좌표 이벤트 전달 (터치스크린에서 사용) 
     
static inline void input_report_abs(struct input_dev *dev, unsigned int code, int value);
     
//하나의 상태에 대하여 여러 이벤트가 동기되어야 한다는 것을 전달
     
static inline void input_sync(struct input_dev *dev);
 
  초기화 과정은 input_dev 구조체에 필요한 정보를 설정하고 이를 이용해서 input_register_device()를 호출하면 됩니다.
초기화 설정에서 각각의 입력 디바이스 드라이버가 이벤트 디바이스 드라이버와 연결되기 위해서는 다음 항목을 설정해 주어야 합니다.
unsigned long evbit[NBITS(EV_MAX)]; // 이벤트 타입
unsigned long keybit[NBITS(KEY_MAX)]; // 사용되는 키 타입
unsigned long absbit[NBITS(ABS_MAX)]; // 사용되는 절대 좌표 값
 
 
예를 들면, 보통 터치스크린 드라이버를 위한 초기화 값은 아래와 같습니다.
 
input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
input_set_abs_params(input_dev, ABS_X, X_AXIS_MIN, X_AXIS_MAX, 0, 0);
input_set_abs_params(input_dev, ABS_Y, Y_AXIS_MIN, Y_AXIS_MAX, 0, 0); 

evbit은 처리해야할 데이터 타입을 정의하고, EV_KEY는 버튼의 입력을 처리한다는 의미입니다. 또 EV_ABS는 절대 좌표 값을 처리한다는 의미 입니다.

keybit은 사용되는 키 값이 어떤 것이 있는지를 표현하는 것입니다. 

absbit은 이벤트 좌표 값이 형식을 말합니다. ABS_X와 ABS_Y는 각각 절대 좌표 형식의 X와 Y를 처리한다는 것입니다.

 

위에 설정 외에도 name, phys, id 값 등 필요에 따라 설정해주시면 됩니다.

 

실제 터치 동작에 따른 이벤트 전달 및 동작은

Touch Press --> Touch Move --> Touch Release

이 세가지로 구분 됩니다. 따라서 저 이벤트 전달 방식을 코드로 옮기면

input_report_key(input_dev, BTN_TOUCH, 1);
input_report_abs(input_dev, ABS_X, value_x);
input_report_abs(input_dev, ABS_Y, value_y);
input_sync(input_dev);

 

하나의 이벤트가 완료되려면 Press 된 상태와 그 위치 X 와 Y의 좌표값을 모두 전달해야 합니다. 이는 하나의 동작에 세개의 이벤트로 구성되었으나 하나의 이벤트로 알리기 위해 input_sync()를 해서 동시 발생으로 간주하도록 해줍니다. 참고로 input_sync() 함수는 EV_SYN을 전달합니다.

 

Touch Release 시의 코드는 

input_report_key(input_dev, BTN_TOUCH, 0);
input_sync(input_dev);

 

  이와 같이 디바이스 드라이버의 이벤트들이 동기화 되어서 동작하게 하기 위해서 input_register_device()에서는 EV_SYN을 설정하는 코드가 포함되어 있습니다.

 

/device/input/input.c

 

int input_register_device(struct input_dev *dev)
{
        static atomic_t input_no = ATOMIC_INIT(0);
        struct input_handler *handler;
        const char *path;
        int error;
     
     
        __set_bit(EV_SYN, dev->evbit); //이부분
     
     
     
     
}

input_event()는 input_handle_event()를 호출하는데 여기에서 EV_SYN를 체크하여 다음 Handler로 하여 전달할지 안할지 결정해서 동작합니다.

 

 

 

  이제 커널 소스의 Documentation/input/input-programming 의 예제를 보도록 하겠습니다.

 

 

#include <linux/input.h>
#include <linux/module.h>
#include <linux/init.h>

#include <asm/irq.h>
#include <asm/io.h>

static struct input_dev *button_dev;

static irqreturn_t button_interrupt(int irq, void *dummy)
{
        input_report_key(button_dev, BTN_0, inb(BUTTON_PORT) & 1);
        input_sync(button_dev);
        return IRQ_HANDLED;
}

static int __init button_init(void)
{
        int error;

        if (request_irq(BUTTON_IRQ, button_interrupt, 0, "button", NULL)) {
                printk(KERN_ERR "button.c: Can't allocate irq %d\n", button_irq);
                return -EBUSY;
        }

        button_dev = input_allocate_device();
        if (!button_dev) {
                printk(KERN_ERR "button.c: Not enough memory\n");
                error = -ENOMEM;
                goto err_free_irq;
        }

        button_dev->evbit[0] = BIT_MASK(EV_KEY);
        button_dev->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0);

        error = input_register_device(button_dev);
        if (error) {
                printk(KERN_ERR "button.c: Failed to register device\n");
                goto err_free_dev;
        }

        return 0;


 err_free_dev:
        input_free_device(button_dev);
 err_free_irq:
        free_irq(BUTTON_IRQ, button_interrupt);
        return error;
}

static void __exit button_exit(void)
{
        input_unregister_device(button_dev);
        free_irq(BUTTON_IRQ, button_interrupt);
}

module_init(button_init);
module_exit(button_exit);

 

 위와 같이 작성되어 있습니다. 이 소스코드는 하나의 버튼의 입력을 받아 입력 이벤트로 전달하는 코드입니다.

이 코드를 순서도로 본다면, 아래 그림과 같습니다.

 

 

모듈에는 하나의 module_init 및 module_exit를 매크로로 명시한 함수를 호출하게 됩니다. 이는 드라이버 초기화 진입점 및 해제 진입점이 됩니다. 해당 함수의 호출 시점은 드라이버의 형태에 따라 다르게 나타납니다. 만약 드라이버가 Built-in(커널에 포함)이라면, 커널 부팅 중 do_initcalls에 의해서, 적재가능한 모듈 형태라면 모듈이 적재될 때 해당 함수가 불려집니다.

 

 

init 시에는 GPIO 등의 필요하 자원에 따른 속성을 초기화 합니다. 

예제에서는 interrupt 를 이용하였기 때문에 BUTTON_IRQ라는 irq 넘버를 지정하여 그에 대한 interrupt handler 함수를 등록합니다.

 

request_irq(BUTTON_IRQ, button_interrupt, 0, "button", NULL);

 

필요한 하드웨어 자원을 초기화 했다면, 입력 디바이스 드라이버를 초기화 해주어야 합니다. 

입력 드라이버를 등록하기 위해선 input 디바이스 정보를 가진 자료구조가 필요한데 그것이 input_dev라는 구조체 입니다. 

 

1. input_dev 메모리를 할당

input_allocate_device()를 호출하면 커널 영역의 메모리를 할당하여 input_dev를 만들고 이를 반환합니다.

 

2. 입력 비트필드 설정

input_dev는 input 디바이스에 대한 다양한 정보를 포합하고 잇습니다. 그 중에서 제일 중요한 요소는 어떠한 이벤트를 핸들링하는냐 입니다. evbit는 디바이스가 지원하는 이벤트의 타입을 포함하고 있으며, 대표적으로 EV_KEY, EV_REL, EV_ABS, EV_MSC 등이 있습니다.

 

각각 이벤트 타입마다 추가적인 비트필드가 존재합니다. 키 이벤트일 경우, 어떤 키를 핸들링하는 지에 대한 정보가 필요하고, 절대 혹은 상대 좌표 이벤트일 경우, 어떤 축의 자표를 핸들링할 것인지, 그 최소/최대 값은 얼마인지를 설정해주어야 합니다.

 

예제에는 EV_KEY(버튼) 으로, BTN_0 키를 핸들링 하기에, keybit에 BTN_0을 설정합니다.

 

3. input_dev 등록

input_dev를 다 정의 하였다면, 입력 디바이스 드라이버를 커널에 등록해야 합니다. 

input_register_device(struct input_dev)

 

 

등록이 완료되면 이제 입력 디바이스 드라이버는 인터럽트 기다리며 버튼이 눌릴 때까지 대기 합니다.  인터럽트가 발생하였을 경우에. BUTTON_IRQ에 등록된 인터럽트 핸들러가 호출되어 입력 이벤트를 전달합니다.

 

 

모듈 init 과 유사하게 모듈 해제시에는 입력디바이스를 해제하고, 그에 필요했던 시스템 자원을 해제합니다.

 

 

 

이렇게 입력 디바이스 드라이버에 대한 개념과 예제를 설명하였습니다.

터치스크린이나 키패드 등 여러 입력 장치들에 대해서 입력 디바이스 드라이버를 만드는데 필요한 정보 및 개념이였습니다.

 

 

 

 

 

 

 

 

이미지 및 내용 참고 : 임베디드 개발자를 위한 코드로 읽는 리눅스 디바이스 드라이버, http://sonseungha.tistory.com

반응형

+ Recent posts