자작 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으로 연결되어 있는지 갯수까지 표기해 준다.
누가 만들었는지 프로그램을 기똥차게 잘 짰다. 크크크...