본문 바로가기

Hacked Brain/embeddedland.net

ARM 부트로더 제작기 보드를 살려보자-1

저 자 : 유영창
출판일 : 2003년11월호

임베디드 시스템에서 하드웨어 설계가 끝나고 제작 후 샘플 보드가 나왔을 때 가장 먼저 하는 것이 보드에 대한 검증이다. 필자가 다니는 회사에서는 이것을 ‘보드 살리기’라는 말로 표현한다. 이 보드 살리기는 운이 좋으면 바로, 운이 나쁘면 언제 끝날지 모르는 피 말리는 시간이 필요하다. 이런 현상이 발생하는 이유는 문제의 원인이 하나가 아니고 여러 가지가 혼재하기 때문이다. 어떤 문제를 해결하는 가장 빠른 방법은 문제의 종류를 구분하는 것이다. 그런데 이 경우에는 이 자체도 매우 어렵다는 것이다. 하드웨어 문제인가? 소프트웨어 문제인가? 때문에 보드 살리기에 필요한 과정을 살펴보고 부트로더와의 관계를 살펴보자.

연+재+순+서
1회 2003.10 | 임베디드 프로그래머와 부트로더
2회 2003.11 | 보드를 살려보자
3회 | 부트로더의 기본 구현
4회 | 부트로더의 네트워크 구현
5회 | 커널로의 진입

연+재+가+이+드
운영체제 | 리눅스
개발도구 | GNU gcc 크로스 컴파일러
기본지식 | 리눅스 운영
응용분야 | 임베디드 리눅스 애플리케이션간 상호 운용 등

유영창 | frog@falinux.com
필자는 제이닷디앤티의 기술이사로 근무 중이다. 원래는 윈도우 시스템 환경의 시스템 프로그래머였다가 그 악명 높은 파란 화면에 질려서 리눅서로 전향(?)했다. 리눅스를 이용해 공장 자동화에 적용시키려다 임베디드 리눅스에 처음 발을 들여놓게 됐다. 하지만 아직도 리눅스의 vi 에디터에 적응하지 못하는 절름발이 리눅서이기도 하다.


임베디드 장비에서 맨 처음 부딪치는 문제가 바로 ‘보드 살리기’이다. 즉 초기 설계된 대로 하드웨어가 제대로 동작하는가를 검증하는 과정이다. 처음부터 새로 공부하면서 구현된 아키텍처가 아닌 이미 구현된 아키텍처에 대한 회로를 다시 만들었을 경우라 치더라도 보드를 동작시켜 보면 처음부터 동작하는 경우는 거의(?) 없다. 대부분의 경우 회로 설계 후 초기 테스트 보드가 나오는 과정까지 여러 형태의 실수가 개입하기 때문이다. 이 경우 기본적인 전원이나 동작 조건은 하드웨어적으로 1차 검증이 된다. 필자가 근무하는 회사에서 보드의 하드웨어 초기 점검 사항은 다음과 같다.

◆ 주 전원의 정상적인 공급
◆ 프로세서 코어 전원의 정상적인 공급
◆ 프로세서 클럭의 정상적인 동작
◆ JTAG의 동작 및 프로세서 ID 체크
◆ ‘이지플래시’ 프로그램과 같은 플래시 라이터를 이용한 정상적인 부트 롬의 쓰기 처리

이 정도의 점검이 끝나면 프로그래머에게 테스트 코드를 요청한다. 기본적인 부팅 코드가 수행될 수 있다고 보기 때문이다. 보드를 시험하기 위한 부팅 코드와 부트로더를 작성하기 위해서 준비해야 할 것은 개발 환경의 구축이다. 이 개발 환경 구축의 방법은 여러 가지가 있겠지만 리눅스 커널을 이용한 임베디드 시스템 개발이 가장 기본이다. 공개된 크로스 컴파일러 환경을 이용하여 구축하는 경우라면 다음과 같이 준비하여야 한다.

◆ 리눅스가 동작하는 PC
◆ 시리얼 통신 에뮬레이터
◆ 플래시 롬 또는 롬 라이터 툴

이외에 준비할 사항이라면 다음과 같은 환경을 추가로 구축해야 한다.

◆ TFTP 서버
◆ 삼바 환경 설정
◆ 윈도우 PC

문제는 리눅스 환경이다. 필자도 임베디드 리눅스 관련 회사에 근무하지만 아무래도 소스 편집 환경은 윈도우가 편하다. 그래서 개발 서버용 리눅스 PC를 따로 두고 대부분의 개발 작업은 윈도우에서 한다(<그림 1>은 필자가 즐겨 사용하는 개발 환경 구성이다). <그림 1>에서 보듯이 개발 호스트로 리눅스를 사용하는데, 그 이유는 크로스 컴파일러 환경이 리눅스에서 동작하기 때문이다. 따라서 리눅스의 운영체제에 ‘삼바’로 파일을 공유시키고 윈도우에서 편집한다.


그림 1. 필자의 크로스 컴파일러 개발 환경
사용자 삽입 이미지


