자작 USB-JTAG과 OpenOCD 연동

  상용품 보드 리버스 엔지니어링시 JTAG 연결이 필요한데 자작한 USB-JTAG을 주로 사용한다.
  두개를 만들었었는데 첫번째 USB-JTAG은 USB 클라이언트 칩을 이용해 윈도우즈용 디바이스 드라이버까지 제작해 사용 했었다. 단점이라면 USB 1.1을 사용해 속도가 느리고 OS가 바뀔때마다 디바이스 드라이버를 다시 만들어야 한다. 그 때는 32비트 Windows XP용으로 드라이버를 만들어 사용했는데 운영체제를 64bit Windows 7으로 바꾸면서 무용지물이 되었다.
Windows 7에서는 디바이스 드라이버를 만들어 정식으로 사용하려면 M$에 돈을 내야 된다나 뭐라나... 요놈은 Linux용 드라이버 만들어서 Linux에서만 사용해야 겠다.

[첫번째 자작 USB-JTAG]

[두번째 자작 USB-JTAG]

  두번째 USB-JTAG은 USB-RS232 컨버터를 내장시켜 해당 USB 컨버터 회사에서 제공하는 드라이버를 사용하고 운영체제에서는 시리얼 터미널로 연결해 사용했다. 속도 증대를 위해 TMS320F2812를 적용했는데 내장된 SPI엔진을 JTAG용으로 사용하면서 속도가 무지 빨라졌었다. 원래 SPI 통신과 JTAG 통신은 다르지만 어느 속도 까지는 사용이 가능하다.
  SoC마다 차이가 좀 있지만 ARM9TDMI와 EJTAG에서는 TCK 속도를 무려 8MHz까지 올릴 수 있었다. 덕분에 30KB정도 되는 부트로더가 JTAG으로 불과 수~수십초 만에 프로그래밍이 된다.
  요놈의 단점이라면 새로운 디바이스를 지원하려면 그때 마다 해당 디바이스에 맞게 JTAG 코딩을 해줘야 한다. ARM계열이라면 ARM7TDMI, ARM9TDMI등에 맞게 Embedded-ICE 기능을 넣어 줘야 하고, MIPS는 EJTAG을 버전 별로 구현해 줘야 한다.
EXTEST를 이용하는 디바이스라면 해당 칩의 BSDL자료를 구해 만들어 줘야 한다. 때문에 해당 메뉴얼들을 다 찾아보고 정독하고 구현하고 안되면 다른 예제 구해다 분석해서 만들어 써야 했다. 요짓을 한 열댓번 하니 토나올 정도로 어렵고 구찮다.
  그래서 이번엔 두번째 만든 USB-JTAG을 OpenOCD라는 아주 훌륭한 툴과 연동 시켜봤다.
