GUEST ARTICLE

 

디버깅을 위한 CoreSight의 이해




이상철 대리 / MDS테크놀로지
sangcheol@mdstec.com

MDS테크놀로지에서 산업용 표준 디버깅 솔루션 'TRACE32' 기술지원을 맡고 있다. 교육과 세미나를 통해 TRA CE32의 다양한 실전 사례와 활용방법을 임베디드 개발자들과 공유하고 있다.

TRACE32 : www.TRACE32.com
MDS테크놀로지 홈페이지 : www.mdstec.com


2005년 ARM사는 ARMv7 아키텍처와 이를 채용한 CortexA8 프로세서를 출시했다. 이는 지금까지의 ARMv7 아키텍처는 기존 ARM 아키텍처와 상당 부분 다른 구성과 월등한 성능을 자랑하며 다양한 프로세서에 적용되었고, 현재 CortexA15와 CortexA7까지 출시되어 다양한 제품에 사용되고 있다.
개발자의 입장에서 프로세서의 성능은 무시할 수 없는 부분이지만 개발과정에서 항상 발생할 수 밖에 없는 버그와 이를 해결하기 위한 디버깅 역시 신속한 개발과 제품 성능 향상을 위해 신중한 고려가 필요한 중요한 부분이다. 더욱이 리눅스, 안드로이드와 같이 복잡한 플랫폼을 기반으로 하는 제품이 시장의 대세가 되면서 SoC에서 지원하는 디버깅 기능 역시 SoC 선정에서 중요한 요소가 되고 있다.
이러한 추세에 맞추어 ARM은 ARMv7 아키텍처를 구성하면서 ARM11까지 유지해왔던 디버그 로직에 전체적인 변화를 주고 이를 CoreSight IP에 담았다. 간단히 정리해서 ARMv7 아키텍처의 디버그 관련 로직 및 IP들이 통칭 CoreSight 라는 새로운 IP로 정의된 것이다.
CoreSight는 기존의 방식과 달리 모든 디버그 로직들이 Memory-mapped 방식으로 각기 고유한 주소를 가지게 되고 SoC에서 보다 다양하고 자세한 디버깅 정보를 얻기 위해 기존의 JTAG, ETM에 더해 ITM, HTM과 같은 다양한 로직이 추가되었다.
하지만 일선의 SW개발자들에게 있어서 CoreSight의 새로운 디버그 로직들로 인해 얻을 수 있는 정보가 무엇인지, 어떻게 이를 얻을 수 있는지 등에 대해서는 아직도 많이 알려지지 않은 편이며 이렇듯 다양한 디버깅 정보를 제공하는 최신 Cortex SoC로 제품은 개발하지만 대부분의 경우 실제 디버깅에서는 과거와 같이 JTAG만을 이용하고 있다. 이 글은 CoreSight의 각 로직의 기능과 이를 얻기 위해 필요한 디버거 - TRACE32 - 설정에 대한 개괄적인 설명을 하고자 하며, 장차 개발 현장에서 JTAG / ETM뿐만 아니라 CoreSight의 다양한 디버그 로직에서 제공하는 풍부한 디버깅 정보들이 활용될 수 있는데 도움이 되었으면 한다.




[그림1] CoreSight block Diagram




CoreSight
 
CoreSight의 전체적인 구성은 위와 같다. 가장 눈에 띄는 차이는 역시 JTAG과 ETM만으로 설명되던 기존의 디버그 로직과 달리 다양한 디버그 로직들이 보인다는 것이다. 먼저 그 이름들을 보자면 :

DAP Debug Access Port
CTI Cross Trigger Interface
CTM Cross Trigger Matrix
HTM AHB Trace Macrocell
ITM Instrumentation Trace Macrocell
SWO Serial Wire Output
TPIU Trace Port Interface Unit
Trace Funnel CoreSight Trace Funnel
Replicator ATB Replicator

