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 함수의 호출 횟수를 최적화하면 많은 성능 향상을 가져올 수 있다.