OpenOCD의 기본 연결은 병렬포트이나 지금은 병렬포트가 달린 PC를 보기 힘들다. USB기반의 다양한 JTAG 하드웨어들이 OpenOCD와 연동이 가능한데 연동 되는 칩셋이 주로 FTDI사의 것들이다. 내가 갖고 있는 보드중 가능한게 있나 찾아 봤으나 없다.
  자작한 USB-JTAG은 타겟과 호스트측이 완전히 isolation 되어 있고 타켓측 JTAG TTL전압이 3.3V, 5V둘다 사용가능해 나름(?) 훌륭하게 잘 만들었다고 혼자 생각한다. 그래서 OpenOCD와 연동시켰다.
  우선 OpenOCD 소스를 구해 분석을 시작 한다. 남이 짜놓은 수십메가바이트 소스를 보자니 가슴이 답답하고 속이 울렁 거린다. 처음 Embedded Linux 커널 포팅 할 때 500MB 커널 소스 풀어 놓고 느꼈던 까마득함을 간만에 느꼈다.
  처음부터 욕심을 내어 FTDI 칩셋에서 지원하는 MPSSE기능을 에뮬레이션 해보려고 했으나 찾아봐야 할게 너무 많아 우선 쉽게 병렬포트 디바이스를 에뮬레이션하는 방향으로 잡고 시작 했다. OpenOCD 소스에서 parport.c 디바이스 핸들링 하는 부분을 다 뜯어 고쳐 자작한 USB-JTAG에 물려 주었다.
  속도는 일반 병렬포트의 반밖에 안된다. 정말 느리다. 8MHz TCK를 사용하다 500KHz도 채 안되는 속도를 사용하려니 답답하다. 그러나 OpenOCD에서 지원하는 모든 디바이스를 아주 쉽게 사용 할 수 있다는 장점이 속도 문제를 덮어 버렸다.
  OpenOCD 연동 작업후 처음 적용해본게 S3C6410이다. ARM11코어 인데 ARM11용 JTAG 디버그 프로토콜 메뉴얼 보면서 구현 하려다 OpenOCD와 연동 시키니 환상이다. 수천만원 빚을 바로 갚아야 하는데 빌려준사람이 '그거 그냥 너 가져!' 라고 하는 소리를 들었다고나 할까?
  JTAG속도가 느리므로 다음과 같은 과정으로 개발을 진행 하였다.
  S3C6410내부에 8KB 정도 되는 SRAM이 있는데 여기에 PLL, UART, DDR 초기화 및 NAND 플래시 프로그래밍 기능만 넣어 부팅 시킨다. 그러면 OpenOCD에서는 최대 8KB만 써넣으면 되므로 저속 TCK는 문제가 되지 않는다.
  실제 위 코드를 구현해 빌드해 보니 약 4KB, OpenOCD로 SRAM에 다운로드하는데 약 30초 걸린다. 나머지 수십KB 본래의 부트로더 바이너리는 UART를 이용해 DDR에 다운로드후 NAND에 쓰면 끝. 이후 펌웨어 업데이트는 부트로더 기능을 사용하면 되므로 대용량 데이터 전송에 JTAG은 더이상 쓰지 않아도 된다.
  좋은 툴을 사용하니 손발 고생이 줄어들었다. 움하하....


<> 2015/07/02 내용 추가
  위에서 설명 한 것 처럼 UART를 이용한 병렬포트 모사 방식은 일단 좀 느리다. 속도 증대를 위해 처음엔 FTDI의 MPSSE 기능을 모사 하려고 했으나 자료들 뒤져 보니 복잡하다.
  OpenOCD 소스를 이리저리 뒤져 보던중 Altera의 USB-Blaster라는 하드웨어용 드라이버 소스가 눈에 들어 온다. 잠깐 뒤적 거려 보니 USB-Blaster라는 하드웨어를 리버스엔지니어링으로 동작을 분석해 UrJTAG에 붙여 놓은걸 OpenOCD에 적용 시켜 놓은 것이 었다.
  소스를 보니 하드웨어 동작에 대한 비교적 자세한 설명이 소스안에 주석으로 표기되어 있었다.
  USB-Blaster동작을 자작한 첫번째 및 두번째 USB-JTAG 하드웨어에 펌웨어로 기능을 모사해 넣었다. 그리고 OpenOCD의 usb_blaster.c 드라이버 파일중 USB bulk 전송 부분을 모두 다시 코딩하여 자작한 2개 USB-JTAG 하드웨어와 연동 되도록 만들었다.
잘 된다. 움하하... 난 역시 대단해...

  속도 비교를 해봤다. S3C6410의 내부 SRAM에 다운로드하는 전송 속도이다.

 - 첫번째 USB-JTAG (병렬 포트 모사): 구현 하지 않음
 - 두번째 USB-JTAG (병렬 포트 모사): 약 140[byte/s]
 - 첫번째 USB-JTAG (USB-Blaster 모사): 약 330[byte/s]
 - 두번째 USB-JTAG (USB-Blaster 모사): 약 3790[byte/s]

TCK 속도를 추정해 보자면 위에서 부터 200~300KHz, 500~700KHz, 6~7MHz 정도 되는듯 하다. USB-Blaster 모사로 구현한 첫번째 USB-JTAG은 실제 병렬 포트를 사용할 때와 비슷한 환경이 되고, 두번째 USB-JTAG은 6MHz로 고정된 Altera USB-Blaster와 비슷한 환경이 될 듯 하다.
덕분에 OpenOCD 연동 작업이 상당히 쾌적해 졌다.

JTAG 핀 탐색 및 I2C 분석기 (JTAG pin identifier & I2C sniffer)

  이번엔 리버스 엔지니어링시 있으면 상당히 도움이 되는 툴을 하나 만들었다.