각 로직들은 고유의 기능을 가지고 있으며 Memory-mapped 방식으로 각기 고유한 주소를 가지고 있다. 이를 보통 베이스 어드레스라 하며, 디버거에 해당 로직의 베이스 어드레스를 지정해 주어야 그 기능을 이용할 수 있다. 기존의 디버그 로직과 비교해 보았을 때 눈에 띄는 차이라면 ~TM으로 끝나는 Trace Macrocell이 많아졌다는 것인데, 점차 JTAG 디버깅만으로 대응하기 힘들어지는 복잡해지는 플랫폼의 디버깅을 위한 ARM의 대응이라 볼 수 있을 듯 하다. 이제 각 로직 별로 각기 역할과 이를 얻기 위한 디버거 설정에 대해 알아보자.


DAP

Debug Access Port는 외부의 JTAG 디버거와의 인터페이스를 담당한다. ARMv6 아키텍쳐 기반의 SoC들은 디버그 로직의 JTAG TAP 컨트롤러와 디버거가 직접 통신하는 방식이었지만 ARMv7 아키텍처는 DAP라는 별도의 인터페이스 로직을 적용한 것이다.
이에 대한 이유라면 역시 이미 대세가 된 멀티코어 디버깅 시 기존 방식이 가지고 있던 문제점을 해결하기 위함일 것이다. 
 


[그림2] JTAG 데이지 체인을 이용한 멀티코어 연결방식


기존의 JTAG TAP 컨트롤러 연결방식의 경우, 멀티코어 구성 시에는 위와 같이 각 코어의 TAP 컨트롤러의 TDI와 TDO 신호를 직렬로 엮어 체인을 구성하였다. 이를 데이지체인(Daisy-chain)이라 하는데, 이 경우 위와 같이 슬립 모드 진입과 같은 이유로 어느 코어의 클럭 또는 전원이 차단될 경우 상관없는 다른 코어의 디버거 연결까지 끊기게 되는 문제가 있었다. CoreSight는 이러한 문제를 병렬식 연결을 통해 해결하고자 하였다.



[그림3] DAP를 이용한 멀티코어 연결방식

 
멀티코어 구성 시 위와 같이 각 코어가 DAP에 병렬로 연결되고 JTAG 디버거는 실제 디버깅하고자 하는 코어가 아닌 DAP와 통신하면서 각 코어와의 디버그 세션마다 일종의 독립된 채널을 만들어주는 것이다. 이로써 슬립모드나 기타 이유로 어느 코어에 발생하는 클럭/전원 변화가 다른 코어의 디버그 세션에 영향을 주지 않도록 하려는 것이다.
하지만 근본적으로 이를 위해서는 각 코어와 코어와 디버그 로직의 클럭/전원 도메인의 완전한 분리가 전제되어야 하는데, CortexA9 MPCore까지는 보통 코어와 디버그 로직이 클럭/전원 도메인을 공유하였다. 때문에 CoreSight 디자인의 의도와 달리 여전히 코어간 영향을 주는 경우가 있었다. 이 부분은 CortexA7과 A15부터 수정 적용 예정으로 해당 프로세서가 적용된 SoC가 출시되면 상당부분 해결될 것으로 예상된다.



[그림4] DAP의 구조


DAP의 개략적인 구조는 위와 같으며 눈에 띄는 특징은 크게 SWJ-DP / AHB-AP / APB-AP / JTAG-AP 라는 네 가지 로직으로 나뉜다는 것이다. 각 로직이 있음으로 인해 개발자가 사용할 수 있는 디버깅 기능에 대해 하나씩 살펴보자.

1. Serial Wire JTAG Debug Port

