본문 바로가기
ARM 프로세서에 Linux 포팅을 위한 준비사항은?

뭘 알아야 이해를 하지

Linux 포팅하기 위한 단계가 있답니다.
호스트 피시에 Linux 설치 - 크로스 컴파일 설치 및 환경 설정 - 부트로더 빌드 - 커널 빌드 - 파일 시스템 빌드 - 개발 보드의 플래시 메모리에 바이너리 넣기 - 어플리케이션 프로그램 개발 - 디버깅 - 개발 완료

첫 번째, 호스트 피시에 Linux 설치부터 자세히 알아 보죠. 우선 다음과 같은 사항이 준비 되어야 한답니다.

1. 호스트 피시에 Linux 설치
2. 개발 보드 확보
3. 크로스 컴파일러
4. 보드 BSP(Board Support Package)

호스트 피시에 Linux를 설치해야 하는데, Linux OS 종류가 워낙 많다 보니 어떤 것을 설치해야 될지 모를 때가 있답니다. 아무거나 설치해도 상관은 없지만, Linux OS마다 명령어가 조금 다르거나 필요한 파일이 없어서 개발자가 직접 설치를 해야 되는 것들이 있지요. 가장 좋은 것은 구매한 개발 보드와 함께 제공되는 CD에서 포팅 관련된 문서를 읽어보시면 추천하는 Linux OS가 있으니, 그것을 설치하시면 된답니다.
Linux 포팅에 있어서 가장 중요한 것은 바로 개발보드 선정이랍니다. 개발 보드도 유행을 타기 때문에 현재 가장 많이 쓰이고 있는 시피유를 중심으로 만들어 진답니다. 불과 2전전까지만 해도 ARM9 시피유에 Linux 포팅을 많이 했지만 현재는 ARM11 시피유에 Linux를 포팅 많이 하고 있는 추세죠. 즉, 암 시피유가 유행을 타는 것과 동시에 Linux 커널 버전도 함께 발전을 하죠. 아무리 암 시피유가 최근에 나왔다고 좋은 것만은 아니죠. 왜냐하면 Linux OS가 그 시피유를 지원해야 하니깐요. 반대로 최근에 Linux OS 개발됐다면 오래된 시피유를 사용할 필요가 없겠죠? 이와 같이 서로간의 이해 관계가 잘 형성되어 있기 때문에 개발 보드, 유행인 시피유 그리고 Linux OS까지.. 마치 잘 연결된 먹이 쇠사슬처럼 되어 있죠.
개발 보드를 구매하실 때 한 가지 더 중요한 것이 BSP인데요, 개발 보드를 만드는 회사는 단순히 개발 보드만 만드는 것이 아니라 BSP도 함께 만든답니다. BSP가 없으면 Linux 포팅은 아주 힘들다고 보셔야 해요. 그래서 개발 보드 만드는 회사는 BSP를 얼마나 잘 관리하고 있고, 업데이트는 계속하고 있는지, 기술지원 문의 했을 때 답변도 잘 해 주는지 등을 잘 따져 보시고 고르셔야 해요.

LInux OS 설치와 개발 보드를 가지고 계신다면 이제부터 크로스 컴파일러 설치와 빌드를 해 보도록 하죠. 크로스 컴파일러는 개발 보드와 함께 제공되는 CD안에 컴파일러가 들어 있답니다. CD안에는 컴파일러 및 BSP가 들어 있으며 BSP에는 부트로더, 커널, 파일 시스템이 압축 파일로 제공되고 있답니다.
우선 제일 먼저 컴파일러 설치 방법부터 빌드 과정까지의 내용을 담아 놓은 문서가 있는지도 찾아보세요. 문서가 있다면 순서대로 따라만 하시면 됩니다. 대부분의 문서 내용은 이와 같이 나와 있을 겁니다.