오래전에 만들어 쓰고 있었으나 얼기설기 대충 만들어 쓰다 이번에 케이스와 USB 인터페이스까지 짜넣어 쓸만하게 만들었다.
  주변 칩 제어에 많이 사용되는 I2C 통신 분석기 (I2C sniffer)와 JTAG 핀 구성이 어떻게 되는지 핀 맵을 찾아주는 JTAG 핀 탐색기 (JTAG pin identifier)이다.
한 개에 두가지 기능을 넣었다.
  메인보드는 흑백 LCD가 부착된 무선 전화기 보드를 사용했는데 ATMEGA128기반에 32KB SRAM이 외부에 부착되어 있어 작은 데이터 로깅용도로 훌륭했다.

  리버스 엔지니어링을 시작 하려면 CPU의 부트 시퀸스를 가로채야 한다.
CPU 부트 모드에 따라 많이 다르게 접근을 해야 하지만 JTAG을 지원 한다면 JTAG을 이용해 좀더 쉽고 빠르게 접근할 수 있다.
  이미 만들어진 보드에서 JTAG핀을 찾기란 쉬울 수 도, 어려울 수 도, 아니면 아예 불가능 할 수 도 있다.
보드에 JTAG 핀으로 의심해 볼 만한 핀들을 이용해 TRS, TMS, TCK, TDI, TDO등 JTAG 핀을 자동으로 찾아 주면 얼마나 좋을까? 그래서 만들었다.

  일전엔 자동차용 네비게이터로 디지털 오실로스코프를 만든적이 있다 (링크).
해당 모델을 리버스 엔지니어링 할 때 아주 막막했던게 LCD 디스플레이 부분이었다. 다른 네비게이터와 좀 다르게 BT1611AG라는 별도 대만산 LCD 컨트롤러를 쓴 모델이었는데 I2C 통신으로 초기화를 하는듯 하였다. 어떻게 초기화를 해야 하는지 자료가 없어 I2C sniffer가 필요한 상황에 이번에 만든 I2C sniffer가 아주 중요한 역할을 해주었다.

  우선 만들어 놓은 작품(?)을 보면 아래 사진과 같다.


[케이스에 우겨 넣은 모습]

  위 사진의 녹색 기판이 무전 전화기 보드이다. 그 위에 작은 청색 보드는 USB-RS232 컨버터이다. USB로 부터 나오는 5V전원을 사용하고 운영체제에서는 RS232 시리얼 포트 (COMx)로 인식된다. 시리얼 터미널을 이용해 접속한다음, 명령을 입력하는 방식으로 사용하면 된다.
  그 아래 길게 누워있는 똥색 기판은 아주 오래전 마이크로마우스 만들때 쓰던 RS232 transceiver 보드 이다. 무선전화기 보드의 UART 전압 레벨은 3.3V인데 USB-RS232 컨버터의 TTL 레벨은 5V라 TTL끼리 접속하려면 레벨 쉬프팅을 해야하는데 귀찮아서 RS232 버스라인을 그대로 쓰기 위해 우겨 넣었다.
케이스는 새로텍이라는 회사에서 만든 각종 메모리 카드 백업용 외장하드(?)를 사용했다.


[완성]

  S3C2440 CPU에서 BT1611AG로 전송되는 I2C 명령을 I2C sniffer로 잡아낸 결과는 아래와 같다.


[I2C sniffing 결과]

  'S'는 START, 'A'는 ACK, 'N'는 NACK를 의미하고 [xx]는 I2C 버스라인에 뜨는 16진수 8비트 데이터 이다. 위 이미지 예시처럼 I2C 클럭 속도는 약 66KHz정도 되고 뿌려지는 데이터들을 볼 수가 있다.
잡힌 데이터를 모아 사용하여 정상적으로  LCD 사용이 가능해졌다. 움하하...

  다음은 JTAG 핀 탐색 기능.
최근 S3C6410 보드의 JTAG 핀 맵 찾을 때 썼는데 수초 이내로 TRS, TMS, TCK, TDI, TDO 5개 핀 배열을 찾아 주었다.


[S3C6410보드와 연결]

[S3C6410의 JTAG 핀맵 찾기 결과]

  S3C6410의 경우 내부에 ARM11 core와 ETM모듈, 2개 디바이스가 daisy chain으로 연결되어 있어 각각 2개 ID 검색이 가능하다. 위 이미지를 보면 CPU ID는 0x07b76f0f, ETM ID는 0x2b900f0f가 TMS-TDI-TDO-TRS-TCK 조합으로 검색 되었다.
  위와 같이 모든 조합에 대해 ID 검색과 10101010 비트 배열로 bypass 테스트를 수행하여 모두 1이거나 모두 0인 결과를 제외한 리턴값을 도시해 주고 그 때 JTAG 핀 배열 값을 표기해 준다. 덤으로 몇 개 디바이스가 daisy chain으로 연결되어 있는지 갯수까지 표기해 준다.