JTAG 디버깅을 위한 전통적인 핀은 TDI, TDO, TMS, TCK의 네 핀이지만 갈수록 작아지는 기기의 보드 면적에 비하면 표준 ARM20 핀 커넥터를 사용하거나 별도의 지그 또는 필름케이블을 사용해야 하는 전통적 JTAG 인터페이스는 많은 불편함과 중간의 연결매체의 쉬운 손상으로 인해 잦은 시행착오와 문제를 야기했었다.
SWJ-DP는 SWCLK와 SWDIO 두 핀만으로 JTAG 디버깅이 가능하게 해주는 것으로 이는 SoC의 핀 수를 아낄 수 있음은 물론 기존의 지그커넥터 정도의 공간에 제대로 된 두 핀을 뽑아 흔히 발생했던 JTAG 연결문제의 가능성 자체를 차단할 수 있다는 장점도 가지고 있다.



[그림5] 표준 JTAG과 SWJ-DP의 전환



보통 지금까지 출시된 SoC의 경우 일반 JTAG연결과 SWJ-DP를 이용한 연결 모두 사용할 수 있으며, TRACE32의 경우 아래의 명령어를 통해 이를 위한 연결 전환을 해줄 수 있다.

 SYStem.CONFIG SWDP ON


표준 JTAG과 SWJ-DP는 연결 방식의 차이일 뿐 활용할 수 있는 JTAG 디버깅 기능은 동일하다.


2. AHB-AP

AHB-AP는 DAP의 두 MEM-AP 중 하나로 설계 시 보통 포트번호로 0번을 할당하며, SoC 내 고속 시스템 버스인 AHB 버스와 연결되어 있다. 이로 인해 기존 디버그 로직의 경우 디버거가 메모리에 접근하기 위해서는 반드시 프로세서와 디버그 인터페이스가 형성된 상황에서 디버그 로직을 통해 프로세서가 바라보고 있는 메모리만을 바라볼 수 있었지만, CoreSight가 채용된 SoC의 경우 디버거는 AHB-AP를 거쳐 AHB 버스를 통해 바로 메모리 접근이 가능하다.


[그림6] AHB-AP


이는 문제 발생 시 기존과 다른 새로운 접근을 가능케 한다. 예를 들어 시스템 동작 중 어떤 이유로 혹은 초기 브링업이나 SoC 디자인 과정에서 디버거 인터페이스가 불가능한 문제가 발생했을 때 기존의 방식으로는 아무것도 할 수 없었지만, CoreSight 환경이라면 디버거는 DAP와 인터페이스하고 AHB-AP를 거치게 되면 실시간으로 메모리 값의 변화를 확인할 수 있으며 필요 시 값을 변경할 수 있다.

이를 통해 문제의 원인이 로직 자체의 설정으로 인한 것인지 어떤 원인으로 인해 디버그 버스가 잡혀 있기 때문에 디버거에서 접근할 수 없는 것인지 등을 유추할 수 있다.
최근 소개되고 있는 SoC의 경우 보안성 강화 등의 이유로 특정 비트 값에 따라 디버그 권한을 설정하는 경우가 있는데, 디버거에서 레지스터/메모리에 접근이 불가능하도록 설정이 된 경우에도 먼저 AHB-AP를 통해 메모리에 직접 액세스해서 JTAG 디버깅을 위한 비트 값을 설정해서 디버거를 사용할 수 있게 할 수도 있다(물론 AHB-AP를 통한 메모리 접근 자체를 막은 경우에는 불가능하다). 이렇게 AHB-AP를 통해 직접 메모리에 액세스하는 경우 프로세서와 디버그 로직을 통하여 메모리를 보는 것이 아니기 때문에 브레이크 포인트 등 디버그 기능은 사용할 수 없다.
실제 개발 과정에서 AHB-AP를 이용할 수 있는 또 하나의 예는 캐쉬 데이터의 반영 여부를 확인하는 것이다. 캐쉬 플러쉬를 해주었지만 메모리에 반영되지 않는 것 같은 상황 등 캐쉬 동작의 확인이 필요할 때 AHB-AP를 통해 접근한 덤프 창과 일반적인 덤프 창을 비교해보면 캐쉬 플러쉬가 정상적으로 이루어졌는지 알 수 있다. AHB-AP는 시스템버스를 이용해 메모리에 접근하기 때문에 MMU나 캐쉬를 거치지 않은 순수한 물리 메모리 값을 볼 수 있기 때문이다.
TRACE32의 경우, 덤프 창을 열 때 메모리 클래스를 지정해주는 것으로 메모리 접근 경로를 지정할 수 있으며 아래 화면을 참고해보자.



