Pure Single Precision Math-Library

  써 놓고 보니 제목이 그럴싸하다.
  ARM Cortex-M4 코어가 들어가는 STM32F429 보드를 가지고 놀던중 수학함수(sin(), cos(), sqrt() 등등)를 사용할 필요가 있어 sin() 함수를 호출 했더니 CPU가 죽는다.
  Cortex-M4 FPU는 double precision을 지원 하지 않는 다는걸 알았다. 그래서 이번엔 sinf()를 호출 해 봤더니 역시 또 CPU가 죽는다.
  나는 보통 Embedded System용 툴체인은 직접 빌드해서 사용한다. 내가 만든 툴체인에 문제가 있나 싶어 FPU관련 옵션을 이리저리 바꿔가면서 툴체인을 다시 빌드해봤으나 역시 증상이 동일 하다. 해본 사람은 알겠지만 툴체인 한번 빌드하는데 적게는 30분에서 많게는 2~3시간이 걸린다. 더 많은 옵션으로 테스트를 해보고 싶지만 툴체인 빌드하느라 시간을 다 까먹고 있어서 툴체인 빌드 삽질을 중지 하고 수학함수(libm) 소스를 열어 봤다. arm-unknown-eabihf(bare-metal)로 빌드 할 경우 newlib가 사용되고 arm-unknown-linux-gnueabihf로 빌드 할 경우 glibc가 사용된다(툴체인 뒤에 붙는 hf는 hardware FPU라는 뜻임). newlib의 경우 수학함수가 모두 double precision으로만 빌드 되고 sinf()나 cosf()와 같은 single precision 함수는 껍데기만 single precision일뿐 정작 함수 내부 구현시 double precision을 사용한다. 그러니 CPU가 죽을 수 밖에...
  glibc소스 확인 결과 삼각함수나 sqrtf(), powf()등은 함수 이름에 걸맞게 내부 구현도 pure single precision으로 구현되어 있었다. 그런데 왜 CPU가 죽는 것일까? 툴체인 빌드시 명확하게 single precision으로만 수학 함수가 빌드되도록 옵션을 설정 해야 한다. 또한 gcc 버전이 올라 갈 수록 하위 호환이 필요한 함수들의 경우 실제 테스트를 해보지 않는 이상 잠정적인 버그로 남아 있을 수 있다. 실제로 ARMv4로 빌드 옵션을 주고 컴파일 해도 최근 gcc의 경우 ARMv7로만 빌드 되는 경우도 있다. 아마 낮은 버전의 gcc와 glibc의 조합을 이용하면 Cortex-M4용 수학함수 툴체인을 만들 수 있을 것이나, 시간 소모가 많다.
  이번 문제는 툴체인을 다시 빌드하지 않고 필요한 수학 함수를 소스 수준에서 포팅하여 완전한 'pure single precision'으로 빌드 하여 사용하기로 하였다.
  openlibm, fdlibm, glibc, yeppp등을 검토하여봤다. openlibm의 경우 ***f()함수는 대부분 single precision으로 구성되어 있으나 삼각함수는 double precision으로만 구현되어 적용이 불가 하였다. sinf(), cosf()등이 있으나 함수 껍데기만 float이고 내부 상수 및 수치 연산은 모두 double로 구성되어 있었다. fdlibm은 오직 double precision만 사용 가능하다(readme에 언급되어 있음). yeppp의 경우 소스크기가 큰편이라 자세히 보지 못했다. architecture별로 FPU사용에 최적화가 되어 사용시 큰 잇점이 있을 것으로 보이나 일반적인 libm 형태 소스 구성이 아니라 분석하는데 시간이 걸려 pass함(나중에 속도 최적화시 다시 봐야 할거 같다). 마지막으로 glibc는 대부분 내가 필요로 하는 함수는 single precision으로 구현되어 있었다. 역시 구관이 명관이라... glibc의 libm중에도 expf()와 같은 일부 함수는 내부에 double precision 연산이 들어가 있는 것도 있었다. glibc 버전중에 찾아보면 single precision으로 구현된 소스가 있을 텐데 일단 지금은 필요한 함수가 아니라 우선 아래 함수만 포팅하여 사용하였다.

  - sqrtf()
  - sinf()
  - cosf()
  - tanf()
  - asinf()
  - acosf()
  - atanf()
  - atan2f()

  pure single precision으로 구성한 소스를 첨부합니다. 필요하신 분은 가져다 활용 하시기 바랍니다. libm 소스는 glibc-2.21에서 발췌 하였습니다. 첨부된 소스 이외 의존성은 없습니다. standalone으로 빌드하여 사용 하시면 됩니다. *.c 파일은 프로젝트에 포함 시켜서 빌드하면 되고 사용시 math.h 헤더파일만 포함하여 사용 하면 됩니다.
  IEEE754(부동 소숫점 연산 표준) 함수를 발췌 하여 사용하였으므로 각 architecture별 FPU가 가지고 있는 최대 성능이 나오지 않을 수 있습니다.