컴파일러 설치 방법이랍니다. 크로스 컴파일러는 일반적으로 배포가 될 당시 압축된 파일 형태로 되어 있답니다. 이 파일을 압축 풀고 나서 설치된 곳의 패스만 설정해 주면 크로스 컴파일러 설치는 끝납니다. 개발 보드를 만드는 회사는 크로스 컴파일러만 압축된 파일로 배포 하거나 크로스 컴파일러와 파일 시스템을 함께 압축해서 배포하기도 하죠. 아래의 예는 크로스 컴파일러가 압축되어 있고, 이 파일을 /opt 폴더로 압축 푸는 과정이랍니다.

# tar xfz 4.2.4-eabi-arm-s3c6410_toolchain.tar.gz -C /opt

압축이 풀리고 나면 크로스 컴파일러가 설치된 패스를 설정해야 합니다. 패스 추가하기 위해서는 Linux OS에서 가장 흔히 사용하는 에디터인 vim이라는 프로그램을 사용하지요.


# vim /root/.bashrc

.....
# cross toolchain path
export PATH=/opt/4.2.4-eabi-arm-s3c6410/bin:$PATH

패스 설정이 끝났으면 현재 사용하는 개정을 로그 아웃하고 다시 로그인을 하면 됩니다.
패스가 잘 설정되어 있는지 확인을 해 봐야 해요. 아래와 같은 명령어를 사용해 gcc version 4.2.4 라는 메시지가 나왔는지 확인을 하시고, 나왔다면 패스 설정이 잘 됐다고 보시면 된답니다.


# arm-generic-linux-gnueabi-gcc -v
gcc version 4.2.4


크로스 컴파일러가 설치가 되었으니 간단한 어플리케이션 하나를 만들어 실행을 해 보죠.

# vim hello.c

이제 컴파일입니다.

# arm-generic-linux-gnueabi-gcc -o hello hello.c
# ls
hello hello.c

항상 이렇게 컴파일을 할 수 없으니 Makefile을 하나 만들어 사용을 해 봐요.

그리고 컴파일 하기


# make
# ls
hello hello.c


과연 암 시피유에서 동작할 수 있도록 만들어졌을까요? file 유틸리티를 통해 확인을 해 보아요.
# file hello
hello: ELF 32-bit LSB executable, ARM, version 1 (SYSV), for GNU/Linux 2.6.21,
dynamically linked (uses shared libs), not stripped

ARM은 ARM 용 시피유에서 동작할 수 있는 것을 뜻하는데, hell을 개발보드에서 실행을 해야 결과를 볼 수가 있답니다. not stripped는 파일 용량을 줄이지 않았다는 뜻이랍니다. 파일 용량을 줄인다는 것은 hello 파일이 not stripped 된 형태로도 만들어질 수 있으며, stripped된 상태로도 만들어 질 수가 있어요. 하지만 어떤 형태로 만들어졌느냐에 따라 파일 시스템이 만들어 질 당시 파일 시스템의 전체 용량에서 차이가 나죠. 즉, 파일 시스템은 플래시 메모리에 들어가는데 플래시 메모리를 조금이라도 절약을 하기 위해서는 아무래도 stripped된 파일 형태로 만들면 파일 시스템 용량이 줄어들어 절약을 할 수가 있죠. 디폴트는 not stripped 이라고 보시면 됩니다.

strip은 다음과 같은 명령어를 사용하시면 되요.~~~!!

# arm-generic-linux-gnueabi-strip hello

# 부트로더
부트로더 빌드 방법에 대해 알아보죠.
우선 부트로더의 역할에 대해 알아보죠. 부트로더는 많은 역할을 하지만 가장 큰 역할은 커널을 에스디램으로 복사 시켜 주는 역할이랍니다. 즉, 개발 보드 플래시 메모리에는 부트로더 바이너리, 커널 바이너리, 파일 시스템 바이너리가 들어 있어요. 개발 보드에 전원이 들어가면 가장 먼저 부트로더가 동작을 하며, 부트로더는 플래시 메모리에 있는 커널을 에스디램으로 복사한답니다. 이러한 이유 때문에 부트로더는 플래시 메모리를 쉽게 읽고, 쓰고, 지우는 작업을 할 수가 있어야 하죠.

