2010년 10월 1일 금요일

UART로 연결된 두 보드에서 PPP 프로토콜 사용하여 통신하기.

일반적으로 PPP은 dial-up connection을 위해서 사용되는 프로토콜로,  가가호호 인터넷 연결을 위한 ADSL이 도입되기 이전인 8-90년대에 가정에서 모뎀과 전화를  사용하여 인터넷에 연결하기 위해서 많이 사용되던 프로토콜이다.

그만큼 오래되고 내용도 자못 복잡하여 해당 기술의 역사와 내용을 완전히 이해하기 쉽지 않지만 (항상 그러하듯) 실제로 사용하기 위해서 모든 것을 알 필요는 없다.

일단 서버와 클라이언트상에 PPP연결은 아래와 같이 이루어진다.

서버-모뎀----------------------------모뎀-클라이언트

여기서 서버는 인터넷 제공업체의 컴퓨터, 클라이언트는 가정집의 컴퓨터라고 생각하면 된다.

모뎀을 외장 모뎀이라고 가정하면, 서버-모뎀 혹은  모뎀-클라이언트는 시리얼 포트(COM포트)를 통하여 연결되어 있을 것이고, 시리얼 포트는 내부적으로 레벨 쉬프터를 거쳐 UART 장치에 연결될 것이다.  즉 아래와 같을 것이란 얘기.

서버의 UART 장치 - 레벨 쉬프터 - COM포트 - 외장 모뎀 ------------------>>>>
>>>>-----------------외장모뎀 - COM포트 - 레벨 쉬프터 - 클라이언트의 UART장치.

먼거리의 서버와 클라이언트를 연결하기 위하여 중간에 여러가지 장치를 거치지만 결국은 서버의 UART 장치와 클라이언트의 UART 장치간의 통신을 위한 프로토콜 되겠다. 뭐가? PPP가.

(참조:
 UART는 3.3V를 사용하는데 컴퓨터 외부의 외장모뎀으로 데이터 전송시 데이터가 확실히 전달되도록 12V로 전압을 높여준다. 바로 레벨 쉬프터는 이때문에 필요하다. 이렇게 12V로 승압된 데이터 신호는 RS232C 라고 불리는 케이블을 통해서 외장 모뎀에 연결된다. )

서버 UART <----->클라이언트 UART

이를 단순화 시키면 결국 두 장치간의 UART 통신이라는 것을 알 수 있다.  UART는 위와 같은 인터넷 연결뿐만 아니라 임베디드 기기안에서 여러 장치간의 통신에  아주 많이 사용되는 방법이다.  (기기안에서의 UART 통신에는 승압이 필요 없으므로 레벨 쉬프터를 사용할 필요가 없다.)

 보통 임베디드 기기 안에서의 UART 통신에서는 대부분의 경우 HDLC라는 프로토콜을 사용하거나 혹은 더 간단하게 개발자들이 자체적으로 프로토콜을  정의하여 사용한다.  사실 PPP도 표준 HDLC 프로토콜이 조금 변형된 형태이며, 여기에 클라이언트가 서버에 접속하기 위한 Authentication, Compression, Error detection, multilink 기능등이 추가된 프로토콜이다. 따라서 임베디드 기기안에서의 UART 통신을 위해서는 굳이 HDLC프로토콜을 놔두고 PPP를 사용할 필요는 없다.

HDLC에 대해서는 아래 사이트를 참조하자.
http://www.interfacebus.com/Design_HDLC.html

하지만 때로는 필요 없을 법 했던 것이 필요해지는 경우도 있는 법. 두 장치가 UART로 연결되어 있는 상황에서 HDLC와 PPP 연결 시 실측 throughput을 비교해 보아야 할 경우가 생겼다.
--- 꼭 이런 상황이 아니라도, UART로 연결 된 두 장치간에 IP를 할당하고 socket프로그래밍을 통해 통신을 하고자 한다면, HDLC대신 PPP를 사용해야 한다.

하여간 이런 경우에 PPP를 쓰는것은 위에서 예로든 인터넷 연결을 위한 Dial up 네트워크 연결 보다 훨씬 간단한데, 이유는 Authenticaiton등을 위한 설정이 필요 없기 때문이다.

아래는 QNX OS상에서 pppd을 실행시켜 연결하는 방법이다. 아마 리눅스나 다른 유닉스에서도 비슷하게 동작이 가능할 것이다.

Receiver(Server) :
 /usr/sbin/pppd debug defaultroute /dev/ser4 updetach -crtscts 1000000 netmask 255.255.255.0 10.10.10.13:10.10.10.12 &

Sender(Client) :
 /usr/sbin/pppt debug defaultroute /dev/ser4 updetach -crtscts 1000000 netmask 255.255.255.0 10.10.10.12:10.10.10.13 &



이와 같이 설정시 PPP의 Throughput 측정 결과는 Baud rate이 1Mbps일 때473Kbps로 측정되었다.
(동일 조건에서 HDLC는 685Kbps가 측정되었다. )

PPP를 사용했을 때는 그 위에 TCP/IP를 거쳐서 사용하게 되므로 HDLC를 사용하였을 때 보다 오버헤드가 클 것이라는 점에서 위 데이터는 쉽게 수긍이 가는 수치인 것 같다.