소스다운로드

  

2016/02/10~2/14 두번째 괌여행







두번째로 괌을 다녀왔다.
이번엔 지난번 가보지 못했던 괌섬 남부 이나라한 자연 풀장도 가봤다.
자연 형성된 잔잔한 바다 풀장에 사람들은 물놀이 삼매경이지만 풀장 바로 앞
불과 10미터 바깥쪽은 사람 키보다 더 큰 파도가 굉장하게 일고 있었다.

여행가기전 괌 숙박 호텔의 95%가 예약이 끝나있었다.
도대체 문슨일인가 싶었는데 발렌타인데이가 주말휴일 끼어 있다보니
호텔 예약이 불가능했었다.
홈페이지에서 한글 지원을 하지 않거나 통합 호텔 예약 사이트(앱)등에서 검색되지 않는
콘도를 찾아 매니저와 메일로 직접 컨택하여 겨우 구할 수 있었다.

네비게이션 기기(UB-5)에 임베디드 리눅스 올리기

쓰레기통에 버려진 네비게이션 기기를 하나 주웠다.
현대유비스 UB-5라는 모델인데 동작은 하는듯 보였다.

[현대유비스 UB-5]

  외부 NTSC 카메라 입력 기능이 있어 영상처리쪽 공부나좀 해볼겸 해서 영상처리용 테스트 보드로 만들어 보기로 했다.

  뭐든 시작은 배를 따는것 부터 한다.
배 따고 EMI차폐용 철판 들어내 보니 ARM1176기반의 삼성 S3C6410 ARM 프로세서가 들어가 있었다. 아주 오래전에 잠깐 써본적이 있는 놈이라 좀 수월 할 듯 해보인다.
  보드 여기저기 JTAG이나 콘솔/디버그 UART용으로 할당 되어 있을 법한 커넥터나 PCB 패턴들을 들쑤셔 찾아낸다.

  JTAG용으로 할당된 PCB패던 뭉치를 찾아내 자작해서 쓰고 있던 'JTAG 핀 분석기'를 물리고 핀맵을 찾아 낸다. 콘솔용 UART 패턴도 찾아내어 기본 펌웨어에서 뭐라그러는지 함 봐준다. 기본 펌웨어에서 뿌려주는 메시지중에 일부는 리버스엔지니어링시 중요한 정보나 단서를 제공 할 수 있으니 예의상 함 읽어봐 주고 저장해 놓는다.
  역시 자작해서 쓰고 있는 'USB-JTAG'하드웨어를 물려주고 S3C6410용 OpenOCD 스크립트를 입수해 CPU 제어권을 잡아 본다. 역시 툴이 좋으니 일사천리로 일이 된다. 움하하...
  기본 저장된 펌웨어를 모조리 덤프받아 백업해 놓고 자작한 부트로더를 올린다.
자작한 부트로더가 일단 올라가면 JTAG연동은 필요 없으니 외부에 콘솔용 UART포트만 뽑아 준다.

[콘솔용 UART포트 인출]

  보드에 USB-OTG 커넥터가 부착되어 있으나 케이스에 구멍이 없어 구멍도 같이 뚫어 주었다. 리눅스 커널 보낼려면 필요하다.
  아주 손쉽게(?) S3C6410 기반의 UB-5 보드용 임베디드 리눅스 커널을 빌드하고 파일시스템 꾸며주고 런타임라이브러리 올려주고 등등 작업후 부팅해본다.

[리눅스 커널 포팅 및 부팅 확인]

잘 되는군....
터치스크린 사용을 위해 tslib를 올려 캘리브레이션을 해본다.

[tslib포팅 및 캘리브레이션]

터치 캘리브레이션 했으니 되는지 확인해 본다.

[터치스크린 테스트]

역시 잘 되는군...
CPU 성능이 좋으니 이번엔 SDL대신 QTE를 올려봤다.
QTE 런타임 라이브러리 용량이 줄이고 줄여도 약 30MB정도로 상당하다. 임베디드 환경에서 30MB는 좀 큰 편이다.
내장된 1GB NAND를 파티셔닝해서 tslib와 QTE 런타임라이브러리를 올리고 리눅스 부팅시 마운팅되도록 한다.

[QT 어플리케이션 테스트]

tslib에서 캘리브레이션된 데이터와 연동되어 QT에서 위치도 잘 잡힌다.
역시 잘된다.
모든게 순조롭다. 난 역시 대단해. 움하하...

