본문 바로가기
소스 레벨 디버깅이 뭐죠?

뭘 알아야 이해를 하지

임베디드 시스템은 윈도우가 설치되어 있는 개발 환경과 다르게 디버깅이 아주 중요하답니다. 일반적으로 윈도우가 설치되어 있는 호스트 피시에서 개발을 할 때는 모니터로 printf 메시지 출력이나 IDE 툴을 통해 쉽게 디버깅을 할 수가 있는 반면 임베디드 시스템은 모니터로 없고 IDE 툴이 윈도우 만큼 잘 되어 있지 않죠. 우선 임베디드 시스템에서는 printf로 메시지를 출력하려면 앞서 말씀 드린 바와 같이 시리얼 컨트롤 레지스터를 초기화 시켜야 하고, 시리얼 케이블을 호스트 피씨와 연결을 한 후 하이퍼터미널과 같은 프로그램으로 메시지를 봐야 하죠. 만약 임베디드 시스템에서 시리얼 포트가 없다거나 시리얼 포트는 있지만 아직 시리얼 컨트롤 레지스터 초기화 전이라면 메시지 출력이 안돼서 디버깅이 어렵겠죠? 그럼 일반적으로 개발 업체는 두 가지 디버깅 방법을 병행해서 개발을 한답니다.

디버깅은 주로 소프트웨어 디버깅과 하드웨어 디버깅이 있죠.
앞서 말씀드린 것처럼 소프트웨어 디버깅은 주로 씨 언어 프로그램에다 printf 명령어를 사용해서 터미널 프로그램으로 메시지를 출력해서 디버깅을 한답니다. 반대로 하드웨어 디버깅은 제이텍(JTAG) 장비를 이용하여 프로세서를 언제든지 멈추고, 실행하고, 명령어 하나씩 실행을 해 볼 수도 있지요.
흔히 임베디드 시스템 개발할 때 소스 레벨 디버깅을 한다 라고 하면 대부분 하드웨어 디버깅이라고 보시면 됩니다. 하드웨어 디버깅은 제이텍 장비를 이용하여 개발자가 씨 언어 소스라인뿐만이 아니라 각종 패리퍼럴 컨트롤, 메모리 컨트롤, 시피유 컨트롤 등 다양하게 디버깅을 해 볼 수가 있답니다. 이러한 하드웨어 디버깅을 할 때 반드시 준비해야 될 사양이 있어요.
우선 첫 번째는 제이텍 장비 및 소프트웨어 프로그램, 타겟 시스템, 제이텍 장비와 연결할 수 있는 제이텍 케이블 그리고 컴파일 후 만들어진 project.elf 파일이랍니다. 소스 레벨 디버깅에서 가장 중요한 elf 파일은 헤더, 바이너리, 심볼 정보 등이 들어 있어요.

그럼 제이텍 장비를 통해 소스레벨 디버깅 하는 절차를 알아 보아요.

제이텍 소프트웨어 프로그램을 통해서 우선 project.bin를 타겟 노어 플래시 메모리에 Write를 합니다. 그리고 다시 project.elf을 호스트 피씨 램에 다운로드를 하죠. 어떻게 하냐고요?
제이텍 소프트웨어 프로그램에서 사용하는 명령어가 따로 있답니다.

[타겟 노어 플래시 메모리에 Binary를 올릴 때 사용하는 명령어]
Flash.Erase 0x0--0x003FFFFF
Flash.Program all
data.load.binary project.bin 0x0
Flash.Program off

[호스트 피씨 램에 ELF 심볼 정보를 올릴 때 사용하는 명령어]
data.load.elf project.elf /nocode

여기까지 됐다면 이제 이러한 화면을 볼 수가 있어요.

