뭘 알아야 이해를 하지
임베디드 시스템은 윈도우가 설치되어 있는 개발 환경과 다르게 디버깅이 아주 중요하답니다. 일반적으로 윈도우가 설치되어 있는 호스트 피시에서 개발을 할 때는 모니터로 printf 메시지 출력이나 IDE 툴을 통해 쉽게 디버깅을 할 수가 있는 반면 임베디드 시스템은 모니터로 없고 IDE 툴이 윈도우 만큼 잘 되어 있지 않죠. 우선 임베디드 시스템에서는 printf로 메시지를 출력하려면 앞서 말씀 드린 바와 같이 시리얼 컨트롤 레지스터를 초기화 시켜야 하고, 시리얼 케이블을 호스트 피씨와 연결을 한 후 하이퍼터미널과 같은 프로그램으로 메시지를 봐야 하죠. 만약 임베디드 시스템에서 시리얼 포트가 없다거나 시리얼 포트는 있지만 아직 시리얼 컨트롤 레지스터 초기화 전이라면 메시지 출력이 안돼서 디버깅이 어렵겠죠? 그럼 일반적으로 개발 업체는 두 가지 디버깅 방법을 병행해서 개발을 한답니다.
디버깅은 주로 소프트웨어 디버깅과 하드웨어 디버깅이 있죠.
앞서 말씀드린 것처럼 소프트웨어 디버깅은 주로 씨 언어 프로그램에다 printf 명령어를 사용해서 터미널 프로그램으로 메시지를 출력해서 디버깅을 한답니다. 반대로 하드웨어 디버깅은 제이텍(JTAG) 장비를 이용하여 프로세서를 언제든지 멈추고, 실행하고, 명령어 하나씩 실행을 해 볼 수도 있지요.
흔히 임베디드 시스템 개발할 때 소스 레벨 디버깅을 한다 라고 하면 대부분 하드웨어 디버깅이라고 보시면 됩니다. 하드웨어 디버깅은 제이텍 장비를 이용하여 개발자가 씨 언어 소스라인뿐만이 아니라 각종 패리퍼럴 컨트롤, 메모리 컨트롤, 시피유 컨트롤 등 다양하게 디버깅을 해 볼 수가 있답니다. 이러한 하드웨어 디버깅을 할 때 반드시 준비해야 될 사양이 있어요.
우선 첫 번째는 제이텍 장비 및 소프트웨어 프로그램, 타겟 시스템, 제이텍 장비와 연결할 수 있는 제이텍 케이블 그리고 컴파일 후 만들어진 project.elf 파일이랍니다. 소스 레벨 디버깅에서 가장 중요한 elf 파일은 헤더, 바이너리, 심볼 정보 등이 들어 있어요.
그럼 제이텍 장비를 통해 소스레벨 디버깅 하는 절차를 알아 보아요.
![](https://blog.kakaocdn.net/dn/btfA7a/btsepJx0Q8M/JRP63cMWKpjKAA3mKLUNGK/img.jpg)
제이텍 소프트웨어 프로그램을 통해서 우선 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
여기까지 됐다면 이제 이러한 화면을 볼 수가 있어요.
![](https://blog.kakaocdn.net/dn/brQvDY/btserfCDps6/UW09YmR99TBbgWJxbGJiL1/img.jpg)
씨 소스 디버깅 윈도우는 개발자가 만든 씨 소스레벨로 한 라인씩 실행을 하면서 프로그램 수행 순서를 모두 추적해 볼 수가 있도록 도와 주죠. 해당 소스라인에 브레이크 포인트를 사용해서 프로그램이 수행하면서 해당 위치에서 멈추게도 할 수가 있죠. 플래시 메모리 덤프는 플래시 메모리에 들어 있는 바이너리를 보거나 패리퍼럴 레지스터 값을 읽어올 수가 있으며 직접 레지스터에다 데이터를 쓸 수도 있답니다. 예를 들어 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)을 해서 보면 암 코어 기계어라고 불리는 코드로 보인답니다. 여기서 우리는 암 코어에 해당 되는 레지스터들을 확인해 볼 수가 있지요.
![](https://blog.kakaocdn.net/dn/n1tAR/btseqnH05Ml/xgQhyFYd6B40jbsj7TmGi1/img.jpg)
그림과 같이 R3는 암 코어 레지스터 중 R3라는 레지스터와 관련 있다는 것을 알 수가 있지요. 기계 명령어 자체는 무엇인지는 잘 모르지만 메모리에 있는 바이너리를 암 코어 입장에서는 기계어 명령어라는 뜻이기도 하죠.
예전에는 숙련된 개발자의 노하우 또는 어떻게 수행 될 거라는 것을 추측에 의해 한 것이 디버깅이었다면 근래에는 하드웨어 디버깅은 직접 눈으로 확인을 할 수 있는 좋은 툴이고 잘 사용하는 것 또한 중요한 시점이기도 하죠.
![](https://tistory1.daumcdn.net/tistory/6281347/skin/images/myface_recipes.jpg)
![](https://tistory1.daumcdn.net/tistory/6281347/skin/images/click15x15.png)
댓글