이제 내장된 NTSC 디코더 칩을 사용해봐야 한다. 리눅스 커널에서 잘 잡히질 않는다.
다시 배 따고 디코더 칩 외부 IO가 정상적인지 스코프로 확인해 본다.
전원도 잘 들어가고 I2C 신호는 뜨는데 I2C 통신에 응답을 하지 않는다.
근처에 있는 음원칩에 대해서도 I2C가 응답을 하지 않는다. 뭐지??
모든 어드레스에 대해 I2C 스캔을 해봤는데 엉뚱한 어드레스에서 응답을 한다.
뭔가 했더니 CPU 옆에 붙어있던 DMB 수신 칩에서 응답을 한 모양이다.
DMB 수신칩 데이터 시트가 없어 관심이 없었는데 요놈이 응답을 하는걸 보니 I2C버스도 잘 동작하는듯 한다. 그런데 비디오/오디오 칩만 응답을 하지 않는다.

카메라 연동이 되어야 영상처리용 테스트 보드가 되는데...

UB-5 네비게이터 메뉴얼을 찬찬히 보니 외부 AV입력단자가 있고 영상과 음성을 4핀용 오디오 잭으로 받고 있도록 구성되어있다.
외부 AV입력 핀에서 유입된 신호로 비디오와 오디오 칩이 파손된 듯 하다.
AV가 안되서 버린 물건인듯 하다.
원본 롬으로 복원해서 진짜로 안되는지 확인해 봐야 하는데, 아...
귀찮다.

그냥 고장난걸로 보고 포팅된 리눅스나 가지고 놀아야 겠다.

Open Source 기반 FLCC-HILS 환경 구축

  간만의 글이다.
  이번엔 오픈소스기반의 소프트웨어들을 이용해 FLCC (Flight Control Computer) 하드웨어를 적용한 HILS (Hardware In the Loop Simulation) 환경을 구축해 간단한 항공기 제어를 해봤다.
용어가 생소한 분을 위해 간략히 소개를 하자면 FLCC는 조종사의 스틱 명령을 전달 받아 Actuator를 이용해 항공기의 조종면을 움직이는 명령을 생성하고 때에 따라서는 Autopilot 기능을 수행하거나 항공기의 안정적인 자세제어를 위한 역할을 수행하기도 한다. 컴퓨터로 제어하는 요즘 항공기에는 대부분 들어가게 되며 Fly-By-Wire 시스템을 위한 중요한 요소이다.
HILS는 시뮬레이션 환경을 말한다. 시뮬레이션이라면 소프트웨어 기반으로만 생각 할 수 있으나 실제 장착되는 장비를 시뮬레이션 루프안에 포함시켜 실제 하드웨어 장비의 동작을 검증하기 위한 목적으로 수행하기도 하는데  이를 HILS라 부른다.
  우선 사용한 오픈소스 및 적용 하드웨어는 다음과 같다.

  - FDM         : JSBSim
  - Visualizer  : FlightGear
  - Application : QT
  - FLCC RTOS   : Embedded Linux-Xenomai
  - FLCC H/W    : PXA270 (ARMv5, 520MHz)
  - Comm.       : Realtime Ethernet (UDP/IP)

  각 부분별 소프트웨어 소개를 잠깐 하자면 JSBSim은 항공기 공력 시뮬레이션을 위한 물리엔진이다. 흔히 FDM (Flight Dynamic Model)이라고 하는데 항공기의 공력 파라미터인 무게, 관성, 양력계수, 항력계수 등을 xml형태로 전달 하고 항공기 제어 파라미터인 엔진 추력, 조종면 위치 각등을 입력하면 항공기의 속도, 위치, 고도, 자세등을 알려주는 오픈소스 기반 소프트웨어 이다.
  FlightGear는 3D 가시화 툴로 JSBSim에서 출력된 비행체 정보를 바탕으로 지리정보 (GIS - Geographic Information System)와 함께 지형지물과 항공기, HUD등을 그려주는 역할을 한다. JSBSim 자체는 이런 가시화 툴을 제공하지 않기에 항공기 제어 결과를 3D 그래픽으로 확인 하고자 한다면 필요한 툴이다. 역시 오픈소스이며 전세계 공항 정보와 많은 항공기 모델을 가지고 있다.