씨 소스 디버깅 윈도우는 개발자가 만든 씨 소스레벨로 한 라인씩 실행을 하면서 프로그램 수행 순서를 모두 추적해 볼 수가 있도록 도와 주죠. 해당 소스라인에 브레이크 포인트를 사용해서 프로그램이 수행하면서 해당 위치에서 멈추게도 할 수가 있죠. 플래시 메모리 덤프는 플래시 메모리에 들어 있는 바이너리를 보거나 패리퍼럴 레지스터 값을 읽어올 수가 있으며 직접 레지스터에다 데이터를 쓸 수도 있답니다. 예를 들어 GPIO 25핀에 RED LED가 있으며, 개발자는 RED LED에 High 신호를 줘서 LED ON하는 프로그램을 만들었는데 LED가 On 안 된다면 무엇일 문제인지 디버깅을 해 봐야 하죠. 이를 경우 PIO25핀에 해당 되는 곳을 덤프하고 그 때의 값이 무엇인지 확인 해 봐야 하죠.
'1' 값이 있었다면 High 신호가 들어갔기 때문에 프로그램 상에는 문제가 없다는 뜻이죠. 즉, HW 문제임을 알 수가 있어요. 반면 '0' 값이 있었다면 Low 신호이고 개발자가 프로그램을 잘 못 만들었다는 것을 알 수가 있어요. 이제 덤프 값이 '0'이라는 것을 확인 했으니 GPIO 25핀에 '0'으로 Write가 됐을 때 Breakpoint 조건으로 설정하면 어떤 소스 라인이 '0'이라는 값을 Write를 했는지를 알아 볼 수가 있답니다. 개발자가 '0'으로 했는지 아님 다른 누군가가 '0'으로 했는지 범인이 밝혀지는 거죠. ㅎㅎ
함수 콜 히스토리는 프로그램 수행 순서가 어떻게 되어 왔는지를 한 눈에 알아 볼 수가 있으며 해당 함수에 있는 로컬 변수의 값을 모니터링 할 수가 있답니다. 예를 들어 휴대폰 화면이 먹통이 돼서 데드락 상태일 때 개발자가 만들 프로그램이 어떤 함수를 걸쳐서 현재 데드락 상태가 됐는지 알고 싶다면 이 윈도우를 사용하면 된답니다. 마지막으로 암 코어 레지스터들 입니다.
개발자가 만든 씨 프로그램을 컴파일러로 빌드 해서 바이너리를 만든 다음 플래시 메모리에 넣게 되죠. 플래시 메모리에 있는 바이너리를 하드웨어 디버거 소프트웨어로 보면 바이너리를 읽을 때 패치(Fetch)하고, 디코딩(Decoding)을 해서 보면 암 코어 기계어라고 불리는 코드로 보인답니다. 여기서 우리는 암 코어에 해당 되는 레지스터들을 확인해 볼 수가 있지요.

그림과 같이 R3는 암 코어 레지스터 중 R3라는 레지스터와 관련 있다는 것을 알 수가 있지요. 기계 명령어 자체는 무엇인지는 잘 모르지만 메모리에 있는 바이너리를 암 코어 입장에서는 기계어 명령어라는 뜻이기도 하죠.
예전에는 숙련된 개발자의 노하우 또는 어떻게 수행 될 거라는 것을 추측에 의해 한 것이 디버깅이었다면 근래에는 하드웨어 디버깅은 직접 눈으로 확인을 할 수 있는 좋은 툴이고 잘 사용하는 것 또한 중요한 시점이기도 하죠.

Linked at 친절한 임베디드 시스템 개발자.. at 2010/07/04 22:41

... 306 인라인 어셈블러를 사용하려면? 307 소스레벨 디버깅이 뭐죠? 308 엠엠유(MMU)와 캐시(Cache)를 사용하려면 어떻게 하죠? &nbsp ... more

Commented by ruring at 2010/07/05 10:28
에러! 범인을 찾아라 편이군요 ㅎㅎㅎ
Commented by soto at 2010/07/05 13:07
네...
정확하게 이해를 하셨군요...^^
무더운 날씨인데, 더위 조심하시구요...
즐거운 한 주 되세요. ~~!!!



Commented by highseek at 2010/07/05 22:30
음? 소스 레벨 디버깅은 눈으로 찾는 디버깅 아니었냐며..(...)
Commented by soto at 2010/08/03 08:22
소스 레벨은 눈으로도 찾을 수가 있지만..

결국 타겟을 동작시키는 것은 암 코어이고,
암 코어는 컴파일러가 만들어낸 바이너리를 읽고 실행하는 것이며
컴파일러는 개발자가 만든 소스를 가지고 빌드하는 거죠.
중요한건 개발자가 만든 소스 순서대로 바이너리가 만들어지면 다행이지만
실제로 소스 의도와는 다르게 바이너리가 만들어지는 경우가 많다는게 문제랍니다.
Commented by soto at 2010/08/03 08:25
그리고 소스가 없고 라이브러리로만 제공되는 경우는 더욱더 소스를 볼수가 없답니다. ^^
※ 이 포스트는 더 이상 덧글을 남길 수 없습니다.
친절한 임베디드 시스템 개발자 되기 강좌 글 전체 리스트 (링크) -



댓글





친절한 임베디드 개발자 되기 강좌 글 전체 리스트 (링크) -