티스토리 뷰

 1. Selecting the right OS (OS 선택)

  • 하드웨어 고려 (32-bit processor 이상인지), 메모리사용량, real-time인지, 디버깅 및 board bring-up 리눅스 이해필요.

2. Embedded Linux four elements ( 4가지 요소)

  • Toolchain (툴체인) : 타겟 디바이스에 코드를 create 하기위한 compiler 및 다른 툴들. 대부분 툴체인에 dependency가 있음
  • Bootloader (부트로더) :  타겟보드 프로그램 초기화 (initialize) 및 리눅스 커널 로드함.
  • Kernel (커널) : 시스템 리소스 매니지 및 하드웨어 인터페이스
  • Root File System (루트 파일 시스템) : 부트로더에 타겟보드 초기화후, 보드위에서 실행 (run) 되는 프로그램 및 라이브러리 

다른 중요 요소들

- 오픈소스 (GNU umbrella), cpu 아키텍쳐 (ARM-based SoCs, Intel: x86, x86_64, IBM (PowerPC), SoC 벤더 ( Atmel, Intel, Qualcomm, TI 등: 기존 cpu 아키텍쳐에 커널 및 툴체인 수정후 올려서 제공하는형식, Board Vendors 및 OEMs (SoC에 specific 서비스 올려서 판매하는 형식, 예: 세텁박스, development 보드 (비글본, 레스베리파이)

 

벤더 선택시 고려사항: 커널 버전 패치가 자주 업데이트 되는지, 보통 SoC벤더는 오픈소스패치는 많이 올리는데 커널업데는 거의 안됨. 예) OpenSSL 라이브러리 버그: heardbleed

 

3. 오픈소스 라이브러리

- 크게 두가지 카테고리:

General Public License (GPL) = copyleft

Berkely Software Distribution (BSD) = permissive 

예) tivoization

 

4. Embedded Linux 하드웨어 고려사항

- Memory Management Unit (보통 32bit or 64bit 아케텍쳐는 MMU가 잇음), MMU없는 디바이스: 마이크로컨트롤러 리눅스, uClinux

- RAM 용량, 최소 4 MiB

- flash memory. 최소 8MiB. SD card, eMMC, USB flash memory 

- 디버그 포트. 보통 RS-232 시리얼 포트

- Joint Test Action Group (JTAG): 부트코드 로드

 

5. QEMU (machine emulator) 

- processor emulate 해줌.

$  qemu-system-arm -machine vexpress-a9 -m 256 -drive 
file=rootfs.ext4, sd -net nic use -kernel zImage -dtb 
vexpress- v2p-ca9.dtb -append "console=ttyAMA0, 115200 root=/dev/mmcblk0" 
- serial stdio -net nic, model=lan9118 -net tap, ifname=tap0
  • -machine vexpress-a9: ARM processor 생성. 다른 아키텍쳐도 가능.
  • -m 256M: 256 RAM 생성
  • -drive file=rootfs.ext4, sd: SD 인터페이스생성 (로컬 파일: rootfs.ext4 이미지 연결)
  • -kernel zImage: 리눅스 커널 로드 (zImage: 로컬파일)
  • -dtb vexpress-v2p-ca9.dtb: 디바이스 트리 로드 (vexpress-v2p-ca9.dtb: 로컬파일)
  • -append "..."
  • -serial stdio: QEMU 터미널에 시리얼 포트 연결해서 QEMU 접속. 
  • -net nic, model=lan9118: 네트워크 인터페이스 생성
  • -net tap, ifname=tap0: Virtual 네트워크 연결 (인터페이스 tap0)

- Host 네트워크 설정

UML (User Mode Linux) 에서 다음과 같이 함.

$ sudo tunctl -u $(whoami) -t tap0

패키지 uml-utilities 다운필요.

QEMU 머신에 인터페이스 (tap0) 연결됨.

 

6. Toolchains (툴체인) 

- 툴체인: "set of tools that compiles source code into executable that can run on your target device"

어셈블리, C, C++

- 컴파일러, linker, 런타임 라이브러리 등

- 초기 툴체인결정 중요. 초기결정후 compiler 및 개발 라이브러리 변경되면 관리안됨. 

- 하드웨어에 최적화된 툴체인 선택필요.

- Embedded Linux 빌드하기 위한 필요세가지: bootloader, kernel, root filesystem.

- 툴체인은 거의 GNU umbrella 안에 있음. 다른 툴체인: Clang, LLVM. 

큰차이는 라이센스. GNU = GPL. Clang = BSD. 이외에 기술적 차이는 Clang은 좀더 빠른 컴파일 타임. GNU GCC는 호환성이 좋음 (현사용하는 코드베이스, OS, 아키텍쳐) 

 

7. GNU Toolchains (툴체인) 

- 메인 Components 세개:

  • Binutils: 바이너리 유틸. 어셈블러 및 링커.

  • GNU Compiler Collection (GCC): 컴파일러. c++, c, java, fortan 등을 assembler코드로 생성
  • C library: os 커널과 인터페이스하기위한 표준 API는 c로 짜여잇음. POSIX.

- 커널 버전: 커널 인터페이스하기 위해서는 Linux Kernel 헤더파일필요 (definitions and constants). 아래와 같은 예를 직접만들기위해서 단지 헤더파일만 복사해서 직접 수정하면, 커널이 참조하는 헤더파일이기 때문에 conflict 발생함. 존재하는 커널 헤더를 그대로 쓰되 커널만 참조하는 헤더파일을 하드웨어타겟 버전 compatible 을위해 버전을 수정해서 굳이 맞추지 않아도됨.

커널 인터페이스는 "backwards-compatible" 이라고도 함. 타겟디바이스와 같거나 더오래된 커널버전이면 됨.

예) 리눅스 프레임버퍼 드라이버에 그래픽 표시

 