부트로더 압축을 풀어 보죠.

# tar xfz u-boot-1.1.6.tar.gz

압축이 모두 풀렸다면, 크로스 컴파일러의 GCC인 컴파일러 이름을 적어 두면 됩니다.

# cd u-boot-1.1.6
# vim make
....

CROSS_COMPILE = arm-generic-linux-gnueabi-
......


이제 빌드도 준비 됐으니, 아래와 같이 make를 해 보죠.

# make clobber
# make distclean
# make boardname_config
Configuring for board name...
# make

빌드가 모드 끝나면, u-boot.bin 파일이 생성된답니다.

# 커널
다음으로는 커널 빌드 과정이랍니다.
개발자는 커널 옵션을 선택해서 빌드하면 커널을 만들 수가 있답니다. 커널 옵션은 상당히 많아서 어떤 것을 선택해야 될지 잘 모르는 경우가 있으니 배포된 커널을 압축 풀어보면 default로 커널 옵션에 대해 설정된 파일이 있답니다. 그 파일을 사용하시면 개발 보드에 맞게 기본적인 리눅스 커널로 만들어 진답니다.

# tar xfj linux-2.6.21.5tar.bz2
# cd linux-2.6.21.5
# make distclean
# make 6410_config @ 개발 보드에 맞게 커널 옵션이 설정된 파일
# make

빌드가 끝나고 나면 커널 이미지는 $6410_linux\linux-2.6.21.5\arch\arm\boot 폴더에 zImage로 만들어 진답니다. zImage는 압축된 이미지이며, 순수한 커널 바이너리는 $6410_linux\linux-2.6.21.5\arch\arm\boot\compressed\piggy.o 파일이랍니다. Makefile을 자세히 분석해 보면 zImage에 대해 잘 알 수가 있는데요, 커널 빌드가 끝나는 마지막 단계를 보시면 최종 piggy.o 파일이 생성되고, 그 파일은 다시 압축이 되지요. 그때 만들어진 파일 이름이 piggy.gz 파일이고, 이 파일은 압축된 형태이기 때문에 압축 풀기 위한 알고리즘 파일인 head와 misc파일이 최종 빌드 되면서 zImage로 만들어 진답니다. 그래서 부트로더는 커널 압축 이미지(zImage)를 에스디램으로 복사한 뒤 제어권을 커널로 넘기면, 커널 압축 이미지인 zImage의 head이 먼저 실행되고, misc 파일이 실행되면서 piggy.gz 파일을 에스디램의 일정한 주소 영역에다 압축을 풀게 되어 있죠. 이 때 압축 풀린 이미지(piggy.o)가 바로 순수한 커널 이미지인거죠.

# 파일 시스템
다음으로는 파일 시스템이랍니다.
호스트 피시에 윈도우즈를 설치하고 나면 디폴트로 생성된 폴더가 있듯이 Linux OS도 디폴드로 생성되는 폴더가 있답니다. 단지 차이점은 윈도우즈는 자동으로 생성되고 Linux OS는 개발자가 원하는대로 직접 만들 수가 있답니다.
Linux OS가 동작하기 위해서는 기본적은 폴더 구성이 있답니다.

