왜 임베디드는 어렵다고 하는가? 입문부터 맵다.
오픈소스 조직 Go수다에서 닉네임 “백엔드는Go밖에못함”인 익명의 개발자님으로부터 STM32f769i-DISCOVERY를 무료로 선물받았다. STM32f429i-DISCOVERY에 리눅스 포팅에 실패하고 ZephyrOS를 간신히 올린 시점에서, 더 쓸만한 학습용 기판을 택배비까지 받지 않고 기증해 주셨다. 발을 다친 채 집에서 요양하면서 이 기판을 공부해 봤는데, 임베디드 기판 치고는 2MB의 RAM과 16MB의 플래시 메모리를 가졌으며, 외장 SD카드도 탑재해 있다.
우선은 이 기판에 리눅스부터 올려볼 생각이었고, 실제로 그렇게 하였다. 아래는 기판을 가지고 작업하면서 겪은 문제들이다.
Buildroot 설정에서 BusyBox를 경량화해야 한다
보통 BusyBox에는 다양한 리눅스 명령어들이 들어가 있다. 보통은 바이너리 크기도 크다. 그러나 이 기판의 RAM은 2MB이다. 우선 욕심내지 말고 이것저것 들어내야 한다.
- chown, chmod 등 관리 편의성을 위한 도구를 모두 지워야 했다
- 이런 것도 지워야 하는 명령도 지웠다
- 그럼에도 불구하고 메모리 단편화가 일어나면 말썽을 일으켰다
여러모로 라즈베리 파이같은 차고 넘치는 기판만 쓰다가 이것을 사용하니 현장감이 올라가며 식은땀이 줄줄 났다.
여기서 생각해야 할 것은 경량화이다.
바이너리 크기를 최적화해야 한다.
C언어 바이너리를 컴파일할 때에 가장 일반적인 옵션은 -O2이다. 그러나 이러한 환경에서는 성능이 문제가 아니고 바이너리가 RAM에 안 올라갈 가능성이 있다.
-Os로 옵션을 바꿔 크기를 줄이는 것을 우선으로 빌드한다.
또한 리눅스 커널 자체에 포함되는 기능을 줄여 이미지 크기를 줄여야 한다.
사용하지 않을 스택은 제거해라.
- 제네릭 이미지를 위한 없는 하드웨어를 위한 드라이버 제거
- 사용하지 않을 스택 전체를 제거
- 용량이 큰 신규 기능은 웬만하면 제거
SDRAM에 이미지 인젝션? 성능 아끼려다 키지도 못하는 수가 있다
리눅스는 서버나 고성능 임베디드 기판에 넣을 때는 넉넉하지만, 일반적인 임베디드 기판에게는 매우 무거우며, 그것이 RTOS가 훨씬 인기가 좋은 까닭이다.
기본적으로 리눅스 커널을 아무리 경량화해도 KB 단위로 떨어뜨리는 것은 매우 도전적인 과제이며, 설령 그렇게 해도 SDRAM에 이미지를 인젝션해서 빠른 부팅을 노릴 틈이 없다.
얌전하게 U-Boot의 성능을 믿고 부팅해 줘야 한다. 또한 이렇게 램 인젝션을 한다고 해도 이런 환경에서 램을 직접 접근 후 부팅하는 명령을 저장할 수 없는 때가 많다.
U-Boot에서 saveenv가 듣지 않는 것을 보고 탄식하면 늦다.
그럼 어떻게 하면 되나요?
대안은 여러가지이지만 두 가지만 소개한다.
리눅스를 뼈만 사용하자
사용하고 싶은 기능만 내버려 두고 모두 떼어 버린다. 완성된 uImage 등이 자신의 RAM의 절반 이하로 용량이 떨어지면 된다. 통상적으로 프로덕션 시 1MB대로 떨어뜨려 빌드하는 경우가 많다고 들었다. 가능하면 바이너리 크기는 줄여 주는 것이 유리하다.
RTOS를 사용하자
이것은 내가 STM32f429i-DISCOVERY를 사용할 때 써 먹었다. ZephyrOS, FreeRTOS 등은 정말로 이미지가 KB 단위이다. 램이 거의 온전히 남아 도는 것을 본다면 당신의 프로젝트 아이디어는 마구 샘솟을 것이다. 만약 아두이노 수준에서 한두발만 더 나아갔더라도 포트폴리오를 위한 과시가 아니고 실제 장난감을 만들 것이라면 이렇게 하자.
결론
임베디드 업계가 맵다고 하는 것이 빈말이 아니다. 이것이 다른 업계로 따지면 “스프링으로 Hello World 찍기”나, “Go언어로 쿠버네티스 활성 노드 가져오기”에 해당하는 단계이다. 이 진입장벽을 넘지 못한다면 임베디드를 공부하는 데에 아주 애로사항이 생긴다. 갑자기 가이드에서 튀어나오는 HEX값, 지옥의 주소 디버깅을 모두 넘어서 자기 장난감을 자기가 만든다면 이제 포트폴리오 1개가 완성되는 것이다. 아주 공부하기 무서운 방향성이지만 취미로 시간을 길게 가진다면 못 할 것도 없다. 가끔 시간이 나면 다루도록 하겠다.