[그림7] APB-AP를 통한 메모리 접근과 AHB-AP를 통한 메모리 접근


위의 두 덤프창은 메모리클래스를 ASD와 ANC로 준 결과창으로 두 덤프창의 내용은 동일하며 이는 캐쉬와 실제 메모리의 내용이 일치함을 의미한다. 만약 캐쉬 플러쉬나 클린 후 위와 같이 덤프창을 열어보았는데, 두 창의 내용이 다르다면 플러쉬/클린 과정 중 문제가 있었음을 알 수 있다. 경우에 따라 OS 부팅 중 AHB 버스를 통한 접근을 막는 경우가 있는데, 이 경우 AHB-AP를 통한 메모리 접근 시 버스 에러가 발생한다.




3. APB-AP



[그림8] APB-AP



APB-AP는 Advanced Peripheral Bus를 통해 프로세서, 코프로세서 및 기타 페리에 접근하는 것으로 설계 시 보통 포트번호는 1번을 할당한다. 일반적인 디버그 인터페이스 및 디버깅을 위한 동작은 APB-AP를 거치게 되며 디버거가 메모리를 바라보는 시점은 프로세서와 동일하기 때문에 특별한 메모리 클래스 지정 없이 Data.List나 Data.dump 창 등을 열어보면 MMU 및 캐쉬 데이터가 반영된 값을 보게 된다. 일반적인 디버그 인터페이스가 이루어지고 디버그 기능을 한다는 면에서 특이점은 없지만, 메모리 주소 지정 시 한 가지 특이점이 있다. APB-AP를 통해 CoreSight의 각 로직에 접근하는 경우 마치 MMU의 가상메모리 주소와 같이 별도의 주소가 할당되어 있다는 것이다.

많이 사용되는 Exynos 시리즈의 경우 0x800xxxxx 번지 대에 CoreSight 각 로직들의 베이스 어드레스가 할당되어 있는데, 이는 APB-AP를 통하는 경우의 주소대이며, 실제 CPU가 인식하는 주소로는 0x108xxxxx 번지대가 할당되어 있다.
때문에 베이스 어드레스를 지정해 줄 때에는 정확한 메모리 클래스를 지정해 주어야 하며, 일반적인 디버그 동작은 APB-AP를 거치기 때문에 별다른 지정 없이 베이스 어드레스를 지정할 때에는 APB가 메모리 클래스로 기본 지정된다. APB-AP를 통해 접근하는 주소대와 실제 CPU가 인식하는 주소인 AHB-AP를 통한 덤프창을 확인해보자. 아래는 TPIU의 베이스 어드레스 부분을 확인한 것이다.



[그림9] APB-AP를 통한 디버그 리소스 접근과 AHB-AP를 통한 디버그 리소스 접근


이와 같이 메모리 클래스를 지정하여 Data.List 창이나 Data.dump 창을 열어볼 때에는 메모리 클래스 지정에 주의해야 한다. 같은 주소를 준다 해도 같이 지정되는 메모리클래스에 따라 완전 다른 값과 의도와 다른 값을 보여줄 수 있고, MMU페이지 설정에 따라 해당 영역에 접근할 수 없기 때문에 물음표로 가득한 창을 볼 수도 있기 때문이다. TRACE32의 경우 흔히 사용되는 메모리 클래스와 의미는 다음과 같다.