부트로더가 커널에게 제어권을 넘기고 나면 커널은 기본적인 스케줄러 및 기타의 일들을 모두 마친 후에 파일 시스템에 있는 프로그램 하나를 실행하면서 리눅스 시스템이 동작하게 된답니다. 여기서 가장 먼저 실행하는 프로그램이 Init 이며, 모든 어플리케이션의 부모 프로세스가 된답니다.
Init 프로세스는 /bin 폴더에 있거나 /sbin, /etc 폴더 중에 한곳에 있으면 된답니다. 각 폴더에 대한 설명을 잠시 드리죠.
/bin 폴더는 Linux OS에서 사용하는 가장 기본적인 유틸리티들이 있답니다. ls, cp, mv, cat, echo, sh, v, mount 등등..일반적인 유틸리티는 이곳에 있답니다.
/dev 폴더는 Linux OS에서 디바이스 드라이버를 구동시키기 위해 커널과 디바이스 드라이버를 연결시켜주는 디바이스 노드 라는 파일이 들어 있는 곳이랍니다. null, console, initctl, fb, tty 등등이 있어요.
/etc 폴더는 환경 설정에 관련한 파일이 이곳에 있답니다. 실행하는 유틸리티보다는 쉘 스크립트로 되어 있거나 text 형태로 되어 있어 경로나 환경 변수에 관련된 내용이 들어 있는 곳이랍니다.
/lib 폴더는 /bin 또는 /sbin 폴더에 있는 유틸리티 파일이 사용하는 라이브러리 파일들이 들어 있는 곳이랍니다.
/mnt 폴더는 마운트를 할 때 사용을 해요. 반드시 필요한 폴더는 아니고 관리나 편리성을 위해 이러한 폴더를 만들고 마운트 할 파일 시스템이 있다면 이곳에다 하죠. 여기서 잠깐!! 마운트의 개념에 대해 알아보죠. 일반적으로 호스트 피시에서 시디롬에 시디를 넣으면 시디의 내용을 바로 볼 수가 있죠. Linux OS는 시디롬에 시디를 넣는다고 해서 바로 읽어 볼 수가 없답니다. 시디 내용을 읽어보시려면 반드시 시디롬을 마운트해야 한답니다. 이러한 마운트를 도와 주는 유틸리티도 필요한데 바로 mount 라는 유틸리티이고 주로 /bin 폴더에 있답니다.
/proc 폴더는 현재 Linux OS가 실행 중이라면, 어떤 프로세스가 실행 중인지를 모두 볼 수 있는 폴더랍니다. 그래서 부팅 전에는 아무것도 없다가 Linux OS가 실행하고 있는 상태라면 많은 내용들이 나온답니다.
/root 폴더는 계정을 뜻한답니다. 일반적으로 Linux OS는 관리자 권한과 유저 권한이 있는데, 관리자 권한일 때 /root 폴더에 관리자 권한에 대한 환경 설정이 들어 있답니다. 유저 권한일 때는 /root가 아닌 /home/username 이라는 폴더로 만들어진답니다. 호스트 피시에서는 이러한 권한 관리가 필요하겠지만 임베디드 시스템에서는 관리자 권한만 있으면 되기 때문에 /root 폴더 하나만 있죠.

/sbin 폴더는 System bin이라고 해서, Linux OS가 동작하기 위해서 반드시 있어야 할 유틸리티들이 있는 곳이랍니다. init, insmod, rmmod, ifconfig, fdisk, route 등등이 있답니다.

/tmp 폴더는 임시로 사용되는 폴더인데 반드시 필요한 폴더는 아니랍니다.

그 외의 폴더는 개발자가 임의의 만들어 주면 되는데, 만약 개발자가 만든 어플리케이션이라고 하면 새로운 폴더를 하나 만들어서 넣어 놓고 부팅하자마자 바로 실행을 하도록 해 주면 된답니다.