주의할 것은 UART 디바이스와 UART 디바이스 드라이버의 설정 그리고 HDLC 프로토콜의  구현 방법에 따라 Throughput과 CPU 점유율이 크기 달라질수 있다는 점이다. 보통 UART는 1Mbps와 같이 빠른 속도로는 잘 설정하지 않는데, 이는 UART가 다소 옛 기술이라 이런 고속 동작시 CPU 사용율이 높아지기 때문에다. 특히 CPU 사용율은 데이터를 read하는 횟수와 상관 관계가 큰데 이는 read가 unix시스템에서의 시스템 콜로, 시스템 콜이 불리는 횟수가 CPU 사용율과 관계가 무척 크기 때문이다. -- 시스템 콜이 불리면 user모드에서 kernel모드로 전환하기 위해 CPU가 할 일이 무척 많다.

이 CPU 점유율 문제는 TX쪽 보다 RX쪽에서 크게 발생하는데 이는 보내는 쪽은 보내고 싶은 데이터를 한번에 write로 보낼 수 있지만, read쪽은 보내는쪽에서 한번에 보내는 크기를 모르면 여러차례에 걸쳐 read 시스템 콜을 호출하여야 하기 때문이다.

Read 쪽에서 CPU사용율을 최소화 하기 위해 시스템 콜이 자주 발생하지 않도록 한번에 많은 데이터를 읽는 것이 유리하지만, 이 경우 원하는 만큼의 데이터가 RX되지 않으면 읽기 함수가 Block되어 빠른 데이터 처리가 어렵다. 따라서 보통은 N byte 가 읽혀지거나 N byte가 RX되지 못해도 M msec이후에는 Read 함수가 return되도록 설정하여야 한다. -  readcon() 참조

또한 시스템에 따라 특정 데이터를 검출하여 해당 데이터가 RX될 때 Read함수를 return해주는 기능을 제공하기도 한다.(POSIX 호환은 아님)  이런 경우 보통 0x7E가 HDLC나 PPP에서 frame의 시작과 끝을 나타내는데 사용되므로, 0x7E를 지정하여 read 함수의 호출 횟수를 최적화하면 많은 성능 향상을 가져올 수 있다.

2010년 6월 23일 수요일

공개키 암호와 안드로이드 서명

컴퓨터 세계에서 공개키 암호를 사용하는 이유는 크게 두 가지로 나눌 수 있는데, 첫번째는 데이터를 보내는 사람을 확인하기 위함이고, 두번째는 데이터를 받는 사람을 확인하기 위함이다.

데이터를 보내는 사람을 확인:  전자서명용
특정인을 사칭하지 못하도록 하기 위함이며, 대표적인 사용 예로는 공인 인증서가 있다.
공인 인증서의 경우, 사용자는 제 3기관에서 발행한 공개키와 개인키 쌍을 발급 받으며, 이 중 공개키는 거래를 원하는 금융기관에 등록한다. 이 후 금융 거래 시 개인키로 암호화 된 개인 서명을 금융기관에 보내면, 금융기관은 이를 공개키로 풀어 개인 서명을 확인한다. 다른 사람의 개인키로 암호화한 전자 서명은 금융기관에 등록 된 공개키로는 풀리지 않으므로, 타인의 사칭을 막을 수 있다.  또다른 예는 ActiveX로 악의적 코드가 다른 회사나 개발자를 사칭하여 배포되지 않도록 전자 서명을 사용한다.

데이터 암호화: 데이터를 보내는 사람의 개인키 사용
데이터 복호화: 데이터를 보내는 사람의 공개키 사용

데이터를 받는 사람을 확인:
보내는 데이터를 안전하게 특정 수신인에게만 전달 되도록 하기를 원하는 경우이다.  이 경우 데이터를 받으려는 사람이 공개키와 개인키 쌍을 생성해서 공개키를 데이터를 보내주는 사람에게 전달하고, 데이터를 보내는 사람은 이 공개키를 사용하여 데이터를 암호화 한다. 이제 암호화된 데이터는 암호시 사용된 공개키와 쌍을 이루는 개인키를 사용하여야만 해독할 수 있으므로, 데이터 중간에 누군가 가로채어도 내용을 알 수 없게 된다.

데이터 암호화: 데이터를 받는 사람의 공개키 사용
데이터 복호화: 데이터를 받는 사람의 개인키 사용


안드로이드 애플리케이션 서명 - 데이터를 보내는 사람을 확인:
안드로이드에서는 애플리케이션 등록자를 확인하기 위해서 애플리케이션을 안드로이드 마켓에 등록할 때 애플리케이션에 전자 서명을 하여 제출하여야 한다. 이를 위해 개발자는 keytool이라는 프로그램을 사용하여 공개키/개인키 쌍을 생성하고 이 중 개인키를 애플리케이선에 전자 서명을 하기 위해서 사용 한다.  공개키는 애플리케이션을 배포할 때 함께 배포하며, 이는 애플리케이션이 설치될 때 개인키로 암호화 된 전자 서명을 확인하기 위해서 사용된다. 이로써 누군가 특정 개발자를 사칭하여 악성 코드를 배포할 수 없게 된다.