누가 만들었는지 프로그램을 기똥차게 잘 짰다. 크크크...

12.5MSPS 자작 디지털 오실로스코프

  2000년즘 아르바이트해서 모은 돈으로 청계상가에서 40MHz 아날로그 오실로스코프를 하나 샀었다. 그때 2족 보행 로봇이나 마이크로마우스, 라인트레이서 등등 만들면서 8051, 80C196, AMD188 보드 만든거 디버깅 할 때 아주 요긴하게 잘 썼었다.
요놈은 아직도 내 작업실에서 잘 쓰고 있다. 다만 아쉬운건 저렴한 아날로그 스코프이다 보니 저장 기능이 없고 one-shot 트리거가 안된다.
  요새 갖고 있는 구형 네비게이션 reverse engineering 재미에 빠져 있던 지라 이참에 디지털 오실로스코프를 만들어 보기로 했다.


[XROAD Z3300]

  우선 타겟이 될 네비게이션은 위 사진의 모델이다. XROAD사의 Z3300모델인데 삼성 S3C2410 기반으로 만들어 진거다.
  늘 그렇듯, 배따고 어찌어찌 JTAG 핀 찾아 내고, 기본 펌웨어는 백업 해놓고, 자작한 부트로더를 포팅한 후 시작 한다. 근데 요놈은 LCD 구동을 기본 CPU를 사용하지 않고 BIT1611AG라는 LCD 전용 제어 칩을 사용한다. 인터넷 뒤져봐도 자료가 없다. 젠장...
S3C2410 LCD 출력 데이터 받아서 패널에 뿌려주는듯 한데 칩 제어는 IIC로 하는듯 하다. 데이터 시트가 없으니 이거 뭐 할 수가 없다. 그래서 어쩔수 없이 무선전화기에서 뜯어 놓은 ATMEGA128 기반 보드를 이용해 IIC 버스 모니터(sniffer)를 급하게 만들었다. 16KB SRAM이 같이 붙어 있어 패킷 로깅하기에 아주 용이하다.
  백업 받아 두었던 S3C2410의 원래 바이너리를 다시 주입한다음 LCD가 정상 동작 할 때까지 IIC 모니터로 모든 패킷을 저장한다. 저장된 데이터는 간단하게 분석해서 똑같이 주입 시켜준다. 다행이 잘 되는군. 움하하...

  오실로스코프 디스플레이 파트는 얼추 이걸로 하면 되고, 데이터 취득을 해야 하는데 S3C2410의 ADC는 터치용으로 아예 할당되어 버려 일반 ADC용도로는 사용이 불가능하다. 또한, 속도도 500KSPS 밖에 되지 않아 오실로스코프용으론 좀 부족하다. 그래서 외부에 데이터 취득용으로 TMS320F28335를 추가로 장착 하였다.
  요놈은 내장 ADC가 1채널 일때는 최대 12.5MSPS, 2채널 일때는 8.33MSPS로 동작 가능하다.
  그런데 문제가 하나 있다. F28335에서 12bit 12.5MSPS로 취득되는 데이터량이 어마어마(?)하다. 초당 25MB나 된다. 이걸 어떻게 S3C2410에 전달을 하지?...
  USB를 쓸까 SPI를 쓸까 하다 F28335에서 트리거 찾아내고 디스플레이만 되는 영역 데이터를 뽑아내는 후처리까지 다 하고난 다음 S3C2410에 넘겨주기로 했다. 대충 계산해보니 약 900Kbps만 넘겨도 전체 동작에 무리가 없어 보였다.
  요 F28335와 S3C2410간 데이터 전송은 UART를 적용 했다. 실험해 보니 최대 1.5625Mbps까지 통신이 가능하였다 (S3C2410에서 최대 설정 가능한 수치임).
  원래는 Linux-Xenomai를 기반으로 사용하려고 OS포팅하고 UI까지 다 꾸며 놨는데 결정적으로 OS 오버헤드인지 뭔지 1.5625Mbps로 통신을 하면 뭔가 불안정 해진다. 데이터를 놓치는거 같다. 그래서 OSless 펌웨어로 다시 구현했다. OS가 없으니 그래픽 구현부터 해서 완전히 밑바닥 부터 짜야 했다. 아.. 피곤...
  아주 손쉽게(?) F28335와 S3C2410 코드를 만들어 얼추 돌아가도록 해봤다.


