본문 바로가기

Hacked Brain/embeddedland.net

임베디드 프로그래머와 부트로더-2

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

== 임베디드 시스템 개발자의 고민
필자가 다니는 회사의 한 개발자는 처음 배운 프로세서가 32비트 원칩 프로세서이다. 특정한 장비 개발 건으로 8비트 원칩을 다룰 일이 생겼는데 프로세서 매뉴얼을 보더니만 씨익 웃고서 “정말 간단한 구조를 가졌네요” 하는 것이다. 필자는 조금 놀랐다. 왜냐하면 예전에 8비트 원칩을 보고 매우 복잡하다는 생각을 많이 했기 때문이었다. 물론 이전에는 Z-80이나 6502 같은 좀더 단순한 프로세서만 보다가 8비트 원칩을 보았기 때문이기도 하다.
문제는 필자와 같이 기존 8비트 원칩 프로세서를 다루던 개발자들이 32비트 원칩 프로세서를 보면 매우 복잡해 보인다는 것이다. 8비트 원칩 프로세서가 다루던 4MHz와는 차원이 다르게 클럭 속도가 50~400MHz 프로세서를 보면 기가 질릴 정도다. 더구나 이 글을 쓰기 바로 전 달에 삼성에서는 500MHz의 CPU를 개발했다는 소식을 전하고 있다. 사용되는 주변 메모리도 내장되어 있던 것과 달리 SDRAM처럼 조금은 복잡한 디바이스들이 붙는 것이다.
하드웨어 개발자가 이러할진대 해당 칩에 펌웨어를 넣어야 하는 프로그램 개발자들은 어떠하겠는가. 그냥 한숨만 나올 뿐일 것이다. 단순하게 기존 8비트 원칩 프로세서에서 만들던 정도의 기능만을 구현하면 그나마 덜하겠지만 TCP/IP 네트워크 기능이라도 붙인다거나 GUI 화면을 구성하거나 PCMCIA와 같은 디바이스를 붙인다면 막막함 그 자체일 것이다. 임베디드 시스템 프로그래머들이 단순하게 펌웨어 자체만 열심히 짠다고 해결되는 것이 아닌 것이다. 그나마 인터넷의 오픈 소스 운동에 더불어 소스포지 같은 곳에서 남들이 열심히 작성한 소스를 가지고 와서 이리 맞추고 저리 맞추고 하기는 하지만, 개발 기간이 짧기로는 세계 2위로 치부해도 서운한 우리나라에서 프로그램 개발자들의 고충은 이만저만한 것이 아니다.
그렇다고 회사가 부유하거나 개발하려는 제품의 단가가 높아서 상용 OS를 사용한다면 그나마 천국에서 일하는 것이겠지만 열악한 환경에서 오늘도 밤 새워가며 고군분투하는 우리나라 프로그래머들에게 상용 OS를 사용한다는 것은 정말 꿈같은 일인 것이다. 대부분의 경영자는 그렇지 않겠지만 일부 몰지각한 경영자들은 좋은 프로세서가 있는데 왜 개발이 늦어지고 품질이 안 나오느냐고 윽박지르기만 하고 있으니 개발자들은 하루하루 비탄의 나날을 살 수밖에 없다. 이런 프로그래머들에게 한줄기 서광이 비추기 시작한 것이 바로 리눅스의 등장이다.