8. Toolchains (툴체인) Type 두가지:

  • Native: 타겟 디바이스와 같은 타입의 시스템에서 run할수 있는 툴체인. 예) 데스크탑, 서버, Arm-based Raspberry Pi 와 Debian: self-hosted native compilers
  • Cross: 타겟 디바이스와 다른타입의 시스템에서 run 할수 있는 툴체인. 예) 개발은 데스크탑에서 한후, 데스크탑과 다른 시스템의 타겟디바이스에서 로드.

- 보통 embedded linux는 cross 툴체인이유는 데스크탑이 환경이 좋아서. (computing power, memory, storage) 그리고

호스트 환경과 타겟 환경을 분리 할수 있어서. 

- 분리하면 좋은점과 cross 컴파일이 그렇게 간단하지 않은 이유: 타겟 툴체인 버전은 초기결정후 stick with 하는 룰에 상응. 오픈소스 라이버리를 사용하는 데스크탑 버전이 업데이트 잦음. 

- 많은 개발자가 투입되는 환경 및 다양한 패캐지가 많은 프로젝트일 경우는 네이티블리 컴파일하는게 좋음.

- Yocto project 가 좋은점: integrated 빌드툴. 다양한 패키지를 타겟보드에 크로스 컴파일 가능.

 

9. 툴체인 빌드시 타겟디바이스 CPU 고려사항

- cpu 아키텍쳐, big-little endian operation, floating point support

- ABI (Application Binary Interface), Extended Application Binary Interface (EABI)

- ABI: function call (함수호출) 에 사용되는 parameter (인자) 표준. 대부분cpu에서 사용

- EABI: ARM cpu 에서 사용. Old Application Binary Interface (OABI) 은 이전버전. 둘 차이는 floating point 인자. OABI는 floating point 넘겨줄때 genearl purpose 레지스터 사용 (interger). EABI는 floating point register사용. EABI를 floating point support가 안되는 ARM cpu에서 사용 불가.

- GNU 에서 -prefix (CPU, vendor: build-root, poky, kernel, OS: gnu, musl) 로 툴체인 구성가능 

 

10. C library 선택

- 종류: glibc (GNU: Posix api, LGPL 2.1) , musl libc ( RAM and storage  작을때), uClibc-ng (microcontoller C library), eglibc

 

11. 툴체인 선택

- pre-build cross toolchain: 쓰기쉬우나, configuration제한적임. SoC. Linaro (system level support). Debian-based 데스크탑 distributions (ARM, MIPS, PowerPC 하드웨어). Binary  SDK (embedded build tools: yocto 프로젝트가 쉬움. 툴체인을 빌드프로세스에서 만들어줌)

- crosstool-NG: 스크립트 실행하여서 메뉴식으로 간편하게 선택하는 방법.