[0.5Vp-p 1KHz 측정 3us/div]


[0.5Vp-p 1KHz 측정 2ms/div]


[프로브 연결부 및 입력 전압 분압용 가변 저항부]


[최종 완성]

<> 사양
  - 주 제어기 (LCD 디스플레이 및 UI): S3C2410 200MHz
  - 보조 제어기 (ADC): TMS320F28335 150MHz
  - 입력 채널: 2채널
  - 속도: 12.5MSPS(1채널), 8.33MSPS(2채널)
  - 트리거 모드: Hold-Off, One-Shot, Run/Stop
  - 트리거 엣지(상승/하강) 선택 및 트리거 레벨 조절 가능
  - 시간축 설정(/div): 3/5/10/20/50us, 0.1/0.2/0.5/1/2/5/10/20/50ms, 0.1/0.2/0.5s
  - 디스플레이: 480x234

S3C2440A Embedded Linux-Xenomai with Realtime CAN (USB-host RTDM)

이번에도 글 제목이 아주 거창하다.
일전에 400MHz짜리 S3C2440A 컨트롤러가 내장된 네비게이터에 Linux-Xenomai를 포팅했었다(글보기).
껍데기도 깨끗하니 어디 좋은데 쓸데가 없을까 하다가 마침 8축 Actuator 구동 시험을 할 일이 있어 구현해 봤다.
제어 대상은 독일 Dunker motor라는 회사에서 만든 제어기 일체형 서보모터이고 CANopen 방식 인터페이스를 사용한다.


[CANopen 인터페이스 방식 Servo Actuator]

문제는 네비게이터에 CAN 포트가 당연히 없다는 것이다.

다행이 여러모로 확장 가능한 USB 호스트 포트가 있어 요놈을 활용해 보기로 했다.
아주 쉽다. 네비게이터에 달린 USB호스트에 USB to CAN 컨버터를 그냥 낑구면 되는 것이다!!! 정말 쉽지 않은가?

그러나 진짜 문제는 여기서 부터다.

Linux기반 USB 호스트측 SW(USB OHCI) 소스는 쉽게 구할 수 있으나 당연히 RTDM(Realtime Driver Module)을 필요로 하는 실시간 운영체제에는 쓸 수가 없다. 엄연히 이야기 하자면 사용은 가능하나 언제 실시간이 깨질지 모른다. 힘들게 실시간 운영체제를 쓰는 의미가 없다.
USB 호스트측 SW를 RTDM으로 처음부터 다시 만들어야 한다.

다음 문제가 또 있다. USB to CAN 컨버터다.

'디바이스 드라이버는 이렇게 저렇게 만드시오, 어플리케이션 API는 이러쿵 저러쿵 만드시오' 하는 메뉴얼따윈 당연히 없다. 드라이버 소스도 못 구한다.
그런데 USB to CAN 컨버터의 디바이스 드라이버도 RTDM용으로 다시 짜야한다.

그리고 또...

CAN 패킷 I/O를 위한 User level의 API 라이브러리도 실시간용으로 다시 만들어야 한다!!!

음... 머리가 아프군...

USB 호스트용 OHCI소스를 분석한다.
control pipe, bulk-in pipe, bulk-out pipe 등등 low level 제어 코드를 뽑아내 RTDM용으로 디바이스 드라이버를 완전히 다시 만든다.
OHCI 기능과는 무관한 오직 USB-CAN만을 위한 디바이스 드라이버를 만들었다.
USB to CAN 컨버터 드라이버는 소스를 구할 수 없으니 WireShark의 USB sniffing기능을 이용해 드라이버 동작을 reverse engineering한다.
User level API동작 분석은 API Monitor라는 툴을 이용해 관련 DLL에 접근하는 모든 API함수들의 동작 시퀸스와 완벽하지는 않지만 매개 변수 값들을 확인하고 알 수 없는 값들은 추정한다.
이렇게 간단한 방법으로 구현했다. 움하하...


[리눅스 부팅 및 Linux Framebuffer 동작 확인]


[SDL을 이용한 GUI구성 - 버튼, 텍스트 박스등 제작 테스트]