참고
1. keytool로 생성된 공개키/개인키 쌍은, 암호(패스워드)로 보호되며 key store라고 불리는 파일에 저장된다.
2. 애플리케이션에 전자 서명은 jarsigner라는 명령으로 할 수 있다. jarsigner명령 수행시 인자로 공개키/개인키가 저장되어 있는 keystore 파일과 서명을 원하는 애플리케이션 패키지 파일(*.apk)을 넘겨주게 된다. 안드로이드 1.5이상에서는 jarsigner를 직접 사용하지 않고 Eclipse안에서 서명을 수행할 수 있다.

뱀다리
혹시 왜 암호와 복호 모두에 사용 가능한 하나의 비밀키를 사용하지 않고 키를 공개키와 개인키로 나누는지 이해가 되지 않는가?  이는 비밀키의 경우 키를 전달 할 때  키가 제 3자에게 누출되는 것을 막을 수 없기 때문이다.(인터넷으로 키가 전송되는 경우를 생각해 보자)  암호와 복호에 동일한 키가 사용될 경우 3자에게 해당 키가 누출되면 더이상 데이터 보안이 불가능해 진다.  공개키/개인키를 사용할 경우 공개키는 전달되는 과정에서 3자에게 누출되어도 상관없으며, 개인키는 개인이 보관하며 타인에게 전송하지 않으므로 누출되지 않도록 해야 한다. 또한 개인키는 일반적으로 비밀키로 한번 더 암호화 하여 보관한다.즉 개인키를 가진 사람만 데이터 복호화가 가능하다.(데이터를 받는 사람을 확인하는 경우, 데이터를 보내는 사람을 확인하는 경우라면, 개인키를 가진 사람만 데이터 암호화(전자서명)이 가능)

2010년 6월 18일 금요일

비디오 신호 전송 인터페이스

임베디드 시스템에서 많이 사용하는 비디오 신호 전송 인터페이스 방법을 정리하였다.

Parallel RGB:
RGB 각각 m bit씩 3 x m 개의 데이터 라인과 hsync. vsync. 라인등을 사용한 가장 기본적인 비디오 신호 전송 방법. 기기에 내장된 LCD모듈로 영상을 전송하기 위하여 임베디드 시스템에서 가장 일반적으로 사용하는 IF.

LVDS(Low Voltage difference Signaling):
고속 데이터 전송을 위해 꼬인 구리선으로 차신호를 보내는 방법으로 일반 데이터 전송(firewire등) 뿐만 아니라 비디오 데이터 전송에 사용된다. Parallel RGB보다 훨씬 적은 수의 라인으로 구성되므로 디스플레이 패널이 기기 외부에 있을때 많이 사용됨. 이름의 LV(Low Voltage)는 5V나 3.3V 가 아닌 1.5V를 사용하기 때문에 붙은 것임. 이름에서 알 수 있듯이 차신호를 보냄으로써 노이즈에 강하다.