*크로스 리눅스 스크래치 (http://trac.clfs.org)

 

12. 툴체인 빌드 (crosstool-NG)

  • crosstool-NG 설치: 

- Host 리눅스 (Ubuntu 기준) 에서 아래패키지 설치

$ sudo apt-get install automake bison chrpath flex g++ git gperf \
gawk libexpat1-dev libncurses5-dev lib-sdl1.2-dev libtool \
python2.7-dev texinfo

- crosstool-NG git repo 클론하기

$ git clone https://github.com/crosstool-ng/crosstool-ng.git

생략 

$ ./bootstrap
$ ./configure --enable-local
## --enable-local 은 현디렉토리에 설치
$ make
$ make install 
$ ./ct-ng 
  • ./ct-ng menuconfig 후 

- 툴체인 설치후에도 라이브리추가가 필요할경우: Path and misc 옵션에서 CT_INSTALL_DIR-RO 을 disable로 변경.

 

  • 구성완료후 빌드 (30분넘게 걸림)
$ ./ct-ng build

~/x-tools/arm-cortex_a8-linux-gnueabihf 에서 툴체인 확인 가능

 

13. 툴체인 빌드 (QEMU)

  • ARM-versatile PB (ARM926EJ-S 프로세서) 기준.
  • distclean으로 전에 빌드후 남겨진 artifact 지움.
  • 프로세서에 완벽하게 맞지 않을경우 arm-unknown-linux-gnueabi 로 해줘도됨.
$ ./ct-ng distclean 
$ ./ct-ng arm-unknown-linux-gnueabi
$ ./ct-ng build
~/x-tools/arm-unknown-linux-gnueabi 에서 툴체인 설치됨.
  • 설치후 ccp파일 컴파일.
$ arm-cortex_a8-linux-ngueabihf-gcc helloworld.c -o helloworld
$ file helloworld
 *file 로 확인 

 

14. Sysroot, library, header files

  • sysroot: 디렉토리안에 섭디렉토리(라이브러리, 헤더파일, configuration 파일) 
  • sysroot 디렉토리 위치 확인.
$ arm-cortex_a8-linux-ngueabihf-gcc -print-sysroot
  • 섭디렉토리 종류:

- lib: C library shared objects, dynamic linker/loader 위치

- usr/lib: static library (C library) 및 다른 라이브러리

- usr/include: 모든라이브러리의 헤더파일 위치

- usr/bin: 타겟에서 실행되는 유틸리티 binary 프로그램

- usr/share

- sbin: ldconfig 유틸리티, 라이브러리 로딩경로 최적화 유틸

 

  • GNU 툴체인 종류:

- addr2line: 디버깅 툴. 시스템 crash report에 유용

- ar: 아카이브 유틸. static libarary 생성

- as: GNU assembler

- c++filt: demangle C++ and jave

- cpp

- elfedit: elf (executable and linkable format )헤더파일 업데이트

- g++: GNU C++ frontend.

- gcc: GNU C frontend

- gcov: 코드 coverage 툴

- gdb: GNU 디버거

- gprof: 프로그램 프로파일링 툴

- ld: GNU 링커

- nm: 오브젝파일 심볼 표시

- objcopy: 오브젝파일 copy 및 translate

- objdump:  오브젝파일정보 표시

- ranlib: 아카이브 인덱스 이용해서 라이브러리 linking, 호출시 빠르게 해줌

- readelf: ELF 오브젝 정보 표시

- size

- strings

- strip: 타겟에 바이너링 실행파일 옮길때 사용. 오브젝파일에서 심볼 제거후 사이즈 축소

 

15. C 라이브러리 컴포넌트 

  • POSIX API 중요 4개 parts: 

- libc: 메인 C 라이브러리. 예) printf, open, close, read, write 등등

- libm: 수학 math.h 라이브러리. 예) cos, exp and log

- libpthread: POSIX 라이브러리. 예) pthread_

- librt: POSIX 리얼타임 extension 라이브러리. 예) shared memory, asynchronous I/O

 

  • 라이브러리 링크 
$ arm-cortex_a8-linux-gnuabihg-gcc main.c -o main -lm
* -l 옵션: libm 링크

 

  • 링크된 라이브러리 확인 
$ arm-cortex_a8-linux-gnueabihf-readelf -a myprog | grep "Shared library"
$ arm-cortex_a8-linux-gnueabihf-readelf -a myprog | grep "program interpreter"

 