SD: MMU가 활성화되어 있을 때, 가상메모리 기준으로 메모리를 볼 때.
ASD: SD와 동일하지만 지정되는 주소는 물리메모리 기준.
ANC: 물리메모리 기준 주소를 지정하고 캐쉬값이 반영되지 않은 순수한 물리메모리값을 보고자 할 때 사용.
SR: 램으로 바이너리 다운로드 시, 데이터캐쉬를 통과하지 않고 값을 쓰고자 할 때.
AHB: AHB버스를 통해 직접 메모리에 접근하고자 할 때 사용. 보통 ANC와 같은 결과값을 볼 수 있다.
E: Run-time으로 메모리 접근을 하고자 할 때 사용. JTAG을 이용한 디버깅은 보통 반드시 타깃을 세워야 메모리/레지스터 값을 볼 수 있지만 Core Sight가 적용된 프로세서인 경우, AHB-AP혹은 APB-AP를 통해 메모리에 직접 접근할 수 있기 때문에 프로세서 동작 시에도 메모리 값의 변화를 볼 수 있다. DMA 등을 통해 메모리 변화가 있는지 확인하고자 할 때 유용하며, 다만 이 때에는 디버그 로직을 거치지 않고 바로 버스를 경유해 메모리를 보는 것이기 때문에 브레이크포인트 등의 디버그 기능은 이용할 수 없다.

4. JTAG-AP

JTAG-AP는 ARM9/11 등 기존의 ARM 코어를 사용할 때 이를 APB-AP 뒤에 놓지 않고 그대로 TAP 컨트롤러만 연결하고자 할 때 사용되는 액세스 포인트이며 설계 시 주로 포트 번호는 2번을 할당한다. 역시 CoreSight의 기본 개념과 같이 병렬로 연결하게 되어 있으며 일반적인 경우 포트번호 0번부터 7번까지 8개의 구형 ARM 코어의 연결을 지원한다.
이를 제외한 다른 특이점은 없으며, 로직의 구성 측면에서 보았을 때 일반적인 데이지 연결과 비교해보면 일장일단이 존재한다.




[그림10] JTAG-AP

 
JTAG-AP 구성 시 CoreSight DAP를 통한 연결 시의 장점 그대로 병렬 연결이기 때문에 JTAG-AP 뒤에 연결된 각 코어의 전원/클럭 차단에 의한 디버그 인터페이스 끊김이 다른 코어의 디버그 인터페이스에 영향을 주지 않는다는 것이다. 하지만 디버거와 코어 사이에 DAP와 JTAG-AP라는 과정을 더 거쳐야 하고 디버그 신호의 변환이 필요하기 때문에 데이지 체인과 비교해 6배에서 10배 가량 느린 속도를 보인다.
ARM9/11은 비교적 느린 클럭으로 동작하기 때문에 별 다른 문제는 되지 않겠으나 좀 더 빠른 동기 제어가 필요한 경우라면 로직 디자인 시 각 코어들을 JTAG-AP와 연결하지 않고 DAP와의 데이지 체인 형식으로 구성하는 것이 좋을 수 있다.
지금까지 CoreSight의 여러 로직 중 디버거와 직접 인터페이스를 하는 DAP와 DAP 내부 로직에 대해 알아보았다. DAP만으로도 기존의 디버그 로직, 디버깅 기능에 차이가 있음을 알 수 있다. 다음 편에서는 CoreSight에 다수가 추가된 트레이스 로직에 대해 설명하고 이를 통해 활용할 수 있는 강력한 트레이스 기반 디버깅 기능에 대해 알아보도록 하자.


회원가입 후 이용바랍니다.
개의 댓글
0 / 400
댓글 정렬
BEST댓글
BEST 댓글 답글과 추천수를 합산하여 자동으로 노출됩니다.
댓글삭제
삭제한 댓글은 다시 복구할 수 없습니다.
그래도 삭제하시겠습니까?
댓글수정
댓글 수정은 작성 후 1분내에만 가능합니다.
/ 400
내 댓글 모음
저작권자 © 테크월드뉴스 무단전재 및 재배포 금지