400MHz ARM9 코어에 USB호스트측 5ms짜리 실시간 태스크와 CANopen 패킷 제어를 위한 50Hz용 실시간 태스크를 만들었다.

8개 Actuator를 20ms주기로 동시에 제어 하도록 구성했다.
GUI는 SDL을 이용해 구현하고 8개 Actuator의 동시 제어를 좀더 직관적으로 하기위해 IIC 통신으로 사용이 가능한 Wii Nunchuk이라는 조이스틱 비스므레한걸 달아 줬다.
8축 CANopen I/O용 5ms/20ms 실시간 태스크 2개, GUI용 Thread 1개, Nunchuk 인터페이스용 Thread 1개, 전체 시스템 서비스 구성용 Thread 1개, 그리고 마지막으로 콘솔 제어 및 모니터링용 main() 루프 한개... CPU를 아주 알차게 쓰고 있는듯 하다.


[최종 완성]

S3C2440A에 Embedded Linux-Xenomai 포팅

  예전에 PXA270에 Embedded Linux-Xenomai를 포팅하여 휴머노이드로봇의 주 제어용으로 사용했었고, Ethernet용 RTDM을 제작하여 Ethernet을 이용한 실시간 제어 가능성 확인용으로도 활용해 봤었다.
  이번엔 안쓰는 구형 네이비게이터에 장착된 S3C2440A(400MHz)에 Embedded Linux-Xenomai를 포팅해봤다. 궁금해서 기기를 까보니 S3C2440A이 보이길레 한번 올려본 것이다.
  사용한 네비게이터는 엠텍반도체라는 곳에서 2006년에 만든 CARON FDN4000모델이다
[CARON FDN4000]

  뚜껑을 따보니 메인기판 1개와 LCD로 구성된 아주 깔끔한 구조였다.
[분해]


[기판 부품면]

[기판 반대면]
  우선 기본적인 외부 I/O를 확인한다. 다행이 UART가 2.5mm 마이크로 폰잭으로 나와 있었다. 터미널을 연결해 뭐라는지 들어보니 E-Boot와 WinCE 조합이었다.
  시리얼 부팅등 간단한 방법이나 사용 가능한 툴등이 있는지 메뉴얼, 인터넷등을 뒤져 봤는데 없다. JTAG을 붙여서 바닥부터 시작해야 할 듯 하다. JTAG 디버그 포트를 찾아 봤으나 핀헤더나 핀헤더가 있었을 법한 껀덕지는 아무데도 없었다. 여기저기 유심히 보던중 아래 그림처럼 SD카드 슬롯이 있는, 보드 끝자락에 뭔가 컨텍이 있을법한 곳이 눈에 띤다.
  맞다. JTAG디버그 포트가 맞다. 나만의 나름(?) 노하우로 JTAG포트임을 확인하고 TMS, TCK, TDO, TDI등 핀배열을 찾아 냈다. 난 역시 대단해 움하하... 이 때도 역시 일전에 만들어 쓰고있는 나의 보물 USB-JTAG이 아주 큰 도움이 되었다.
  S3C2440A는 ARM9TDMI코어로 JTAG 연동을 위해 Embedded ICE를 구현하면 메모리 읽기 쓰기등이 가능해 진다. 일전에 같은 ARM9TDMI 기반인 KS8695보드 리버스 엔지니어링을 위해 구현했던 코드를 그대로 활용해 S3C2440A용을 만들어 USB-JTAG에 심어 주었다.
[디버깅을 위해 JTAG단자 인출]
  아래와 같이 H/W 개발 환경을 꾸며주었다. 우선 기본 내장된 펌웨어를 모조리 읽어 파일로 저장해 놓은 다음 플래시 메모리를 깨끗하게 지우고 시작 한다.
  부트로더 만들어 올리고, 리눅스 커널 부팅을 위한 ATAG도 만들어 주고, 이더넷 포트가 없으니 커널/램디스크 다운로드용 USB포트도 뚫어 주고, 호스트PC용 USB 디바이스 드라이버도 만들어 주고, 커널 패치하고, 커널 설정 하고, 빌드하고, BusyBox 구성해 주고, 램디스크 만들어주고 보드에 올리면 된다. 참 쉽죠?