== 리눅스와 임베디드 시스템
요즘에 웬만한 사람이라면 알고 있는 리눅스는 초기에 PC에서 사용되는 프로세서인 인텔 i386 프로세서 계열만 지원했다. 그러다가 다른 CPU에 포팅을 하면서 아키텍처 의존적인 코드들이 정리되기 시작했다. 이런 정리가 이뤄진 이후에 리눅스 해커들은 자신이 사용하는 시스템의 프로세서에 하나 둘씩 이식해 가는 숫자를 늘려 갔고 덕분에 리눅스 커널은 다른 아키텍처에 이식하기 쉬운 구조가 되었다.
그러나 초기에는 고기능의 프로세서에 커널 포팅을 수행했기 때문에 주로 알파 프로세서 같은 고성능 프로세서에만 포팅이 가능했다. 더군다나 아무리 이식성이 우수하다고 해서 8비트 원칩 프로세서와 같은 계열에 포팅한다는 것은 말도 안된다. 16비트 프로세서인 인텔 286에 포팅하는 프로젝트도 존재하기는 하지만 지금은 진행이 미미한 상태이다. 즉 어느 정도 프로세서가 받쳐 주어야 한다는 것이다. 리눅스 커널이 필요로 하는 최소 사양이 32비트 처리 능력과 최소한 메모리 4MB 이상은 되어야 한다. 이것도 최소 사양일 뿐 실제 사용 한다는 것은 무리이다. 하지만 32비트 원칩 프로세서가 등장하면서 상황은 달라졌다. 리눅스 커널이 동작할 수 있는 성능이 보장됐기 때문이다.
필자가 보기에 오픈소스란 개념은 단순하게 소프트웨어만 적용되는 개념이 아닌 듯하다. 예전에 프로세서가 새로 나오면 해당 프로세서의 자료를 구하기는 ‘하늘의 별 따기’였다. 대량으로 소비할 수 있는 회사에 근무하는 개발자들은 이런 소리가 뭔 소린가 하는 생각이 들겠지만 기껏 해봐야 서너 개 사서 개발해야 하는 개발자들은 프로세서 판매자에게 아부에 가까운 아양을 떨어야 매뉴얼이라도 구할 수 있었다. 더구나 참고할 수 있는 레퍼런스 회로도를 구하는 것은 정말 꿈같은 일이기도 했다. 하지만 최근에 판매되는 프로세서들은 해당 프로세서 생산 회사의 홈페이지에 가면 레퍼런스 회로도나 초기 구동용 펌웨어 소스를 쉽게 구할 수 있다. 물론 프로세서에 따라 다르겠지만 기존에 폐쇄적으로 나오던 회사마저 공개로 방향을 바꾸고 있다는 소식이다. 즉, 하드웨어 관련 정보도 오픈소스처럼 공개하는 것이 하나의 추세가 되어가는 것이다. 결국 개발자들이 쉽게 접할 수 있는 프로세서가 시장에 살아 남는다는 것을 프로세서 생산자들도 깨닫게 된 것이다.
이런 공개된 정보 중에 프로세서를 지원하는 리눅스 커널 소스를 공개하는 것도 하나의 흐름이 되었다. 그렇다면 프로세서 생산자들이 왜 리눅스 커널 소스를 공개하고 있는 것일까? 이유는 단 한가지라고 본다. 그만큼 임베디드 시스템 개발자들이 리눅스 커널을 선호하기 때문이다. 굳이 사용하지 않는다면 공개할 이유가 없으니까. 그렇다면 왜 임베디드 개발자들이 리눅스 커널을 사용하려는 것일까?
다른 곳에서 많이 소개되기도 했지만 한번 되짚어 보자. 공짜라는 개념은 집어 치우자. 실제로 커널 소스에 대한 가격은 지불하지 않지만 실제로 개발하다 보면 분명히 그만큼의 돈이 든다(시간도 돈이다). 지금부터 기술하는 내용은 필자가 실제로 개발하면서 느낀 점이다.

◆ 소스가 공개되어 있다
프로그래머들은 의외로 남의 코드를 믿지 않는다. 자신은 절대 아니라고 하지만 어떤 문제가 생기고 자신이 이해하기 힘든 증상이 나타나면 거의 대부분의 프로그래머들은 자신의 코드를 의심하기보다는 주변을 의심한다. 필자는 프로그래머가 고수인지 하수인지를 구별할 때 기준을 자신의 프로그램 버그 가능성과 다른 사람 프로그램 버그 가능성에 대해 의심하는 비율로 나눈다. 다른 사람의 버그 가능성에 대한 의심 비율이 70% 이상이면 그 사람은 분명히 하수다. 반대로 자신의 버그 가능성에 대한 의심 비율이 70% 이상이면 그 사람은 고수다. 그래서 윈도우 98의 에러 메시지를 만든 사람은 필자가 보기에 하수일 가능성이 높다. 시스템에 문제가 생기면 이런 메시지가 뜨기 때문이다.

“응용 프로그램의 잘못된 연산으로 인하여 프로그램이 종료되었습니다.”

이런 의심 많은 프로그래머들에게 소스가 공개되어 있다는 것은 곧 신뢰성과 연관될 수 있다. 또 문제가 생기면 수정할 수도 있다는 것이다. 즉 문제에 대한 제어권이 개발자 자신에게 있는 것이다. 이것은 개발자 입장에서 보면 너무도 중요한 점이다. 문제가 생겨도 해결할 가능성이 아주 조금이라도 있기 때문이다.