이제 이렇게 폴더를 구성했다면, 이 폴더들을 압축해서 하나의 파일로 만들는 작업이 파일 시스템 빌드 랍니다. 여기서 어떻게 압축을 하느냐에 따라 파일 시스템 종류가 달라진답니다. 호스트 피시에 윈도우즈를 설치할 때 주로 FAT32와 NTFS라는 두 종류의 파일 시스템을 선택할 수 있는 것처럼 Linux OS도 선택 가능하고, 윈도우즈 보다 휠씬 많는 파일 시스템을 지원한답니다. 이 폴더들은 물리적인 메모리에 존재해야 하기 때문에 메모리 영역을 나누어서 별도의 파일 시스템으로 관리를 할 수가 있답니다. 예를 들어서 에스디램과 낸드 플래시 메모리가 있다고 하면 에스드램에는 data를 읽고, 쓰기가 가능한 곳이기 때문에 /bin, /dev, /etc, /mnt, /proc, /root, /sbin, /tmp 폴더를 존재하게 하고, 유저가 MP3 파일 등을 저장하기 위한 /data 폴더를 만들고, 이 폴더를 낸드 플래시 메모리로 지정하게 끔 구성을 할 수 있게 한다는 거죠. 왜 MP3 파일을 에스디램에 저장하지 않느냐고요? 에스디램에 MP3가 저장이 되지만 만약 시스템을 리부팅 했을 때는 MP3 파일이 없어지잖아요. ㅋㅋ 그래서 영구적으로 저장하기 위해서는 낸드 플래시 메모리에 저장해야 한답니다. 이렇게 서로 파일 시스템마다 역할이 다르다 보니 서로 다른 파일 시스템으로 환경으로 만들 필요가 있는 거죠. 일반적으로 에스디램에서 가장 많이 사용하는 파일 시스템은 램디스크(Ramdisk) 파일 시스템이 있구요, 낸드 플래시와 같은 곳에 저장하기 위한 파일 시스템은 Jffs2, Yaff2 등이 있답니다.
램디스크 파일 시스템을 만드는 방법은 다음과 같아요.

# ls filesystem_root/
bin/ dev/ etc/ lib/ mnt/ opt/ proc/ root/ sbin/ tmp/ usr/ var/
# mkdir filesystem
# cd filesystem
# dd if=/dev/zero of=ramdisk bs=1k count=16384
# mke2fs ramdisk
mke2fs 1.41.3
ramdisk is not a block special device.
Proceed anyway? (y,n) y
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
……
# mkdir mnt_ramdisk
# mount -t ext2 -o loop ramdisk mnt_ramdisk
# cd mnt_ramdisk
# cp -a /filesystem_root/* ./
# cd ..
# umount mnt_ramdisk
# gzip -vf9 ramdisk
# ls
mnt_ramdisk ramdisk.gz

이러한 작업을 반복적으로 해야 하니 쉘 스크립트로 만들고 난 후 실행 권한으로 바꾼답니다. 마지막으로 실행을 해 보면 램디스크 파일 시스템이 만들어 진답니다.

# vim start

# chmod 777 start @ 스크립트를 실행 권한으로 바꿈
# ./start @ 스크립트가 실행이 됨


# 플래시 메모리에 이미지 올리기
이제 개발 보드의 플래시 메모리에 바이너리 넣는(쓰기) 방법에 대해 알아 보아요.
현재 지금까지 u-boot.bin, zImage, ramdisk.gz 이렇게 3개의 파일이 만들어 졌답니다. 이 파일들은 플래시 메모리에 넣어 보도록 하죠.
부트로더는 커널(zImage)을 에스디램으로 복사를 하기 위해서 플래시 메모리를 쉽게 접근할 수가 있다고 이야기한 바가 있습니다. 그래서 부트로더는 부트로더(u-boot) 자기 자신과 zImage, ramdisk.gz 파일을 플래시 메모리에 넣을 수가 있으며, 일반적으로 플래시 메모리에 쓰기를 한다고 표현하죠. 하지만 어디까지나 이것은 플래시 메모리에 부트로더가 있다는 가정하에 그렇죠. 만약 플래시 메모리에 부트로더가 없다면 최초에 한 번은 하드웨어 장비인 JTAG으로 부트로더를 플래시 메모리에 쓰기를 해야 하죠.

이제 기본적인 시스템을 알았으니 본격적으로 포팅에 들어가보도록 하죠.

Linked at 친절한 임베디드 시스템 개발자.. at 2010/08/22 23:11

... bsp; 403 uC/OS2 포팅 완료까지의 절차가 어떻게 되죠? 404 ARM 프로세서에 Linux 포팅을 위한 준비사항은? 405 Linux 포팅 완료까지의 절차가 어떻게 되죠? &nbsp ... more

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



댓글





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