16. 라이브러리 static & dynamic linking

  • gcc 이든 g++이던지 모든 리눅스 어플리케이션은 C 라이브러리 libc 와 링크됨
  • explicit 하게 라이브러리 링크하는 명령어는 -l 옵션으로 함
  •  static linking: "all the library functions your application calls and thier dependencies are pulled from the library archive and bound into your executable" 실행 이미지에 라이브러리까지 포함되어서 빌드됨. 그래서 타겟에 라이브러리까지 끌고 들어감으로 runtime 빠르지만 크기가 커질수 잇음. 라이브러리는 타겟에 없어도됨 
  • dynamic linking: "references to the library files and functions in those files are generated in the code that the actual linking is done dynamically at runtime" 타겟에 위치하는 공용으로 사용될수 있는 라이브리를 runtime 때 linking 해서 참조함. 타겟에 라이브러리가 있어야됨.

17. static library

  •  [sysroot]/usr/lib 위치

18. shared library

  • dynamic linking. 
  • position-independent: run-time linker is free to locate it in memory
$ arm-cortext_a8-linux-gnueabihf-gcc -fPIC -c test1.c
$ arm-cortext_a8-linux-gnueabihf-gcc -fPIC -c test2.c
$ arm-cortext_a8-linux-gnueabihf-gcc -shared -o libtest.so test1.o test2.o

application linking:
$ arm-cortex_a8-linux-gnueabihf-gcc helloworld.c -ltest

위치: /lib, /usr/lib
search path 변경: export LD_LIBRARY_PATH=/opt/lib:/opt/usr/lib
  • soname: <library name>.so.<interfacename> 
    - encodes interface number, 런타임 링커에서 참조됨. 
  • /usr/lib 에 library.so.interfacename 버전 여러개 있는이유:
    - encodes interface number, 런타임 링커에서 참조됨. encodes interface number, 런타임 링커에서 참조됨.

- 설치된 라이브러리 버전마다 symbolic 링크가 달라서 타겟에서 로드되는게 다를수 있음.

예)

libjpeg.a : static 링킹에 사용되는 라이브러리 아카이브 

libjpeg.so -> libjpeg.so.8.0.2 : 다이나믹 linking 에 사용되는 심볼릭링크

libjpeg.so.8 -> libjpeg.so.8.0.2 : 런타임에 로드되는 심볼릭링크

libjpeg.so.8.0.2  : 실제 shared library. 컴파일타임과 런타임둘다사용.

 

첫번째 두번째는 호스트에서 필요하고, 실제 타겟에서는 마지막 두개만 필요함.

 

19. Cross Compiling

Common 빌드시스템:

- pure makefiles: CROSS_COMPILE 에 의해서 관리

- Auto-tools: GNU 빌드 시스템

- CMake

 

makefiles:

- CROSS_COMPILE 변수설정으로 machine 아키텍쳐에 맞게 컴파일.

예) arm_cortex_a8-linux-gnueabi 컴파일시

$ make CROSS_COMPILE=arm-cortex_a8-linux-gnueabihf-
아니면
$ export CROSS_COMPILE=arm-cortex_a8-linux-gnueabihf-
$ make 

Autotools:

- 장점: embedded 리눅스 시스템에 따라 달라지는 컴파일 package (예) 라이브러리 버전, 헤더파일 위치, dependencies)분석이 쉬움.

- configure 명령어로 dependecies 확인가능 및 makefiles 생성 및 feature enable/disable 가능.

- 예) 호스트에 패키지 다운받아서 설치할때 보통 아래와 같이 configure 하고 빌드함.

$ ./configure
$ make
$ sudo make install 

 - configure flag 옵션

CC: C 컴파일러 명령어
예) $ CC=arm-cortex_a8-linux-gnueabihf-gcc ./configure 
CFlAGS: C 컴파일러 flags
LDFLAGS: Linker flags. 
예) 라이브러리 디렉토리 참조 못할때. -L <lib dir> 로 라이브러리 search path에 추가.
LIBS: 링커에 참조되는 라이브러리 리스트
CPPFLAGS: C/C++ preprocessor flags. 
예) 헤더파일 디렉토리 참조 못할때. I<include dir> 로 헤더파일 디렉토리 searh path에 추가.
CPP: C preprocessor에서 사용.

예)
$ CC=arm_cortex_a8-linux-gnuabihf-gcc ./configure \
--host=arm_cortex_a8-linux-gnueanihf --prefix=/usr

Build: package 빌드하는 컴퓨터.
Host: 프로그램 run 하는 컴퓨터. default값은 build와 같음. cross compile시 설정.
Target: generate code 하는 컴퓨터. cross compile시 설정.