◆ 많은 디바이스 드라이버 소스가 포함되어 있다
임베디드 시스템을 개발하는 프로그래머의 최대 고민은 주변 디바이스의 제어 프로그램을 작성하는 것이다. 매뉴얼이 아무리 자세하게 나오더라도 디바이스 제어 루틴을 짜면서 고생하지 않은 프로그래머들은 거의 없을 것이다. 더구나 대부분의 매뉴얼이 영어라서 부정문에서 한번 헛갈리면 별 것 아닌 문제로 며칠을 낭비하는 경우가 종종 있기 때문이다. 이런 디바이스의 제어에 필요한 웬만한 소스가 커널에 존재하고 있기 때문에 리눅스 프로그래머는 처음부터 다시 작성해야 하는 경우가 매우 적어진다. 필자가 임베디드 시스템에 리눅스를 적용하면서 처음부터 고생하면서 다시 작성해야 했던 디바이스는 몇 개 안된다. 이것 하나만으로도 리눅스 커널을 임베디드에 사용하는 필자는 본전을 뽑았다.

◆ 응용 프로그램이 하드웨어 구조에 영향을 적게 받는다
OS 없이 개발하던 펌웨어의 경우에는 응용 프로그램과 OS의 개념 구분이 없기 때문에 항상 새로운 하드웨어를 도입하게 되면 처음부터 다시 작성해야 한다는 마음을 먹어야 한다. 물론 오랜 경험 끝에 이렇게 다시 작성해야 하는 경우를 최소한으로 하려고 최선을 다하지만 프로세서나 하드웨어 구조가 바뀌면 처음부터 새로 구축하고 싶은 유혹을 떨쳐 버리기 힘들다.
하지만 리눅스 커널을 사용한다면 새로 작성해야 하는 부분이 상당히 준다. 즉 응용 프로그램 소스는 거의 손대지 않아도 된다는 것이다. 왜냐하면 하드웨어에 관련된 부분은 거의 커널 수준에서 맞춰주면 된다. 또 실제로 하드웨어가 바뀌더라도 가급적이면 응용 프로그램의 수정이 없도록 디바이스 드라이버 단에서 맞춘다. 임베디드 시스템 개발 기간의 대부분이 응용 프로그램 작성으로 소모된다는 점만 보면 이것은 개발 생산성이라는 측면에서 엄청난 이득이다.

◆ 실제 하드웨어가 없어도 응용 프로그램을 구현할 수 있다
임베디드 시스템의 개발 스케쥴을 보면 대부분 하드웨어가 준비된 이후에 소프트웨어 개발을 진행하는 방식을 택한다. 그만큼 하드웨어 의존적인 코드가 많기 때문에 미리 하기가 힘들고 시험 자체도 검증되지 않기 때문이다. 그나마 가상 코드라고 해서 미리 컴파일 에러만 잡고 로직을 만들어 가는데 이것도 결국 하드웨어가 나온 후 동작시키면 엄청나게 수정되는 경우가 비일비재하다. 그래서 하드웨어가 나오기 전에 개발은 별 의미없는 경우가 많다.
하지만 리눅스 커널이 동작하는 환경이라면 PC나 임베디드 시스템이나 응용 프로그램 구현 방식이 같다. 필요한 하드웨어 제어는 디바이스 드라이버의 접근에 대한 처리를 에뮬레이션 형태로 해주면 대부분의 로직이 검증되기 때문이다. 필자 역시 이 방식을 즐겨 사용한다. 결국 개발 시간을 잡아먹는 것은 응용 프로그램 제작이기 때문이다. 그리고 하드웨어 검증까지 지켜보면 결국 시간에 쫓겨서 고생하는 것은 프로그래머 몫이다.

◆ 참조할 만한 응용 프로그램들의 소스는 대부분 리눅스 애플리케이션 소스다
간단한 응용 프로그램이야 별 문제 없지만 동영상 구현같이 복잡한 애플리케이션을 처음부터 자신이 만들어 간다면 엄청난 시간이 걸릴 것이다. 그런데 이런 기능이 구현된 소스는 인터넷에서 쉽게 구할 수 있다(물론 필요한 기능에 따라 다르겠지만). 문제는 이런 응용 프로그램 대부분이 리눅스에서 동작하는 경우가 많다는 것이다. 그래서 필히 리눅스 프로그램 방식에 익숙하지 않으면 고생하기 십상이다. 결국 리눅스 커널을 도입한다는 것은 리눅스 프로그램 방식에 익숙해지는 것이기 때문에 아무래도 일반 펌웨어 프로그래머보다는 유리하다.
앞에서 열거한 니용 외에도 많은 장점이 있다. 이 때문에 전 세계의 많은 개발자들이 리눅스 커널을 임베디드 시스템에 적용하는 것이다.