디지털 테스트 시스템을 위한 LVDS 이해하기
노트북PC와 TV까지 '포스트 LVDS' 도입 물결
(영어버젼:http://blog.naver.com/jkhan012?Redirect=Log&logNo=150084746813)

TMDS(Transition Minimized Differential Signaling):
DVI와 HDMI에서 사용되는 고속 시리얼 데이터 전송 기술. LVDS와 유사한 기술로 RGB 채널별로 한개의 twisted-pair를 사용하여 차신호를 보낸다.  DVI나 HDMI 모두 TMDS를 사용.
http://en.wikipedia.org/wiki/Transition_Minimized_Differential_Signaling

TSI(Transport Stream Interface):
MPEG 비디오 데이터를 전송하기 위해 사용되는 인터페이스.
TDAT, TCLK, TSYN,TVAL 4라인으로 구성됨.

PinName : Description  : Master : Slave
---------------------------------------------
TDAT       Data          Output   Input
TCLK       Clock         Output   Input

TVAL       Data Valid    Output   Input

TSYN       Packet Sync.  Output   Input



참고자료:
디지털 시대의 비디오 신호조작기술
Analog 비디오 신호를 Digital Parallel RGB로 바꾸어주는 IC
Digital Parallel RGB를 LVDS로 바꾸어주는 IC

2010년 6월 16일 수요일

안드로이드에서 C만으로 프로그램 개발하기

많은 분들이 이미 고민해 주시고 해결책을 찾아 주셔서 관련 사이트를 링크만 한다.

먼저 일반적인 NDK를 사용하여 C사용하는 방법...
Being a Developer -
- Android NDK를 이용한 C/C++ 안드로이트 프로그래밍 Hello JNI


이제, Java없이 C로 실행파일까지 만들어 버리는 방법을 살펴 보자.

오가네 - 어느 프로그래머의 책 읽기
- 안드로이드(Android) NDK로 실행 파일 만드는 법
- 안드로이드(Android)NDK 실행파일 프로젝트 예제
- android-gcc

博而不精
- 윈도우에서 c로 안드로이드 어플 개발하기

기본적으로 NDK를 사용하여 C 실행 파일 생성 및 실행이 가능하지만, 만일 안드로이드가 지원하는 ARM 플래폼이 아니거나 NDK이외의 gcc 컴파일러 사용이 필요할 경우 이것도 불가능하지 않다.  해당 내용은 "Java와 C를 이용한 프로 안드로이드 게임 개발"에 서 찾아볼 수 있다.

2010년 5월 19일 수요일

정체불명의 로그 추적하기.

개발 중 재현이 어려운 문제를 해결하기 위해 logger box를 사용한 몇 주간의 exposure test 끝에 문제를 재현하였는데 도대체 누가 출력했는지 알 수 없는 로그가 발견되었다. 이걸 어떤 모듈(실행중인 프로그램)에서 출력하는지 손쉽게 알 수 있는 방법이 없을까 고민하다가 아래와 같은 방법을 사용하였다.

bash-2.03$ find . -exec strings {} -f \; | grep "XXXX"

도대체 사용할 일 없어보였던 strings 명령을 실전에 최초로 사용한 케이스 되겠다.

보너스로, 특정 바이너리가 사용하는(필요로하는) so파일 찾는 법은 아래와 같다.

bash-2.03$ readelf -a binaryname | grep NEEDED

2010년 4월 22일 목요일

Linux 토막 지식

- 부트 옵션 "root=/dev/ram" 는, 부팅 종료 후에도 initrd를 폐기하지 않고 root file system으로 사용하겠다는 뜻이다. 즉 별도의 flash나 HDD등에 root file system을 만들지 않는 경우에 사용하는 옵션이다.
- 부팅 옵션은 .config파일의 CONFIG_CMDLINE 항목에 지정할 수 있다. 혹은 menuconfig->Boot options->Default kernel command string에서 지정한다.
- 부팅 중 initrd안에 linuxrc script가 실행되고, 실행이 끝나면 일반적으로 initrd는 폐기된다.
- 별도의 root file system이 존재할 때 root file system에 /initrd 디렉토리가 있을 경우, 부팅 종료 후 initrd가 폐기되지 않고, /initrd에 mount된다.
- vmlinux파일. ELF type
- Image. raw binary file
- zImage. Image를 gz압축한것
- bzImage. i386의 real mode 1M 메모리 제약을 위해 일정 크기 이상의 큰 kernel에서 사용.
- make mrproper : 커널소스를 초기 상태로 되돌린다. .config파일까지 초기화되므로 주의. mrproper는

참고 자료:
- uImage와 zImage차이설명
- 임베디드 시스템 엔지니어를 위한 리눅스 커널 분석
- mount

vi에서 ^M 제거하기

:1,$s/^M//g
  혹은
:%s/^M//

1,$ : 첫번째 라인에서 $(마지막) 라인까지 적용.
 여기서 1,$ 대신 모든 라인을 뜻하는 % 로 바꾸어 사용할 수 있음.
s : substitute .
/ : 구분자
^M : Ctrl Key + v key + m key 를 차례로 모두 누를것. 누르는 동안 앞에 누른 키를 계속 누르고 있을 것.
// : 두 구분자 사이에 아무것도 없으므로 ^M이 아무것도 없는 것으로 치환됨 .
g: 한 라인에서 ^M이 여러개 있을 경우 이들 모두를 바꾸기 위해서 사용. 여기서는 한 라인의 마지막에만  ^M이 있으므로 굳이 g를 사용할 필요가 없다.


참고
^:캐럿: 정규식에서 문장의 시작 위치를 뜻함. vi에서 "^"를 누르면 해당 라인의 첫 글자로 이동. 반면에 "0"(Zero)을 누르면 행의 첫 글자가 아닌 행의 첫번째 열로 이동.  하지만 위의  ^M앞의 ^는 이것과 상관없는 control문자를 뜻함.
$:달러: 끝의 의미가 있음. 여기서는 마지막 라인을 의미, 정규식에서 사용되면 문장의 끝을 의미. vi에서 "$"을 누르면 현재 행의 마지막열로 이동함.

2010년 4월 8일 목요일

Linux Logging : syslogd vs klogd

syslogd는 유저 어플리케이션이 syslog APIs를 사용하여 남기는 로그를 기록하고 관리하기 위해서 사용되는 데몬이다. 하지만 커널 프로그램에서는 메세지를 남기기 위해서 사용자 어플리케이션용인 syslog APIs를 사용하지 못하기 때문에 syslogd으로 로그 메세지를 남길 수 없다. 따라서 커널 프로그램에서 printk를 사용하여 출력하는 메세지는 바로 syslogd로 가지 못하며, klogd이 받아 이를 syslogd으로 넘겨주게 된다. 참고로 유저 어플리케이션에서 syslogd로 메세지를 남길 때는 아래 함수들을 사용한다.

#include < syslog.h >


void openlog( char *ident, int option, int facility)
void syslog ( int priority, char *format, ...)
void closelog( void )

커널 로그 메세지는 dmesg 명령으로 볼수 있으며, /proc/kmsg 에서도 확인할 수 있다.

#dmesg

혹은 klogd을 죽이고
#cat /proc/kmsg

printk는 커널내의 메모리상의 circular로깅 버퍼에 기록되므로 인터럽트 처리 루틴에서도 호출이 가능하다. klogd은 항상 이를 모니터링하며 데이터를 읽어서 syslogd로 보내주는데 이때 circular buffer가 clear되므로 /proc/kmsg를 사용하여 모니터링하고자 할 때는 klogd를 죽여야 한다.

만일 기대한 로그가 보이지 않는다면, 현재 로그 레벨이 너무 높아서일 수 있다. 높은 로그 레벨에서는 높은 우선 순위의(중요한) 메세지들만 기록된다. 로그 레벨은 값이 작을수록 높은 우선 순위를 가지며, 0~7사이의 값을 가진다.


아래 명령으로 현재 로그 레벨을 알 수 있다.

# cat /proc/sys/kernel/printk
4 4 1 7

이는 각각 현재 로그 레벨, 기본 로그 레벨, 최소 허용 로그 레벨, 부트시 기본 로그 레벨에 해당한다. 이중 현재 로그레벨은 아래와 같이 변경할 수 있다.

echo 8 > /proc/sys/kernel/printk

가장 낮은 로그레벨이 7이므로 위와 같이 8로 설정하면, 모든 커널 로그 메세지를 볼 수 있다.

참고 사이트:
http://www.linuxjournal.com/article/4036?page=0,2

2010년 3월 11일 목요일

리눅스 드라이버 작성을 위한 Bottom Half 선택하기

리눅스 드라이버 작성 시 bottom half 처리가 필요할 경우 선택 가능한 몇 가지 방법이 있다. 필요에 따라 적절한 방법을 선택하면 되는데, 이를 위한 일반적(절대적이지는 않지만 대부분의 경우 잘 동작하는...)이고 간편한 선택 방법은 아래와 같다.

1. 해당 작업이 sleep이 가능하거나 sleep이 필요할 경우 : Work Queue
2. 1이 아니며 빠른 처리가 필수적인 경우: Tasklet

tasklet은 빠른 응답이 필요한 경우에 work queue보다 더 적합하지만 interrupt context에서 실행되므로 해당 작업 도중에 sleep이나 선점이 일어날 수 없다. tasklet은 softirq를 사용하여 구현되는데, 디바이스 드라이버 작성시에는 softirq보다 tasklet사용이 권장된다. 하지만 softirq 사용이 필요한 경우가 있을 수도 있다. softirq와 tasklet의 가장 구별되는 특징은 tasklet은 여러 tasklet이 동시에 실행되지 않음이 보장된다는 점이다. 따라서 동기화에 대한 고려가 덜 필요하므로 softirq 보다 쉽게 사용이 가능하다.

tasklet과 softirq와의 관계와 마찬가지로, work queue는 kernel thread를 사용되어 구현되어 있다. work queue는 kernel thread를 직접 사용하는 것 보다 훨씬 쉽게 사용할 수 있도록 구성되어 있을 뿐만 아니라 kernel thread를 직접 만들어서 사용할 때 할 수 있는 거의 모든 일을 work queue를 사용하여 구현할 수 있다. 따라서 디바이스 드라이버 작성자가 굳이 work queue대신 kernel thread를 직접 생성하여 사용할 필요가 없다. work queue는 kernel thread로 구현되었으므로 process context에서 실행되고 따라서 sleep이 가능하다. 대신 동기화에 대해서는 디바이스 드라이버 작성자가 직접 고려해 주어야 하며, process context지만 kernel thread이므로 user space에 대한 접근은 불가능하다.

2010년 2월 15일 월요일

다양한 serial 통신 이해하기

UART
가장 대중적으로 사용되는 시리얼 통신은 UART device를 사용하는 것으로 보통 RS-232C transceiver와 함께 쓰인다. 하지만 RS-422이나 LIN등 다른 IF도 많이 사용된다. UART는 RX/TX 라인이 별도로 존재하고(full duplex) 별도의 clock라인은 사용하지 않는다. 따라서 양측이 서로 Baud rate를 맞추어야 통신이 가능하다. 즉 Asyn.통신이라는 말씀. 따라서 UART와 함께 사용되는 RS-232C도 동일한 특성을 가진다. 하지만 LIN transceiver를 사용할 경우에는 RX/TX선을 따로 가지는 대신 1개의 선만 사용하므로 full duplex가 아닌 half duplex로 동작하게된다. 또한 RS-232C는 1:1통신용으로만 사용되지만, 다른 IF 사용시 여러 장치간 통신에 사용이 가능하다.

UART에서 transceiver를 별도로 사용하는 이유는 무엇일까? 동일 보드에서 UART를 사용하여 통신할 경우 UART <-->UART 연결을 사용할 수 있지만, 외부 디바이스간의 통신에는 보다 멀리 전송하기 위해서 level shifter등을 사용하여 전압을 승압하는 것이다. 또한 다양한 전송 IF를 사용하여 1:1전송 뿐만 아니라 1:n 전송을 통한 네트워크 구현도 가능하다.

http://blog.naver.com/hjsnyh?Redirect=Log&logNo=80020142147

LIN- Local Interconnect Network
LIN은 자동차 업계에서 많이 사용하는 저속 차량용 네트워크로, UART를 사용한다. LIN transceiver를 통하여 network는 RX/TX구분없이 1 line을 사용하여 통신이 이루어 진다. 즉 RS232C에서는 RX/TX를 별도 라인으로 사용해서 full-duplex로 동작하는데 반하여 LIN 에서는 half-duplex로만 동작하는 Async. 통신방식이며 I2C, USB등과 유사하게 Master 기기가 통신을 시작하는 방식을 사용한다. 보통 20kbps이하의 저속 통신에 사용되며, 최근에는 CAN등에 자리를 내주고 있다. Master라는 것은 seiral통신에서 통신을 시작할 수 있는 권한이 있는 디바이스로, Slave장치는 Master장치가 통신을 요청할 때 까지 어떠한 통신도 시작할 수 없다. 각 serial통신 방법에 따라 Master가 1개만 존재하거나 여러개 존재할 수 있으며, CAN같은 경우 모든 장치가 Master/Slave구별 없이 원하는 시점에 메세지 전송이 가능하다. USB장치의 경우에는 Master/Slave라는 용어 대신 Host/Device라는 용어를 사용한다.

http://blog.naver.com/cybercall?Redirect=Log&logNo=120032068893


SPI - Serial Peripheral Interface Bus
SPI는 또 다른 serial장치로 CS, MISO, MOSI, SCK 4개의 선을 사용한다. RX/TX라인이 별도로 존재하고, CLK이 있으므로 full duplex, Sync.전송 방식이다. SPI는 Master/Slave 장치가 구별되며 Master에서 데이터를 보내는 양 만큼 Slave에서 데이터가 들어오게 된다. 이는 Master/Slave 양쪽에 shift register를 사용하기 때문으로 Master측에서 Tx만 필요한 경우 데이터를 보내는 순간 Slave에서 들어오는 데이터는 무시하면 된다. 반면 슬레이브에서 보내는 데이터를 읽어야 할 경우 Master는 dummy바이트를 보냄으로써 Slave로 부터 데이터를 받을 수 있다.
보통 1:1 통신용으로 많이 사용되지만, 1개의 Master에 여러개의 Slave를 붙일 수도 있다. Master에 CS를 여러개 사용하여 각각을 Slave의 CS로 사용하여 여러개의 Slave를 서로 독립적으로 control하도록 할 수도 있고, Master에 한개의 CS를 모든 Slave에서 공유하면서, 한 Slave의 MISO를 다음 Slave의 MOSI로 연결하여 daisy-chain을 구성하여 여러개의 Slave를 연결하기도 한다.

http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus


I2C- Inter Integrated Circuit
I2C는 2개의 선만을 사용하며 이는 각각 data와 clk에 해당한다. clk이 있으므로 Sync.이며 data를 위한 1라인만 사용하므로 TX/RX를 1선으로 처리해야 하므로 half duplex전송만 가능하다. I2C버스에서는 여러개의 Master와 Slave 장치가 연결될 수 있다. half duplex 특성 상 TX/RX가 동시에 발생할 수 없기 때문에 I2C는 Master가 모든 통신을 시작하며 Slave 장치는 여기에 응답만 가능하다. 이와 같은 통신 특징은 USB에서도 찾을 수 있다. (하지만 USB는 다중 Master를 지원하지 않는데 반하여 I2C는 다중 Master를 지원한다) I2C는 여러개의 Master를 허용하므로 이들이 동시에 메세지를 보내기 시작할 경우 bus는 0을 보낸쪽이 차지하게 되며 1을 보낸 쪽은 전송을 중단한다. 동일한 방법이 CAN bus에서도 사용되나 CAN의 경우 모든 장치가 Master로써 동작한다.(CAN에서는 모든 장치에서 Tx 시작이 가능하므로 Master/Slave를 굳이 구별하지 않는다.) 또한 CAN은 CLK이 없는 Asyc. 통신인 반면 I2C는 CLK을 사용한다. I2C에서는 다중 Master를 지원하지만 일반적으로 1개의 Master를 사용하여 시스템을 구현하는 경우가 많다. I2C는 표준 모드에서 100kbps, 고속 모드에서 400kbps로 동작한다. I2C는 SPI에서와 같은 CS가 존재하지 않으므로 각 장치마다 7bit address를 부여하여 이를 사용하여 target장치를 지정한다.

USB
USB장치도 I2C와 같이 Master(USB에서는 Host라는 용어를 사용)만이 트랜잭션을 시작할 수 있으며 Slave(USB에서는 device라는 용어를 사용)는 여기에 응답만 가능하다. 하지만 USB는 clk을 위한 선이 별도로 없다는 점에서 I2C와 다르게 Asyn. 통신이며 다중 Master(Host)도 허용되지 않는다. USB는 Frame이란 개념을 도입하여 한 Frame안에 여러 슬레이브 장치와 Master간의 통신이 포함될 수 있다. 하지만, Slave간의 통신은 불가능하며 Frame이 주기적으로 보내지지만 CLK이 따로 존재하지는 않기 때문에 Sync.통신은 아니다. 따라서 USB전송모드중 한가지인 isochronous를 사용하여 audio데이터를 전송할 경우, buffer가 충분히 크지 않다면 clock drift등으로 인한 buffer overrun이나 underrun이 발생 할 수 있다.

UART가 외부 전송을 위해 RS-232C나 LIN등을 사용하듯이 USB는 처음부터 외부 전송을 목적으로 만들어졌다. 하지만 최근에는 내부 데이터 버스로도 사용되고 있으며 , 이를 위해서 HSIC라는 I/F가 정의되었다.  HSIC는 USB의 sub spec.으로 high speed 전송만 지원하고 전송 거리가 10cm등으로 제약되어 있다.

I2S
I2S는 오디오 신호 전송용 serial통신으로 TX, RX, CLK, Frame Sync. 4개의 선으로 이루어져 있다. I2S를 통해서 다양한 형식의 PCM 오디오 데이터가 전송될 수 있다. 시스템에서 오디오는 보통 한방향으로만 전송되는 경우가 많으므로 TX/RX 중 하나만 사용하여 3개의 선만 사용하는 경우가 많다.

CAN
CAN은 SWCAN과 DWCAN이 존재한다. SWCAN의 경우 low speed(33.3KBit/s ~ ) 전송용으로 사용되며 1 wire통신이다. DWCAN의 경우에는 고속 전송용으로(~1MBit/s) 사용되며 이를 위해 2 -wire를 사용하며, 두 선은 각각 +- 만 변경된 동일한 신호를 가진다. CAN bus에는 여러개의 모듈이 연결되고 Master/Slave 개념 없이 서로 동등하게 통신이 이루어진다. 이를 위해서 I2C에서 사용한 것과 같은 arbitration란 개념이 필요하다. 즉 두 개 이상의 모듈이 동시에 메세지를 보내기 시작할 경우 메세지 ID가 작은 값을 가진 메세지가 bus를 차지하게 된다. 즉 0과 1이 동시에 bus에 실리면 bus에는 0이 실리게 되고 1을 전송하는 모듈은 전송을 중단하여야 한다. 하지만 I2C와 다르게 모든 장치가 메세지를 보낼 수 있으며 별도의 CLK라이을 사용하지 않는 ASync. 통신이다.

MOST50
차량용 멀티미디어 데이터 전송용 버스로 MOST25/150에서는 광통신을 사용하지만 MOST50에서는 wire를 사용한다. MOST50의 경우 48kHz마다 1 frame - 128 byte데이터가 MOST ring을 통해 전송된다. 이와 같은 frame은 Timing Master기능이 있는 특정 모듈이 만들어 보내며, 차례로 MOST ring에 포함된 모든 장치를 지나가게 된다. 각 장치는 해당 frame의 빈곳에 자신의 데이터를 넣어서 다음 장치로 재전송하게 된다. MOST ring에는 Timing Master이외에 Network Master, Connection Master, Power Master등 다른 Master기능을 가진 장치가 존재한다. 하지만 USB나 I2C와 다르게 Master가능을 가지지 않는 장치들 사이에도 서로 통신이 가능하며 Master의 도움없이 메세지 전송을 시작할 수 있다. 128byte의 MOST frame은 크게 세 부분으로 나뉘는데 각각 control data, Stream data, Packet data 영역이 된다. Control data영역으로 일반적인 용도의 commend나 메세지를 정의해 서로 주고 받을 수 있으며, Packet data영역은 주로 대용량 데이터 전송에 사용된다. 이 영역을 통하여 TCP/IP 데이터등을 전송할 수도 있다. Stream data영역은 DVD나 CD데이터와 같이 Sync.데이터 전송을 위해 사용하며, 사용 전 Connection Master를 통해 Stream data 영역안의 특정 위치를 해당 용도로 미리 할당받도록 되어 있다. 따라서 이후 아무리 다른 영역의 bandwith가 부족해 져도, 미리 할당받은 영역을 통해서 Sync.한 데이터 전송이 가능하다. 하지만, 이 영역은 특성상 에러가 발생하여도 재전송을 할 수는 없다. 기본적으로 MOST ring은 Timing Master가 만들어내는 clk을 모든 장치가 공유하여 사용하므로 Sync.전송이 가능하며 이로 인하여 audio/video등 multi-media데이터 전송시 clock drift문제등을 걱정할 필요가 없다.

2010년 1월 26일 화요일

NAND flash memory 이해하기.

Block
- NAND flash는 여러개의 Block으로 구성되며, Block단위로만 erase가 가능함.
- 64KByte ~ 512KByte의 크기를 가짐.
Page
- 하나의 Block은 보통 512Byte~8KByte 크기를 가지는 다수의 page들로 구성됨.
- Page는 NAND flash의 읽기 및 쓰기의 기본 단위로, byte 혹은 word 단위로 읽고 쓸수 있는 NOR flash에는 없는 개념이다. 즉 읽기 쓰기가 byte단위로는 불가능하기 때문에 driver에서 이를 고려하여 주어야 한다.

OOB(Out of Band)- Page마다 따라오는 수~수백 바이트 정도 크기의 extra 데이터 영역으로 16의 배수 바이트인 경우가 많다. spare영역이라고도 불린다.
- 이 영역은 사용자에게는 숨겨진 영역으로 아래와 같은 용도로 사용됨
  1. Bad Block Marking : 특정 블록이 bad block일 경우 한 Block안의 첫 page 혹은 마지막 page의 OOB에 이를 표시함. 예를들어 최근에 출시되는 삼성 NAND는 공장 출하시부터 존재하는 bad block을 표시하기 위해서 bad block의 마지막 page첫 Byte를 Non-FF value로 표시함. 이는 NAND flash별, 제조사별로 다르며 해당 디바이스의 data sheet에서 확인해야 한다.
  2. ECC(error correction codes)
  3. File System Info.: 특정 file system은 이부분을 사용하여 구현됨.
이 영역은 대부분 r/w가 모두 가능함. 하지만 이 영역에 공장 출하시부터 존재하는 Bad Block Marking 정보가 지워질 경우 이 정보를 다시 살릴 수 있는 방법이 없으므로 절대로 OOB영역의 bad block 정보를 지우지 않도록 주의하여야 함. 필요시 이 정보를 사용하여 BBT를 작성하게 됨.


SLC/MLC- NAND flash의 type에는 SLC/MLC가 있는데 이는 각각 Single Level Cell/Multi Level Cell을 뜻함.
- SLC는 MLC보다 수명이 10배가량 길지만 가격이 비쌈. 따라서 write가 자주 발생하는 데이터용으로 적합.
- MLC에는 고용량이면서 write가 자주 발생하지 않는 데이터에 적합. (ex, MP3, video등 multimedia files)

BBT (Bad Block Table)- BBT는 boot loader나 flash관련 tool을 사용하여 flash를 erase 할 때 OOB를 참조하여 만들 수 있으며, Linux의 경우 kernel과 boot loader간에 BBT생성 규칙과 구조에 대해서 상호 협의가 되어 있음.

- BBT는 flash file system에 따라서 사용하기도, 사용하지 않기도 하므로 필수적으로 필요한 것은 아님.
- BBT를 만들어 놓으면 특정 block의 bad 여부를 빨리 확인할 수 있지만, BAD block 데이터가 OOB의 데이터와 항상 sync.가 되도록 주의하여야 하며, BBT를 기록하려는 block이 BAD block일 경우 어떻게 처리해야 할 지 등도 고려하여야 함.
- BBT는 두 개의 Block을 사용하며 NAND flash내의 마지막 Block에서부터 거꾸로 non-bad block을 찾아, 첫번째 발견된 non-bad block이 primary BBT, 두번째로 발견되 non-bad block이 secondary BBT가 됨.
- BBT에는 한 Block당 2bit를 사용하여 NAND flash 전체의 Block의 상태를 기록하는데, 각각의 Block은 "good", "bad" , "reserved" 세개의 상태로 표현됨.
- File System에서는 "good"으로 표시된 영역만 사용함. BBT가 저장된 Block은 "reserved" 로 표시하여 File System에서 덮어쓰지 못하도록 알려줌.


그 외 특성- NAND flash로 부팅하기 위해서 첫번째 sector에 boot loader가 위치해야 하는데, 첫 sector가 bad block이면 boot loader가 위치할 수 없으므로, 대부분의 제조사는 1st block이 bad block이 아님을 보증함.
- NAND는 NOR와 달리 읽기 횟수에도 제한이 있다. NAND에서는 매번 특정 블럭을 읽을때마다 해당 정보를 저장하는 전하가 약해진다. (물론 정보를 잃은 block은 erase후 다시 사용가능하다) 따라서 읽기 전용 파일이라 하더라도 해당 정보를 너무 여러번 읽어 데이터가 지워지기 전에 다른 곳으로 옮겨서 저장하는것을 고려하여야 한다. 또한 전체 파일 시스템 내에 읽기 전용 블록이 고정되어 있을 경우, 쓰기 가능한 영역에 erase가 집중되어 해당 영역의 수명이 짧아지는 문제도 발생할 수 있다(NOR도 마찬가지). 따라서 NAND용 flash file system은 설계 시 읽기 전용 블록의 읽은 횟수를 count하여 데이터가 유실되기 전에 다른 블록으로 옮겨 줌으로써, 데이터의 유실을 막고 flash erase가 읽기 쓰기 영역에만 집중되는 것을 피하도록 설계되어야 한다.
- NAND flash를 부팅 장치로 사용하는 경우 부트로더와 OS 영역은 일반적으로 file system의 관리를 받지 못하는 영역으로, flash의 읽기 수명이 해당 제품의 예상 수명보다 짧을 경우에는 해당 영역을 주기적으로 지운 후 다시 기록하여 주거나, 부팅 실패시 backup 영역에서 부팅을 재시도하도록 하는 등의 대책을 세워야 한다. 이는 해당 시스템의 NAND controller와 부트로더의 구현에 따라 적절히 설계되어야 한다.
- NAND flash는 NAND controller의 도움을 받아야만 부팅장치로 사용될 수 있다. 만약 NAND controller가 HW적인 ECC를 지원한다면 부팅 속도가 NOR보다 빠를 수도 있다. 최근의 SoC들은 대부분 HW적인 ECC및 부팅기능을 지원하는 NAND flash controller를 가지고 있다.

참조 링크http://wiki.openmoko.org/wiki/NAND_bad_blocks
NAND bad block management by uboot and kernel
NAND 플래시 메모리의 이해
http://www.ibm.com/developerworks/kr/library/l-flash-filesystems/