prefix: 설치되는 위치. 보통 <sysroot>/usr/local/ 이나 <sysroot>/usr/에 설치됨.

 

* auto 툴체인 아니면 manual cross compile은 어려움. Buildroot 이나 Yocto project 같은 빌드툴 사용.

* cross development 툴체인이여도 결국 code 를 빌드해주는 powerful한 호스트 컴퓨터와 빌드된 code를 run해주는 target과는 clear한 sepration이 있어야함.

* 쉬운방법은 crosstool-NG 사용해서 타겟에 필요한 모든 packages 컴파일하거나 Buildroot 및 Yocto Project와 같은 build system사용해서 source code빌드해서 타겟에 필요한 packages들을 모은 distribution단위에 툴체인 컴파일함.

*graphical interface: dependency 엄첨많음. manual cross compilling 힘듬. ex) QT, GTK, mplayer

*toolchain = startingpoint

*host computer = build the code, target computer = run the code

*toolchain = contains GNU binutils = C compiler & C++ compiler = including GNU debugger, GDB

 

20. Bootloaders 의 모든것 

bootloaders:

- second element of embedded linux system

- start the system up and loads the OS kernel

* boot the target device

* it can be customized to run on new device 

* bootloader = cleaner design of U-boot

 

bootloader 역활:

- 첫번째 initialize system, 두번째 load the kernel into RAM 그리고 executional 한 environment 으로 생성

- 단계별로 loader 가 그다음 loader 를 해당 메모리에 load 해서 실행함.

 

power on후 system 상태: minimal state

- minimal state = DRAM controller not setup, main memory inaccesible, storage inaccesble via NAND flash controllers, MMC controller.

 

minimal state 에 사용가능한 resources:

- single CPU core & on-chip static memory

 

bootloader 와 kernel interface:

- 먼저 hardware configuration information 이 담긴 구조체 pointer 를 넘겨줌

- 두번째로는 kernel command line 의 pointer 를 넘겨줌.

ex)

Loader: ROM code -> SPL -> TPL -> kernel

Memory: SRAM -> DRAM -> DRAM

 

*ROM code loads SPL into SRAM -> SPL loads TPL into DRAM -> TPL loads kernel into DRAM -> kernel is running and bootloaders disappear from memory

 

kernel executing: 

- kernel executing 시작하면 boorloader 필요없음.

 

bootloader maintenance mode:

- boot configuration 용

- memory에 새로운 boot image 로드

- diagnostics 용

- CLInterface 로 사용함.

 

boot sequence:

*reset vector = non-volatile memory = NOR flash = can be mapped directly into he address space = usually top end of flash memory address

- reset vector 에서 bootloader code 로 jump instruction줌.

- 그러면 NOR flash에 위치하는 boorloader code가 실행되고 main memory (= DRAM) 를 초기화 해줌 

- DRAM 이 avaiable 해지면 bootloader 는 kernel 을 flash memory 에서 main memory 로 load 및 control transfer함.

 

boot sequence phase1 (첫번째 단계): ROM code

-ROM code: proprietary code that runs immediately after a reset or power-on

-ROM code: open source irreplacable. 이유는 bootloader의 첫번째 역활의 system 초기화가 SoC 마다 detail이 다 다름.

-ROM code 역활: small chunk of code 정도를 Static Random Access Memory (SRAM) 으로 load 함. DRAM은 memory controller가 있어야하기 때문에 system 초기화때는 memory (DRAM) 초기화 하기 힘듬.

 

*보통 embedded SoC 에 4KB ~ 100 KB SRAM on-chip으로 잇음.

예) TI OMAP, Sitara chips

- SPI 또는 Ethernet, USB or UART를 통해서 ROM code 로드함.

- 로드하는 (from) 위치는 flash memory (NAND), MMC ( eMMC, SD card), 'ML0' file of MMC 등등

 

- ROM code 마지막 실행단계: SRAM으로 bootloader 로드후 SPL code 로 jump

* SPL = secondary program loader = intermediate loader 

 

boot sequence phase 2:  Secondary program loader

- SPL 역활: memory controller 초기화 및 Tertiary Program Loader (TPL) 을 DRAM 으로 load

- can be open source

- proprietary code supplied by the manufactuerer as a binary blob.

 

*device tree: flattened device tree (FDT)

 

*UEFI firmware: Universal Extensible Firmware Interface

- most embedded x86/86_64, ARM designs are based on this firmware

 

 

 

 

 

 

 

 

 

 

 

 

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
TAG
more
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함