[H/W 개발환경]
  사용한 커널 조합은 linux-2.6.28.8과 xenomai-2.6.0-rc이다. ramdisk 마운트 하는데 애를 좀 먹었다. crosstool-ng로 툴체인을 만들어 쓰고 있는데 요놈에 버그가 있었다. 툴체인 버그로 생긴 문제는 도무지 찾기가 힘들다...
  Xenomai가 패치된 커널 메시지는 아래와 같다.
-------------------------------------------------------------------
Uncompressing Linux... done, booting the kernel.
Linux version 2.6.38.8-xenokang (root@localhost.localdomain) (gcc version 4.7.3 (crosstool-NG 1.19.0) ) #1 PREEMPT Wed Nov 19 16:23:11 KST 2014
CPU: ARM920T [41129200] revision 0 (ARMv4T), cr=c0007177
CPU: VIVT data cache, VIVT instruction cache
Machine: FDN4000
Memory policy: ECC disabled, Data cache writeback
[FDN4000] fdn4000_map_io()
CPU S3C2440A (id 0x32440001)
S3C24XX Clocks, Copyright 2004 Simtec Electronics
S3C244X: core 400.000 MHz, memory 133.333 MHz, peripheral 66.666 MHz
CLOCK: Slow mode (1.500 MHz), fast, MPLL on, UPLL on
Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 16256
Kernel command line: console=ttySAC1,57600 initrd=0x32200000,5M ramdisk=16384 root=/dev/ram0
PID hash table entries: 256 (order: -2, 1024 bytes)
Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
Memory: 64MB = 64MB total
Memory: 57636k/57636k available, 7900k reserved, 0K highmem
Virtual kernel memory layout:
    vector  : 0xffff0000 - 0xffff1000   (   4 kB)
    fixmap  : 0xfff00000 - 0xfffe0000   ( 896 kB)
    DMA     : 0xffc00000 - 0xffe00000   (   2 MB)
    vmalloc : 0xc4800000 - 0xf6000000   ( 792 MB)
    lowmem  : 0xc0000000 - 0xc4000000   (  64 MB)
    modules : 0xbf000000 - 0xc0000000   (  16 MB)
      .init : 0xc0008000 - 0xc001f000   (  92 kB)
      .text : 0xc001f000 - 0xc01e0000   (1796 kB)
      .data : 0xc01e0000 - 0xc01f2e00   (  76 kB)
SLUB: Genslabs=13, HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
Preemptable hierarchical RCU implementation.
        RCU-based detection of stalled CPUs is disabled.
        Verbose stalled-CPUs detection is disabled.
NR_IRQS:85
irq: clearing subpending status 000000d2
I-pipe, 11.111 MHz clocksource
I-pipe 1.18-09: pipeline enabled.
Console: colour dummy device 80x30
console [ttySAC1] enabled
Calibrating delay loop... 199.06 BogoMIPS (lpj=497664)
pid_max: default: 32768 minimum: 301
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
gpiochip_add: gpios 288..303 (GPIOK) failed to register
gpiochip_add: gpios 320..334 (GPIOL) failed to register
gpiochip_add: gpios 352..353 (GPIOM) failed to register
[FDN4000] fdn4000_init()
S3C2440: Initialising architecture
S3C2440: IRQ Support
S3C244X: Clock Support, DVS off
bio: create slab at 0
Trying to unpack rootfs image as initramfs...
rootfs image is not initramfs (no cpio magic); looks like an initrd
Freeing initrd memory: 5120K
I-pipe: Domain Xenomai registered.
Xenomai: hal/arm started.
Xenomai: scheduling class idle registered.
Xenomai: scheduling class rt registered.
Xenomai: real-time nucleus v2.6.0-rc5 (head) loaded.
Xenomai: starting native API services.
Xenomai: starting RTDM services.
io scheduler noop registered
io scheduler deadline registered
io scheduler cfq registered (default)
s3c2440-uart.0: ttySAC0 at MMIO 0x50000000 (irq = 70) is a S3C2440
s3c2440-uart.1: ttySAC1 at MMIO 0x50004000 (irq = 73) is a S3C2440
s3c2440-uart.2: ttySAC2 at MMIO 0x50008000 (irq = 76) is a S3C2440
brd: module loaded
mousedev: PS/2 mouse device common for all mice
RAMDISK: gzip image found at block 0
VFS: Mounted root (ext2 filesystem) on device 1:0.
Freeing init memory: 92K
init started: BusyBox v1.22.1 (2014-11-28 14:19:48 KST)
starting pid 24, tty '': '/etc/init.d/rcS'