FlightGear를 설치하면 JSBSim도 같이 설치되며 별도 지정을 하지 않으면 JSBSim을 기본 FDM으로 사용하게 된다. FlightGear와 연동하여 사용 가능한 FDM은 JSBSim 말고도 YASim이 있는데 둘의 차이라면 JSBSim은 항공기의 양력계수, 항력계수등 공력 파라미터를 입력 받는 반면 YASim은 항공기의 기하학 (Geometric) 정보인 날개 면적, 코드 길이, 조종면 면적, 동체 길이등을 직접 입력 받아 공력 물리엔진 연산을 수행한다.
  QT는 그래픽 어플리케이션 개발용 라이브러리이며 역시 오픈소스이다. IDE 기능까지 포함하고 있어 MS의 비주얼 스튜디오와 같다고 보면 된다. 그러나 윈도우즈 뿐만 아니라 리눅스나 맥 OS에서도 사용 가능하며 심지어 리눅스기반의 임베디드 시스템에도 포팅하여 사용 가능하다. 꼭 그랙픽 관련 어플리케이션 뿐만 아니라 콘솔 기반 응용 프로그램도 작성 가능하다. 그래픽관련 라이브러리 뿐만 아니라 Multi-thread, Network등 많은, 그리고 유용한 라이브러리도 제공한다.
QT를 소개하는 이유는 FLCC측 비행 제어 어플리케이션 개발시 처음부터 FLCC하드웨어를 사용하지 않고 FlightGear가 동작하는 호스트 PC에서 Native 개발 환경으로 빠르게 동작 확인을 해볼 수 있다는 점 때문이다.
Native 개발 환경에서 동작이 확인 되면 별다른 소스 수정없이 바로 FLCC 타겟에 사용 가능 하다. 물론 Native OS가 비실시간 운영체제라면 실시간 태스크 관련 코드는 수정이 좀 필요할 것이다.
  마지막으로 FLCC 하드웨어에서 사용할 RTOS인 Xenomai이다.
리눅스 기반의 실시간 커널 패치로 이전 글에서 많이 소개 되었다.
항공기 실시간 제어를 위해 FLCC 하드웨어에는 Embedded Linux-Xenomai를 사용했다.

  항공기를 제어 시뮬레이션을 수행 하려면 FDM으로 부터 계산된(시뮬레이션된) 항공기 자세정보가 필요하며 제어 루프에 의해 계산된 출력물인 엔진 추력, 조종면 각도값은 다시 FDM으로 주입하여 일련의 되먹임 (Feedback) 제어루프가 형성 되어야 한다.
다행히 FlightGear에는 UDP/IP 및 RS-232통신라인을 이용해 이런 일련의 데이터 흐름을 만들 수 있는 기능이 있다.
해외 자료들 뒤져 보니 실 기체 개발시 HILS용으로 FlightGear를 많이 사용하는가 보다.
제어 루프는 RTOS기반의 FLCC 하드웨어에서 수행 하도록 구성하면 된다.
  전체 시스템 구성을 보자면 아래 그림과 같다.

[그림 1] Native 시뮬레이션 환경


[그림 2] FLCC-HILS 환경

  사용한 FLCC 하드웨어는 일전에 EtherCONN 개발시 사용한 PXA270기반 보드를 사용했다 (링크참조).
Linux-Xenomai가 이미 포팅되어 있고 UDP/IP 통신을 위한 Ethernet용 실시간 디바이스 드라이버 (RTDM)가 만들어져 있으니 바로 활용 가능 하였다.
  개발시에는 [그림 1]과 같이 Native 환경에서 개발을 진행 하고 얼추 결과가 나오면 [그림 2]와 같이 실제 FLCC 하드웨어에 제어 코드를 이식해 사용 하면 된다.
  HILS 환경을 구축하고 간단하게 항공기의 롤 및 피치 제어용 Auto-pilot을 구현해 돌려 봤다. 아래 동영상 결과는 실제 FLCC 하드웨어로 제어하는 모습이다.




[영상 1] Roll/Pitch Auto-pilot Off


[영상 2] Roll/Pitch Auto-pilot On


[영상 3] Roll/Pitch Auto-pilot Off/On

  [영상 1]은 롤/피치 제어용 Auto-pilot기능이 없는 순수 비행 화면이다.
비행 조종은 게임 패드의 조이스틱을 사용했으며 트림을 사용하지 않고 조종하는 모습이다.
조종사가 아니다 보니 항공기 조종하는게 생각 보다 어렵다.
  [영상 2]는 롤/피치 제어용 Auto-pilot의 도움을 받아 비행하는 모습니다. 아케이드 게임하는 것처럼 조종하기가 참 수월해진다.
  [영상 3]은 롤/피치 제어용 Auto-pilot 기능을 on/off를 반복하면서 동작 상태를 관찰하는 모습이다.

2015/06/21~06/24 괌여행

메르스를 피해 괌으로 도피했다.
리티디안 해변은 지금까지 본 바다중에 가장 인상 깊은 곳이었다.











자작 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 송신칩 등등도 해보면 재미질것 같다. 데이터 시트나 메뉴얼을 구할 수 없는 칩들이 몇 개 있어 좀 제한적이긴 하겠다.
  요놈은 하우징이 깔끔한 완제품이라 어디 좋은데 쓸수 있게 만들면 훌륭할거 같으다.