컴파일을 할 경우에는 X 터미널 에뮬레이터 프로그램을 이용해 리눅스에 명령을 전달한다(필자의 경험에 의하면 국내에서 개발된 XManager라는 프로그램이 가장 편한 것 같다). 주로 전달하는 명령은 컴파일 명령이다. 또한 리눅스 서버는 개발 보드에서 이더넷을 지원할 경우라면 tftp와 같은 파일 전달 서버로써 동작한다. 보드에서 출력되는 시리얼 정보는 ‘token’이라는 공개된 윈도우 프로그램을 주로 이용하고 있다.
이렇게 기본 시스템 환경을 구성하고 나면 이제 가장 골치 아픈 크로스 컴파일 환경을 만들어야 한다. 아무래도 리눅스 커널을 이용한 임베디드 시스템을 구성할 때는 리눅스에 크로스 컴파일 환경을 만드는 것이 유리하기 때문에 이 크로스 컴파일이라는 것에 대해 자세하게 알아보자.

== 크로스 컴파일 환경 구축
대부분의 프로그래머들은 PC라는 동일한 환경에서 프로그램을 작성한다. PC에서 프로그램을 짜고 컴파일하고, 또 실행 파일도 PC에서 수행한다. 이렇게 동일한 환경에서 동작되는 컴파일러와 이 컴파일러에서 생성된 실행 파일을 동일한 환경에서 수행한다면 이 때의 컴파일러를 ‘네이티브(native) 컴파일러’라고 한다. 이와 반대로 컴파일러가 동작하는 시스템과 컴파일러에 의해서 생성된 실행 파일이 동작하는 시스템이 다를 때 이 컴파일러를 ‘크로스(cross) 컴파일러’라고 한다.
임베디드 시스템에 동작하는 프로그램을 작성한다면 당연히 크로스 컴파일러 환경을 구축해야 한다. 개발 환경은 PC일 것이고 실행 파일이 동작하는 시스템은 다른 CPU 구성을 갖는 임베디드 시스템일 것이기 때문이다. 그렇다고 모든 임베디드 시스템에 동작하는 프로그램들이 꼭 크로스 컴파일 환경을 필요로 하는 것은 아니다.
반면 PC와 같은 구조를 갖는 임베디드 리눅스 시스템을 만든다면 PC의 네이티브 컴파일러에서 만들어진 실행 파일이 그대로 수행될 수 있다. 하지만 임베디드 시스템이 대부분 저렴한 가격대를 요구(PC를 이용한 시스템은 가격이 높아질 수밖에 없다)하거나 특수한 기능을 수행하는 구조를 가지기 때문에 이런 경우는 드문 편이다. 그나마 개발 프로세스를 빠르게 진행하기 위해서 익숙한 PC 구조를 사용하는 것이 요즘 들어 많아지는 추세이기는 하지만 말이다.
어쨌든 크로스 컴파일 환경에서의 개발은 기존 윈도우 개발자 입장에서 보면 매우 열악한 개발 환경이 된다. 돈이 많은 회사야 좋은 개발 툴을 사서 일부 개선하겠지만 그래도 열악하기는 마찬가지다. 이 환경의 가장 단적인 불편 사항은 컴파일이 끝난 후 실행 파일을 즉시 시험하지 못한다는 것이다. 이외에 개발 과정에서 손가락이 무척 바빠지는 것도 빼놓을 수 없는 요인이다. 단순하게 마우스 클릭 한번으로 수행되는 윈도우의 RAD형 컴파일러에 익숙한 사람이 뭔가를 하기 위해서 타이핑하는 것은 무척 힘들기 때문이다.
그래도 이렇게 불편한 리눅스에서 동작하는 크로스 컴파일러를 사용하는 것에는 나름대로 이유가 있다. 지금은 예전과 달리 많은 사람들이 임베디드 시스템 개발에 리눅스를 사용한다는 것쯤은 알고 있다. 하지만 그 이유가 리눅스 커널을 임베디드 시스템에 탑재하기 때문이라고 알고 있다면 이는 잘못된 상식이다. 오히려 임베디드 시스템 개발 환경으로 리눅스를 사용하는 근본적인 이유는 gcc라는 막강한 컴파일러가 있기 때문이라고 할 수 있다.
리눅스만 사용하는 사람이라면 리눅스 프로그램 개발을 위해서 당연히 gcc라는 컴파일러를 사용한다. 그래서 gcc라는 것이 그냥 리눅스용 컴파일러라고 알고 있다. 하지만 gcc는 그렇게 단순한 컴파일러가 아니며, 또한 gcc는 그냥 i386 프로세서에서 동작하는 실행 파일을 만들어내는 컴파일러가 아니다. 현재 존재하는 컴파일러 중에서 가장 많은 프로세서를 지원하는 컴파일러가 바로 gcc이다. gcc 컴파일러 패키지는 이미 전 세계에 동작되는 대부분의 프로세서를 지원하기 위한 준비를 갖추고 있다. 더구나 공짜다. 하지만 대부분의 사람들은 이런 gcc가 어떻게 다른 CPU를 지원하게 할 수 있는지에 대해서는 잘 모른다. 그냥 gcc 명령을 치면 i386 코드가 생성되기 때문이다.
별빛(byeolbich)