Please press Enter to activate this console.
starting pid 30, tty '': '-/bin/sh'
[root@s3c2440 /]#
[root@s3c2440 /]#
[root@s3c2440 /]# ./xenomai/bin/latency
== Sampling period: 1000 us
== Test mode: periodic user-mode task
== All results in microseconds
warming up...
RTT|  00:00:01  (periodic user-mode task, 1000 us period, priority 99)
RTH|----lat min|----lat avg|----lat max|-overrun|---msw|---lat best|--lat worst
RTD|     -4.681|      3.510|     36.090|       0|     0|     -4.681|     36.090
RTD|     -4.681|      3.600|     40.230|       0|     0|     -4.681|     40.230
RTD|     -4.681|      3.600|     42.930|       0|     0|     -4.681|     42.930
RTD|     -4.681|      3.600|     42.660|       0|     0|     -4.681|     42.930
RTD|     -4.681|      3.600|     42.480|       0|     0|     -4.681|     42.930
RTD|     -4.681|      3.600|     43.920|       0|     0|     -4.681|     43.920
RTD|     -4.681|      3.600|     42.480|       0|     0|     -4.681|     43.920
RTD|     -4.681|      3.690|     47.250|       0|     0|     -4.681|     47.250
RTD|     -4.681|      3.600|     42.660|       0|     0|     -4.681|     47.250
RTD|     -4.681|      3.600|     41.760|       0|     0|     -4.681|     47.250
RTD|     -4.681|      3.600|     42.030|       0|     0|     -4.681|     47.250
RTD|     -4.681|      3.600|     42.660|       0|     0|     -4.681|     47.250
RTD|     -4.681|      3.600|     43.830|       0|     0|     -4.681|     47.250
RTD|     -4.681|      3.600|     42.390|       0|     0|     -4.681|     47.250
RTD|     -4.681|      3.600|     42.660|       0|     0|     -4.681|     47.250
RTD|     -4.681|      3.600|     42.930|       0|     0|     -4.681|     47.250
RTD|     -4.681|      3.600|     43.200|       0|     0|     -4.681|     47.250
RTD|     -4.681|      3.600|     43.110|       0|     0|     -4.681|     47.250
RTD|     -4.681|      3.600|     41.580|       0|     0|     -4.681|     47.250
RTD|     -4.681|      3.600|     42.390|       0|     0|     -4.681|     47.250
RTD|     -4.681|      3.600|     44.280|       0|     0|     -4.681|     47.250
RTT|  00:00:22  (periodic user-mode task, 1000 us period, priority 99)
RTH|----lat min|----lat avg|----lat max|-overrun|---msw|---lat best|--lat worst
RTD|     -4.681|      3.600|     42.840|       0|     0|     -4.681|     47.250
RTD|     -4.681|      3.600|     42.030|       0|     0|     -4.681|     47.250
^C---|-----------|-----------|-----------|--------|------|-------------------------
RTS|     -4.681|      3.600|     47.250|       0|     0|    00:00:23/00:00:23
[root@s3c2440 /]#
[root@s3c2440 /]#
-------------------------------------------------------------------

  실시간 태스크 어플리케이션 동작이 확인되고 커널과 램디스크만 올라간 상태라 이제 시작이긴하다. fb붙여서 LCD도 돌려보고, 주변에 덕지덕지 붙어있는 터치판넬, 오디오, 비디오, GPS, FM 송신칩 등등도 해보면 재미질것 같다. 데이터 시트나 메뉴얼을 구할 수 없는 칩들이 몇 개 있어 좀 제한적이긴 하겠다.
  요놈은 하우징이 깔끔한 완제품이라 어디 좋은데 쓸수 있게 만들면 훌륭할거 같으다.

2014/08/31~09/04 터키여행

이번엔 터키를 다녀 왔다.
원래 파리를 가기로 했으나 당일 터키로 갑자기 변경해 출발한 여행이라 아무런 정보가 없어 거의 패닉 상태로 개고생 했다.
일정 때문에 24시간을 깨어 있었던적도 있었다.
말이 안통해 새벽 5시즘엔 앙카라에서 미아가 될뻔도 했다.
그래도 참 재밌었던 여행이다.
외국사람이 한국말로 자기나라를 소개하는 가이드 투어라는것도 처음 해봤다.
노란 풍선을 타고 하늘도 날았다.