자작 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 연동 작업이 상당히 쾌적해 졌다.

댓글 2개: