2017년 1월 10일 화요일

RIoT Board based on Freescale i.MX 6Solo processor

개인적으로 Freescale chip을 사용해 보고 싶던 차에, RIoT Board를 하나 어렵사리 입수했다. 😈 앞으로 몇 차례의 blog를 통해 RIoT Board를 소개하는 시간을 갖고자 한다. 오늘은 그 첫번째 시간으로 RIoT board의 전반적인 개요 및 source code(bootloader, linux kernel  등)를 build하고, 이를 target board에 올려 보는 과정을 소개해 보고자 한다.



참고: Freescale은 모토로라의 반도체 사업이 분사한 회사로, 얼마전에 NXP(네덜란드 필립스의 부품 사업에서 분사한 회사)로 인수/합병되었으나, 최근 다시 NXP가 Qualcomm에 인수/합병된 상태임.

Freescale i.MX6를 기반으로 하는 SBC(single board computer)는 매우 많은 편인데, 필자가 검토(?)만 했다가 가격이나 구매에 어려움이 있어 포기한 제품을 열거해 보면 다음과 같다.

a) Hummingboard-gate
b) Wandboard
c) OpenRex
d) NXP MCIMX6Q-SL  SABRE Lite Development Kit
e) LeMaker Piano
...


<목차>
1. RIoT Board 소개
2. Source Build 절차 소개
3. 부팅하기(eMMC, NFS booting)
4. BuildRoot for RIoT board
5. Yocto Project for RIoT board


1. RIoT Board 소개
RIoT board를 한마디로 표현해 보기 위해, riotboard.org에 소개된 원문을 그대로 옮겨 보았다(여러가지 미사여구를 사용하여 설명하는 것 보다는 이것이 좀 더 확실해 보이기 때문임).

"The RIoTboard is an open source platform based on an ARM® Cortex®-A9 processor. The RIoTboard is an evaluation platform featuring the powerful i.MX 6Solo, a multimedia application processor with ARM Cortex-A9 core at 1 GHz from NXP Semiconductors. The platform helps evaluate the rich set of peripherals and includes a 10/100/Gb Ethernet port, HDMI v1.4, LVDS, analog headphone/microphone, uSD and SD card interface, USB, serial port, JTAG, camera interface, GPIO boot configuration interface, and expansion port."

그림 1.1 RIoT board


RIoT board 관련 자세한 사항은 아래 site(element14 & embest)를 참조하기 바란다. 아래 web page 내용으로 봐서는 Project 자체는 좀 오래된 느낌이고, 개발 community가 제대로 활성화되지 못한 느낌이다. 하지만 freescale community 및 github가 활성화되어 있는 만큼 사용하는데는 전혀 무리가 없어 보인다.

1) http://www.embest-tech.com/shop/star/riotboard.html
2) https://www.element14.com/community/community/designcenter/single-board-computers/riotboard


그림 1.2 RIoT board block diagram



그림 1.3 RIoT board top view


그림 1.4 i.MX 6Solo block diagram

참고) RIoT board & i.MX 6Solo 관련 보다 구체적인 사항은 추후 별도의 blog로 정리해 보도록 하겠다.


2. Source Build 절차 소개
이번 절에서는 manual 방식으로 toolchain, u-boot, linux kernel source를 일일이 내려 받아, 개별적으로 build하는 절차를 소개해 보고자 한다.

<Toolchain download>
git clone git://github.com/embest-tech/fsl-linaro-toolchain.git
  => freescale linaro toolchain을 내려 받는다.
  => 받은 위치는 ~/IoT/RIoTBoard/embest/toolchain 이 되겠다.

<U-boot & linux kernel source download>
https://www.dropbox.com/sh/7nplywnxtoabfno/AABSkTD9yNvkzPboHVR4DZzma?dl=0
  => 여기서 source code file을 직접 dowload 받는다.
  => 2 ~ 3년 전쯤에 작업이되어서 그런지, git or github으로 되어 있지 않고, 압축 파일 형태로 내려 받도록 되어 있다.

<U-boot build>
$ cd u-boot-imx/
$ vi Makefile
  => 2013.4 version 임

$ export ARM=arm
$ export CROSS_COMPILE=~/IoT/RIoTBoard/embest/toolchain/fsl-linaro-toolchain/bin/arm-fsl-linux-gnueabi-
$ make distclean
   => dist clean 한다(config 설정까지도 clear 시킨다).
$ make mx6solo_RIoTboard_config
  => let's see boards.cfg
$ make
  => 최종적으로 u-boot.imx 결과 파일이 생성됨.
  => u-boot.imx format은 나중에 다시 확인해 보기로 하자.

그림 2.1 u-boot build 모습

<kernel build>
$ export PATH=~/IoT/RIoTBoard/embest/u-boot-imx/tools:$PATH
  => tools/mkimage를 kernel build시 사용(uImage 생성 시)하기 위함임.

$ cd linux-imx/
$ vi Makefile
  => 3.10.17 version임 

$ export ARCH=arm
$ export CROSS_COMPILE=~/IoT/RIoTBoard/embest/toolchain/fsl-linaro-toolchain/bin/arm-fsl-linux-gnueabi-
$ make imx_v7_defconfig
$ make menuconfig
그림 2.2 kernel menuconfig - Freescale i.MX

$ make uImage LOADADDR=0x10008000
  => arch/arm/boot/uImage 생성됨.

그림 2.3 kernel build 모습

$ make imx6solo_RIoTboard.dtb
  => arch/arm/boot/dts/imx6solo_RIoTboard.dtb 파일 생성
  => RIoT board용 dts file도 별도의 blog에서 정리하기로 하자.


3. 부팅하기(eMMC, NFS booting)
최초 보드를 개봉한 상태에서 bootloader(u-boot)의 version을 확인해 보니, 2009년도 version이다. 결과론이지만, bootloader를 교체하지 않은 상태로 NFS booting을 시도해 보았으나, kernel이 구동되지 않는 문제가 발생하였다. 아무래도 bootloader와 kernel이 궁합이 맞지 않는 듯 보인다(uImage를 생성하는 방식에 문제가 있나 ?). 따라서 NFS booting을 시도하기 전에 먼저, RIoT board에서 제공(정확히는 Freescale에서 제공)하는 Mfgtool을 이용하여, eMMC image를 2절에서 build한 내용으로 교체해 보도록 하겠다.

참고) RIoT board에는 eMMC가 기본으로 장착되어 있고,  microSD & SD card를 추가할 수 있다. 물론,  microSD & SD card로 부팅이 가능하도록 되어 있다.

3.1 Mfgtool을 사용하여 eMMC 이미지 교체하기
먼저 아래 site에서 Mfgtool을 내려 받는다. File의 크기가 1.0GB(실제 mfgtool의 크기가 얼마 안되지만, image용 binary가 포함되어 있어 크기가 매우 큼)이므로 download 시간이 매우 올래 걸릴 수 있으니, 주의하기 바란다.

<Ubuntu 16.04 PC>
$ uzip tools_SVN2652.zip
  => 위에서 내려 받은 파일의 압축을 푼다.

$ ls -l
합계 172336
drwxrwxr-x 3 chyi chyi      4096  9월 11  2014 tools_SVN2487
drwxrwxr-x 3 chyi chyi      4096  9월 11  2014 tools_SVN2652

$ cd tools_SVN2652
  => 위의 두개 모두 사용 가능한 듯 보이나, 숫자가 큰 놈을 선택해 본다.
$ cd Mfgtools-Rel-4.1.0_130816_MX6DL_UPDATER
$ vi cfg.ini
  => name 항목의 값을 아래 그림 3.1과 같이 i.MX6SOLO-yocto-RIoTboard-eMMC로 수정한다.
  => 참고로, SD booting을 하고자 한다면, i.MX6SOLO-yocto-RIoTboard-SD를 입력해 주어야 한다.

그림 3.1 Mfgtool cfg.ini  수정

$ cd profiles/MX6DL Linux Update/OS Firmware/files
  => 이 디렉토리 아래에 2절에서 build하여 얻은 u-boot.imx, uImage, imx6solo_RIoTboard.dtb 파일 등을 복사하도록 한다.
  => 그리고, rootfs(fsl-image-fb-riotboard.tar.bz2)는 일단 zip file에 포함되어 있던 것을 그대로 사용해 보자.

$ ls -la
합계 154576
drwxrwxr-x 3 chyi chyi      4096  9월 11  2014 .
drwxrwxr-x 3 chyi chyi      4096  9월 11  2014 ..
drwxrwxr-x 2 chyi chyi      4096  9월 11  2014 android
-rw-rw-r-- 1 chyi chyi 107639993  7월  4  2014 fsl-image-fb-riotboard.tar.bz2
-rw-rw-r-- 1 chyi chyi     44359  1월  9 19:48 imx6solo_RIoTboard.dtb
-rw-rw-r-- 1 chyi chyi  38129513 10월 21  2013 imxdeb.tar.gz
-rw-rw-r-- 1 chyi chyi    159380 10월 21  2013 u-boot-mx6dl-arm2-lpddr2.bin
-rw-rw-r-- 1 chyi chyi    158764 10월 21  2013 u-boot-mx6dl-arm2.bin
-rw-rw-r-- 1 chyi chyi    184732 10월 21  2013 u-boot-mx6dl-nand.bin
-rw-rw-r-- 1 chyi chyi    171340 10월 21  2013 u-boot-mx6dl-sabreauto-nand.bin
-rw-rw-r-- 1 chyi chyi    161992 10월 21  2013 u-boot-mx6dl-sabreauto-spi-nor.bin
-rw-rw-r-- 1 chyi chyi    168388 10월 21  2013 u-boot-mx6dl-sabreauto-weimnor.bin
-rw-rw-r-- 1 chyi chyi    162280 10월 21  2013 u-boot-mx6dl-sabreauto.bin
-rw-rw-r-- 1 chyi chyi    431456 10월 21  2013 u-boot-mx6dl-sabresd.bin
-rw-rw-r-- 1 chyi chyi    160252 10월 21  2013 u-boot-mx6dl.bin
-rw-rw-r-- 1 chyi chyi    171172 10월 21  2013 u-boot-mx6solo-sabreauto-nand.bin
-rw-rw-r-- 1 chyi chyi    161808 10월 21  2013 u-boot-mx6solo-sabreauto-spi-nor.bin
-rw-rw-r-- 1 chyi chyi    168204 10월 21  2013 u-boot-mx6solo-sabreauto-weimnor.bin
-rw-rw-r-- 1 chyi chyi    162088 10월 21  2013 u-boot-mx6solo-sabreauto.bin
-rw-rw-r-- 1 chyi chyi    431272 10월 21  2013 u-boot-mx6solo-sabresd.bin
-rw-rw-r-- 1 chyi chyi    372196  1월  9 19:49 u-boot.imx
-rw-rw-r-- 1 chyi chyi   5461952  1월  9 19:47 uImage
-rw-rw-r-- 1 chyi chyi   3734820 10월 21  2013 uImage-nand
===============================================================

다시 최상위 디렉토리로 이동한 후, tools_SVN2652/ 디렉토리를 zip으로 묶어, Windows PC로 복사하도록 하자.

$ zip -r tools_SVN2652.zip ./tools_SVN2652
  => tools_SVN2652.zip 파일을 Windows PC로 복사한다.


<Windows 10 PC>
MfgTool2.exe(Windows) <-- USB cable --> RIoT board

USB cable을 이용하여 serial download가 가능하도록 하기 위해, Target board의 boot configuration switch(target board의 중앙에 위치)를 그림 3.2에서 그림 3.3과 같이 조정한다(주의: 전원을 끄고 해야 한다).


그림 3.2 boot configuration switch - eMMC booting mode(2, 5번만 OFF되어 있음)



그림 3.3 boot configuration switch 조정(serial download mode)

SVN2652.zip 파일의 압축을 풀고, MfgTool2.exe를 실행한다.

그림 3.4 MfgTool2.exe  실행

이 상태에서 USB cable을 miniUSB port(J11)와 Windows PC간에 연결하고, 5V DC 전원을 인가해 보도록 하자. 정상적으로 연결을 했다면, 그림 3.4의 "No Device Connected" 메시지가 "HID-compliant device"로 바뀌게 될 것이다. 

다음으로 Start 버튼을 선택하면, 그림 3.5와 같이 eMMC로 firmware image를 write하는 작업이 시작되게 될 것이다.


 그림 3.5 eMMC write 작업 시작

어느 정도의 시간이 경과(대략 1분 정도)하면, eMMC writing이 완료하게 되는데, 이때는 Stop -> Exit 버튼을 차례로 선택하여 Mfgtool을 종료해 주면 된다.

그림 3.6 eMMC write 작업 종료(완료)

이제 마지막으로, 5V DC 전원을 끄고, 정상 booting을 위해 target board의 boot configuration switch를 원래(그림 3.2)대로 돌려 놓는다. 마침내, 모든 것이 완료되었다. 전원을 다시 인가해 보도록 하자. 아래 그림 3.7과 같이 kernel이 정상적으로 올려오면 성공이다.

그림 3.7 eMMC 정상 부팅 화면

그림 3.8 RIoT Board 동작 모습(5V DC, Serial cable, HDMI 연결)

3.2 NFS booting하기
자, 그럼 이제 부터는 개발시 보다 편리한 NFS booting을 시도해 보도록 하겠다.
NFS booting과 관련해서는 이미 이전 blog에서 여러 차례 소개한 바가 있으니, 아래 내용(2절)을 참고하기 바라며, 여기서는 필요한 내용만 간략히 정리하고 넘어가도록 하겠다.


<Target board>
U-Boot > setenv ethaddr 12:34:56:ab:cd:ff
  => ethernet port에 대해 MAC 주소를 지정한다.

U-Boot > setenv ipaddr 192.168.1.40
  => target board의 IP 주소를 설정한다.

U-Boot > setenv netmask 255.255.255.0
  => subnet mask를 설정한다.

U-Boot > setenv serverip 192.168.1.100
  => NFS server(Ubuntu Linux)의 IP 주소를 지정한다.

U-Boot > setenv rootpath /home/chyi/IoT/RIoTBoard/embest/rootfs
  => NFS rootfs path를 지정한다. 이 값은 /etc/exports에도 설정되어 있어야 함.

U-Boot > setenv nfsboot 'setenv bootargs root=/dev/nfs rw nfsroot=${serverip}:${rootpath}
ip=${ipaddr}:${serverip}::${netmask}::eth0:off console=ttymxc1,115200 nosmp; tftp 0x12000000 uImage; tftp 0x18000000 imx6solo_RIoTboard.dtb ; bootm 0x12000000 - 0x18000000'
  => console이 ttymxc0가 아니라, ttymxc1임에 주의

U-Boot > saveenv
  => 지금까지 변경한 내용을 저장(여기서는 eMMC  영역)한다.
U-Boot > run nfsboot
  => 이 상태에서 NFS booting을 시도해 보면, 아래 그림과 같이 정상적으로 부팅이 진행됨을 알 수 있다.

그림 3.9 NFS booting 모습 


4. BuildRoot for RIoT board
RIoT board는 이미 BuildRoot에 적용되어 있다. 따라서 최신 buildroot source code를 내려 받은 후, build를 시도해 보도록 하자.

$ git clone git://git.buildroot.net/buildroot
  => 최신 buildroot source를 download한다.

$ make riotboard_defconfig
  => riotboard defconfig를 적용한다.

$ make menuconfig





그림 4.1 buildroot menuconfig

$ make
  => build를 진행한다.

<Output>
그림 4.2 buildroot build 결과물

자, 그럼 이 상태에서 NFS booting을 시도해 보도록 하자.

<Ubuntu 16.04 Host>
$ cd output/images
$ mkdir rootfs
$ sudo tar xvf ./rootfs.tar -C ./rootfs
$ vi /etc/exports
...
/home/chyi/IoT/RIoTBoard/buildroot/output/images/rootfs 192.168.1.*(rw,no_root_squash,sync,no_subtree_check)
~
sudo /etc/init.d/nfs-kernel-server restart

$ cp ./uImage /tftpboot
$ cp ./imx6dl-riotboard.dtb /tftpboot/imx6solo_RIoTboard.dtb

<Target board>
U-Boot > setenv rootpath /home/chyi/IoT/RIoTBoard/buildroot/output/images/rootfs
U-Boot > run nfsboot


그림 4.3 buildroot NFS booting 모습



5. Yocto Project for RIoT board
이번 절에서는 freescale's community yocto bsp web site 및 참고 문헌 [6]을 토대로,  RIoT board를 위한 yocto build system을 소개해 보고자 한다.

$ cd ~/IoT/RIoTBoard
$ mkdir yocto; cd yocto

$ mkdir bin; cd bin/
$ curl http://commondatastorage.googleapis.com/git-repo-downloads/repo > ./repo
  => freescale yocto project에서는 (특이하게도) android에서 source code를 내려 받기 위해 만든 repo를 활용하고 있다.
  => repo는 python으로 작성되어 있다.
$ chmod 755 repo
$ sudo cp repo /usr/local/bin/
$ cd ..

$ mkdir fsl-community-bsp
$ cd fsl-community-bsp/
$ repo init -u https://github.com/Freescale/fsl-community-bsp-platform -b krogoth
  => freescale의 경우는 poky version 중, 현재 krogoth(2.1 version)까지만 지원(2.2 morty는 아직 지원 안함)하고 있다.
$ repo sync
  => 앞서 dowload한 repo를 통해 yocto project code를 내려 받는다.
  => CPU의 성능을 감안하여 "repo sync -j8" 와 같이 option을 줄 수도 있다.

~/IoT/RIoTBoard/yocto/fsl-community-bsp$ ls -la
합계 52
drwxrwxr-x  6 chyi chyi  4096 12월 30 19:41 .
drwxrwxr-x  4 chyi chyi  4096 12월 30 19:10 ..
drwxrwxr-x  7 chyi chyi  4096 12월 30 19:12 .repo
-r--r--r--  1 chyi chyi  2104 12월 30 19:12 README
-r-xr-xr-x  1 chyi chyi  7027 12월 30 19:12 setup-environment
drwxrwxr-x 10 chyi chyi  4096  1월  3 14:26 sources

~/IoT/RIoTBoard/yocto/fsl-community-bsp/sources$ ls -la
  => sources 디렉토리 내에는 그 동안 많이 보아왔던 poky & meta-fsl* 관련 내용이 보인다.
합계 40
drwxrwxr-x 10 chyi chyi 4096  1월  3 14:26 .
drwxrwxr-x  6 chyi chyi 4096 12월 30 19:41 ..
drwxrwxr-x  7 chyi chyi 4096 12월 30 19:12 Documentation
drwxrwxr-x  4 chyi chyi 4096 12월 30 19:12 base
drwxrwxr-x 20 chyi chyi 4096 12월 30 19:12 meta-fsl-arm
drwxrwxr-x  7 chyi chyi 4096 12월 30 19:12 meta-fsl-arm-extra
drwxrwxr-x  6 chyi chyi 4096 12월 30 19:12 meta-fsl-demos
drwxrwxr-x 18 chyi chyi 4096 12월 30 19:12 meta-openembedded
drwxrwxr-x 10 chyi chyi 4096  1월  3 14:26 meta-qt5
drwxrwxr-x 12 chyi chyi 4096 12월 30 19:12 poky
======================================================

$ ls -l */conf/machine
  => 여러 결과 중, riotboard 관련 machine name을 찾아 보도록 한다.
  => machine name을 찾는 이유는, freescale의 경우는 build 시 MACHINE name을 지정하고 있기 때문임(freescale 만의 독특한 방법).
..
-rw-rw-r-- 1 chyi chyi  416 12월 30 19:12 imx6dl-riotboard.conf
...

$ mkdir -p imx6dl-riotboard
$ MACHINE=imx6dl-riotboard source setup-environment imx6dl-riotboard
  => setup-environment(shell script)는 freescale에서 만든 것으로 oe-init-build-env에 대한 wrapper script에 불과함.
  => freescale의 경우는 특이하게도 EULA license를 확인하는 과정이 추가되어 있음.

Do you accept the EULA you just read? (y/n)  y
EULA has been accepted.

Welcome to Freescale Community BSP

The Yocto Project has extensive documentation about OE including a
reference manual which can be found at:
    http://yoctoproject.org/documentation

For more information about OpenEmbedded see their website:
    http://www.openembedded.org/

You can now run 'bitbake <target>'

Common targets are:
    core-image-minimal
    meta-toolchain
    meta-toolchain-sdk
    adt-installer
    meta-ide-support

Your build environment has been configured with:

    MACHINE=imx6dl-riotboard
    SDKMACHINE=i686
    DISTRO=poky
    EULA=
==============================================================

$ bitbake core-image-minimal
  => core image build를 시작한다. 역시 오래 걸림.

<Output>
5.1 RIoT board를 위한 yocto build 결과물

자, 다음 단계는 앞서 build한 결과물이 정상 동작되는지 NFS booting을 통해 확인해 볼 차례이다.

<Ubuntu 16.04 Host>
$ cd tmp/deploy/images/imx6dl-riotboard
$ mkdir rootfs
sudo mount -t ext4 -o loop ./core-image-minimal-imx6dl-riotboard.ext4 ./rootfs
  => ext4용 image를 rootfs 디렉토리로 mount한다. 이 디렉토리를 NFS rootfs 디렉토리로 사용할 예정임.

cp zImage /tftpboot/
cp zImage-imx6dl-riotboard.dtb /tftpboot/imx6solo_RIoTboard.dtb
  => yocto project에서는 uImage 대신 zImage를 기본으로 생성하고 있음.

<Target board>
U-Boot > setenv rootpath /home/chyi/IoT/RIoTBoard/yocto/fsl-community-bsp/imx6dl-riotboard/tmp/deploy/images/imx6dl-riotboard/rootfs
  => /etc/exports 파일도 수정해 주어야 한다.


U-Boot > setenv nfsboot 'setenv bootargs root=/dev/nfs rw nfsroot=${serverip}:${rootpath} ip=${ipaddr}:${serverip}::${netmask}::eth0:off console=ttymxc1,115200 nosmp; tftp 0x12000000 zImage; tftp 0x18000000 imx6solo_RIoTboard.dtb ; bootz 0x12000000 - 0x18000000'
  => zImage를 사용하는 관계로 관련 부분을 수정해 준다.

U-Boot > run nfsboot

5.2 RIoT board - Yocto booting 결과


RIoT board Yocto project 사용법과 관련해서는 아래 site에 보다 자세하게 설명되어 있으니, 참고해 보는 것도 좋을 듯 싶다.


============
이상으로 RIoT board를 간략히 소개하고, source code build & 구동 방법을 정리해 보았다.

References
1. RIoTboard-User-Manual-V2.1.pdf, riotboard.org
2. RIoTboard-Schematics-v.1.0.pdf, riotboard.org
3. Wiki-Intermediate-Flash a BSP image using MfgTool.pdf, riotboard.org
4. IMX-6Solo-Processor-Datasheet.pdf, Freescale Semiconductor, Inc.
5. IMX-6Solo-Processor-Reference-Manual.pdf, Freescale Semiconductor, Inc.
6. Embedded Linux Projects Using Yocto Project Cookbook, Alex Gonzalez, PACKT publishing.

Slowboot

2016년 12월 30일 금요일

SAMA5D3 Xplained board에서 Qt application 돌려 보기

이번 post에서는 Atmel SAMA5D3 Xplained board에 LCD를 연결하고, 그 위에서 간단한 Qt application을 돌려 보는 과정을 소개해보고자 한다.

SAMA5D3 Xplained board + Yocto Project + LCD + Qt application

Qt: a cross-platform application framework written in C++

<목차>
1. BuildRoot 환경에서 SD card 용 부팅 이미지 만들기
   -> 본 blog의 주제와는 무관한 내용임.
2. LCD 준비하기 
3. Yocto project로 Qt를 포함한 부팅 이미지 만들기
4. Host PC에 Qt5 설치하기
5. Target Board에서 Qt application 돌려 보기
6. Qt application을 Yocto Project에 추가하기


1. BuildRoot 환경에서 SD card 용 부팅 이미지 만들기
이번 절에서는 (본 blog의 주제와는 무관하지만) 그동안 주로 NAND & NFS booting만을 소개하였으므로,  SD card를 이용한 booting 방법(MMC booting)을 소개하고자 한다.

<Ubuntu 16.4 Host PC>
$ cd buildroot
make atmel_sama5d3_xplained_mmc_dev_defconfig
  => SD/MMC booting을 위한 config 파일 적용 

$ make menuconfig
  => 필요한 설정이 있다면 적절히 변경한다.

$ make
  => 전체 build를 진행한다.

그림 1.1 make의 마지막 부분 - post-image.sh 실행 화면

(build의 마지막 단계에서 사용하는) post-image.sh 파일은 최종 sd card용 image를 만들어 내기 위해 genimage라는 tool을 사용한다. 아래 내용은 각각 post-image.sh 파일(그림 1.2)과 genimage가 사용하는 genimage.cfg의 내용(그림 1.3)을 capture한 것이다.

그림 1.2 post-image.sh 파일

그림 1.3 genimage.cfg 파일

참고) genimage.cfg의 문법을 이해하기 위해서는 아래 site 내용을 참조해 볼 필요가 있다.

<build 결과물>
그림 1.4 Build 결과 파일(sd card booting 용 파일)

$ cd output/images
$ bzip2 ./sdcard.img
  => bzip2 압축을 진행한다(뒤에서 소개할 Rawrite32.exe에서 bz2 file 형식을 필요로하기 때문임)      
         -rw-r--r-- 1 chyi chyi  41073563 12월 21 20:15 sdcard.img.bz2

(*) TBD - sdcard.img format(sd card 내 partition 정보) 추가 설명 필요함.

윈도 PC로 위의 sdcard.img.bz2를 복사한 후, 아래 내용을 수행한다.

<Windows 10 PC>
a) 아래 site에서 Rawrite32.exe 파일을 download 받아 설치한다.

b) SD card(최소 1GB 정도는 되어야 함)를 PC에 꽂는다.
c) Rawrite32.exe를 이용하여 sdcard.img.bz2를 SD card에 설치한다.

그림 1.5 Rawrite32.exe 실행 화면 - sdcard에 sdcard.img.bz2 설치 

그림 1.6 SD card에 복사된 내용


SD card를 target board에 꽂은 후, 부팅을 시도한다.

<Target board - SAMA5D3 Xplained>

그림 1.7 SD card를 장착한 target board

참고) SAMA5D3 Xplained board는 NAND flash 부팅 보다 SD/MMC card 부팅을 우선시 한다. 다시 말해, SD card가 꽂혀 있을 경우는 SD card로 먼저 부팅을 시도하게 되고, SD card에 booting image가 없다면 NAND booting 으로 이어지게 된다.

그림 1.8 SD card 부팅을 위한 u-boot env configuration

여기서 잠시, u-boot 환경 설정 값 중, bootcmd로 설정된 내용을 살펴 보기로 하자.

if test ! -n ${dtb_name}; then setenv dtb_name at91-${board_name}.dtb;
  => dtb_name이 정의되어 있지 않을 경우, at91-${board_name}.dtb을 dtb_name으로 사용.
  => 이 경우는 board_name이 sama5d3_xplained로 되어 있으므로, dtb_name으로는 at91-sama5d3_xplained.dtb가 사용될 것임.
  => at91-sama5d3_xplained_pda4.dtb를 사용하기 위해 board_name을 바꾸도록 하자.

fatload mmc 0:1 0x21000000 ${dtb_name};
  => fatload는 SD card 상의 FAT file system으로 format된 파티션으로 부터 file을 읽어드리는 명령임.
  => 사용법: fatload <interface> [<dev[:part]> [<addr> [<filename> [bytes [pos]]]]]
  => 0:1은 first device의 first partition을 의미함(partition은 1부터 시작함)
  => 정리하자면, 이 명령은 mmc device의 첫번째 partition에 있는 at91-sama5d3_xplained.dtb 파일을 RAM의 0x21000000 번지로 loading함을 의미함.
  => RAM의 0x21000000 번지는 나중에 kernel image가 loading되어 decompressing될 경우에 겹쳐서는 안되는 위치로 잡아 주어야 함.

fatload mmc 0:1 0x22000000 zImage;
  => 앞선 설명에 의해, mmc device의 첫번째 partition에 있는 zImage file을 RAM의 0x22000000 번지로 loading하는 명령임.

bootz 0x22000000 - 0x21000000
   => bootz 명령 사용법: bootz [address of kernel] [address of ramdisk: filesize] paddress of dtb]
   => RAM에 올려져 있는 kernel(zImage), ramdisk rootfs, dtb 등을 이용하여 실제 booting을 시도하는 명령임.
   => bootz 대신에 bootm 명령을 사용하려면, uImage를 이용해야 함.
   => ramdisk rootfs는 사용하지 않으므로, 그 자리에 '-' 를 대신 입력해 준다. 안그러면, dtb를 ramdisk로 오해할 수 있으니 ...

여기서 잠깐 ! 
down votaccepted
What is the difference between them?
Image: the generic Linux kernel binary image file.
zImage: a compressed version of the Linux kernel image that is self-extracting.
uImage: an image file that has a U-Boot wrapper (installed by the mkimage utility) that includes the OS type and loader information.


그림 1.9 target board booting 모습 - picocom -b 115200 /dev/ttyUSB0


그럼, 이제부터 본격적으로 본 blog의 주제로 넘어가 보기로 하자.

2. LCD 준비하기
먼저 LCD 준비와 관련해서는 이전 blog의 내용을 참조하기 바란다.

또한, Atmel KMS/DRM LCD driver의 구조/동작 원리 관련해서는 아래 site 내용이 도움이 될 것으로 보인다.


3. Yocto Project로 Qt를 포함한 부팅 이미지 만들기 
이번 절에서는 Yocto Project를 기준으로 Qt용 demo image를 만드는 절차를 소개해 보도록 하겠다.
먼저 Atmel SAMA5D3 Xplained board용 yocto project build 절차는 이전 blog에 소개된 5절의 내용을 기본적으로 사용하도록 하겠다.

따라서, 여기서는 Qt와 관련된 부분만을 별도로 추가해 보기로 하자.

$  cd yocto
$ git clone git://github.com/meta-qt5/meta-qt5.git -b krogoth
  => meta-qt5 source를 내려 받는다.

$ cd poky/build-atmel/conf
$ vi bblayers.conf
  => meta-qt5를 추가한다.


그림 3.1 conf/bblayers.conf 파일 수정

$ cd ..
source oe-init-build-env build-atmel
  => build-atmel을 위한 환경 설정을 한다.

bitbake atmel-qt5-demo-image
  => qt5 demo image를 만든다.
  => 실행 결과, Ubuntu 16.04에서는 아래와 같이 qtbase 관련 에러가  발생한다.
  


그림 3.2 qtbase 관련 에러 발생

그림 3.2의 내용으로 봐서는, "0001-Fix-building-without-OpenGL-support.patch" 패치 파일에 문제가 있는 듯 보이는데, 일단 (임시적으로) 아래 그림 3.3과 같이 해당 패치가 아예 적용되지 않도록 recipe를 수정해 보기로 한다.

그림 3.3 meta-atmel/qt5-layer/recipes-qt/qt5/qtbase_%.bbappend 파일 수정

수정 후, 다시 build를 계속 진행해 보니, 정상적으로 build가 마무리(tmp/deploy/images/sama5d3-xplained/*) 되었고, NFS booting(자세한 사항은 이전 blog 6절 참조)을 해 보니 아래와 같이 Qt 화면(Atmel demo app)이 정상적으로 출력된다.

그림 3.4 Qt demo application main 화면

다음으로 Qt application을 build하는데 필요한 cross-compiler toolchain을 준비해 보도록 하자.

$ bitbake -c populate_sdk atmel-qt5-demo-image
  => SDK를 만드는 작업을 한다(시간이 오래 걸림).
  => 이 내용과 관련해서는 이전 blog 1절에서 이미 소개한 바 있음.

$ cd tmp/deploy/sdk
./poky-atmel-glibc-x86_64-atmel-qt5-demo-image-cortexa5hf-vfp-toolchain-2.1.2.sh
  => toolchain을 설치한다.


그림 3.5 Qt를 위한 yocto toolchain 설치 화면

$ .  /opt/poky-atmel/2.1.2/environment-setup-cortexa5hf-vfp-poky-linux-gnueabi
  => 설치된 toolchain을 적용한다(실제 cross-compile 작업을 수행하기 직전에 실행해 주어야 함)
  => Qt의 경우는 Qt Creator 설정 메뉴에서 관련 내용을 지정해 줄 것(5절에서 설명할 것임)이므로, 실제로 불필요한 내용으로 볼 수도 있음.


4. Host PC에 Qt5 설치하기
이번 절에서는 Ubuntu 16.04 Linux PC에 Qt5를 설치하는 과정을 소개하고자 한다. 먼저, 아래 site의 내용을 참조하여 linux(64bit)용 qt run file을 download 받는다.
|
V
$ wget http://download.qt-project.org/official_releases/qt/5.6/5.6.1/qt-opensource-linux-x64-5.6.1.run


이후 모드(실행 모드) 전환 후, 아래와 같이 실행하도록 한다.

$ chmod +x qt-opensource-linux-x64-5.6.1.run

$ ./qt-opensource-linux-x64-5.6.1.run
  => 설치를 시작한다(몇번의 click으로 설치 가능함).


그림 4.1 Qt5 설치 화면

설치가 완료된 후, Qt Creator를 실행해 보면 다음과 같다.

그림 4.2 Qt Creator 실행 화면

(*) 참고: 최신 버젼 Qt5.7.1을 설치했으나, qt Creater의 상단 메뉴 내용이 출력되지 않아, 5.6.2로 다시 설치함. 5.6.2을 선택한 이유는 앞서 yocto에서 사용한 Qt version이 5.6.2이기 때문임.


5. Target Board에서 Qt application 돌려 보기
이번 절에서는 Qt Creator와 Yocto cross toolchain을 이용하여, target board용 application을 생성하는 절차를 소개하고자 한다.

Qt Creator의 환경 설정에 들어가기에 앞서, 지난 4절에서 설치해 둔 yocto toolchain을 이용하여 console 상에서 간단한 Qt application을 만드는 과정을 설명하는 것이 순서일 듯 싶다.

먼저 아래와 같이 hello world program을 작성해 두었다고 가정하자.

그림 5.1 Qt Creator로 작성한 main.cpp

$ cd helloworld1/
  => 여기에 main.cpp가 있음.

$ source /opt/poky-atmel/2.1.2/environment-setup-cortexa5hf-vfp-poky-linux-gnueabi
  => cross-compile을 하기 위해, yocto toolchain의 환경을 설정한다.
  => 파일 내용을 보면 알 수 있듯이, 각종 cross compile을 위한 export 명령이 정의되어 있음.

$ qmake -project
  => .pro file을 생성한다.

$ qmake
  => Makefile을 생성한다.

$ make
  => build를 진행한다. 아래와 같은 결과가 출력된다.

$ ls -la
-rw-rw-r--  1 chyi chyi  40529  1월  5 13:05 Makefile
-rwxrwxr-x  1 chyi chyi 268356  1월  5 13:05 helloworld1
-rw-rw-r--  1 chyi chyi    286  1월  5 13:05 helloworld1.pro
-rw-rw-r--  1 chyi chyi    212  1월  5 12:59 main.cpp
-rw-rw-r--  1 chyi chyi 312796  1월  5 13:05 main.o

$ scp ./helloworld1 root@192.168.1.50:/usr/bin
  => helloworld1 program을 target board(192.168.1.50)로 복사한다.

이후 target board에서 helloworld1를 실행해 보니, 정상 동작한다.

<target board에서 실행>
$ /usr/bin/helloworld1
...

그렇다면, console 대신에, Qt Creator 상에서 직접 target board용 image를 build하고, target board 상에서 동작시키기 위해서는 어떻게 하면 될까 ?
우선 제일 먼저 해야할 작업은, 앞서 준비해 둔 yocto cross toolchain 환경 설정과 관련된 내용을 Qt5/Tools/QtCreator/bin/qtcreator.sh 파일의 맨 앞에 추가해 주는 것이다. 이는 QtCreator를 실행하는 환경 자체를 cross-compile 환경으로 바꾸기 위한 조치로 보면 된다.

source /opt/poky-atmel/2.1.2/environment-setup-cortexa5hf-vfp-poky-linux-gnueabi

그림 5.2 Tools/QtCreator/bin/qtcreator.sh 수정

주의) 반드시 #! /bin/sh 앞 라인에 위의 내용을 추가해 주기 바란다.

그런 다음, 아래와 같이 Qt Creator를 다시 구동시켜 주자.

$ cd ~/Qt5/Tools/QtCreator/
$ bin/qtcreator.sh &

다음으로 (QtCreator 상단의) Tools -> Options 메뉴를 선택한 후, 몇가지 환경 값을 지정해 주어야 하는데, 그 내용을 하나씩 살펴 보도록 하자.
먼저 좌측 Devices 선택 후, 우측의 Add 버튼을 눌러, 새로운 target device(Generic Linux Device 선택해야 함)를 생성해 주도록 하자. 미리 말하지만 이 설정을 추가하는 이유는 target board용으로 build한 application을 scp 등으로 target board에 자동으로 올려 테스트를 하기 위해서이다.


그림 5.3 Target board 디바이스 생성 화면 

그 다음, 좌측의 Build & Run을 선택한 상태에서, 다시 상단의 Compilers tab을 선택 한 후, Add 버튼(mouse로 Manual 선택 상태에서)을 눌러 yocto cross-compiler의 path를 아랫 값으로 지정해 주도록 한다. 눈치챘겠지만, Qt application을 build할 때 g++이 아니라, arm-poky-linux-gnueabi-g++를 사용하겠다는 것으로 보면 된다.

/opt/poky-atmel/2.1.2/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-g++

 그림 5.4 Cross compiler 지정 화면 

같은 방식으로, 이번에는 Debuggers tab을 선택하여, arm용 cross gdb path를 아래와 같이 입력해 준다.

/opt/poky-atmel/2.1.2/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-gdb

 그림 5.5 cross gdb 패스 입력 화면

다음으로 상단의 Kits tab을 선택하여 sysroot path(target board용 rootfs)를 지정해 준다. 참고로 sysroot 디렉토리 내에는 Qt5를 위한 각종 library(usr/lib/libQt5*)가 존재하는데, 이는 cross-compile 과정(link)에서 사용되게 된다. 따라서 이 path를 제대로 지정하지 않을 경우, 각종 link error에 봉착하게 될 것이다.

/opt/poky-atmel/2.1.2/sysroots/cortexa5hf-vfp-poky-linux-gnueabi

 그림 5.6 sysroot path 지정 화면

주의) 위의 그림에서 한가지 주의할 점은 Qt mkspec 란에 반드시 linux-oe-g++를 입력해 주어야 한다는 점이다. 이를 누락할 경우, cross-compile시 Qt 관련 error가 발생하게 된다.

마지막으로, Qt Versions tab을 선택한 후 qmake path를 아래와 같이 입력해 준다.

/opt/poky-atmel/2.1.2/sysroots/x86_64-pokysdk-linux/usr/bin/qt5

그림 5.7 qmake path 지정 화면 

이제 Qt Creator 상에서의 cross-compile을 하기 위한 모든 준비가 마무리 되었다. 앞서 만들어 둔, hello world program을 약간 수정(버튼을 하나 추가함) 후, Qt Creator 상에서 build해 보고, build 결과로 생성된 binary file을 target board에 올려 실행해 보도록 하자.

먼저 아래 그림과 같이 helloworld1.pro 파일에 아래 내용을 추가하도록 한다. 이를 추가하는 이유는 target board의 어느 위치로 binary file을 전송(복사)할 지를 결정하기 위해서이다.

TARGET = helloworld1
     target.files = hellworld1
     target.path = /usr/bin
INSTALLS += target

그림 5.8 helloworld1.pro file 수정 

다음으로, helloworld1을  Rebuild해 준다(우측 helloworld1 source tree 위에서 마우스 우 Click -> Rebuild 메뉴 선택).

재 build에 성공했으면, 좌측의 Projects 버튼을 선택한 후, 다시 상단의 Run 메뉴(sama5d3 밑에 있음)를 선택하여 그 아래에 나오는 Run Environment 부분을 아래와 같이 수정해 주도록 한다. 참고로, 현재 build된 yocto qt image는 framebuffer를 기반으로 동작하도록 되어 있다(즉, X11 방식이 아님). 따라서, Qt application이 이 환경에서 제대로 동작하기 위해서는 framebuffer 관련 설정이 추가되어야 한다.

Run Environment
  -> Add 버튼 선택
      -> Variable: QT_QPA_PLATFORM 입력
      -> Value: linuxfb 입력

그림 5.9 Projects -> Run 설정 변경

아래 그림 5.10은 앞서 helloworld1.pro에 추가한 target 관련 내용이 Run Settings  화면에 반영된 모습이다.

그림 5.10 Projects -> Run의 내용(Local File Path 및 Remote(=target board) Directory 모습)

자, 이제 마침내 helloworld1 binary를 target 보드에서 돌려볼 차례가 되었다. Qt Creator의 좌측 Run 버튼을 눌러, 과연 어떤 일이 벌어지는지 살펴 보도록 하자.

결과는 예상대로, helloworld1 program이 target board의 LCD 화면에 출력되고 있다. Console 상에서도 ps 명령을 통해 확인(그림 5.12)해 보니, /usr/bin/helloworld1이 구동되고 있음을 알 수 있다.

그림 5.11 helloworld1 app을 target board에서 실행한 화면

그림 5.12 console 상에서 ps 명령 실행 결과

참고) 현재 framebuffer에 출력된 내용을 깨끗이 지우고자 할 때는 아래 명령을 사용하면 된다.
# cat /dev/zero > /dev/fb0


6. Qt application을 Yocto Project에 추가하기
이번 절에서는 5절에서 만든 Qt application을 Yocto project에 추가하는 방법을 소개해 보고자 한다.

$ cd yocto/meta-atmel/recipes-test
  => 이 디렉토리 아래에 qt application을 추가하기로 함(반드시 이 디렉토리일 필요는 없음).

$ mkdir qthello
$  vi qthello_1.0.bb
  => qthello package에 대한 recipe 파일을 만든다.

그림 6.1 qthello_1.0.bb 파일

$ mkdir qthello-1.0; cd qthello-1.0
  => source code가 위치할 디렉토리를 만들고, 그곳으로 이동한다.

$ vi qthello.pro
  => qmake project file을 하나 만든다.


그림 6.2 qthello.pro 파일

$ vi qthello.cpp
  => qthello.cpp file을 하나 만든다.


그림 6.3 qthello.cpp 파일

$ cd ~/poky/build-atmel
bitbake qthello
  => 앞서 작성한 recipe 및 source code에 하자가 없는지, qthello package만 build해 본다.

$ vi conf/local.conf
  => qthello package를 rootfs image에 포함시키기 위해 local.conf를 수정한다.

그림 6.4 conf/local.conf에 qthello 패키지 추가

bitbake atmel-qt5-demo-image
  => 전체 image를 다시 build하도록 한다.

이제 NFS booting을 시도한 후, qthello application을 수동으로 돌려 보도록 하자.

<Target board>
export QT_QPA_PLATFORM=linuxfb
  => framebuffer로 직접 display할 내용을 write하고자 할 때 사용함(linuxfb plugin 지정)

export QT_QPA_GENERIC_PLUGINS=evdevmouse,evdevtouch:/dev/input/touchscreen0,evdevkeyboard:/dev/input/event0
  => input 장치(touch, keyboard, mouse)에 대한 plugin 설정

# /usr/bin/qthello

그림 6.5 qthello 실행 결과(글씨가 안보임)

참고) 위의 방법 대신, "/usr/bin/qthello -platform linuxfb" 형태로 실행해 주어도 된다.

이상으로 SAMA5D3 Xplained board에 yocto image를 올리고, 여기에 간단한 Qt application을 추가해 보는 과정을 간략히 소개해 보았다.


References
1. https://github.com/vivien/genimage
2. http://events.linuxfoundation.org/sites/events/files/slides/brezillon-drm-kms.pdf, free-electrons
3. Application Development with Qt Creator, Ray Rischpater, PACKT publishing.
4. Embedded Linux Projects Using Yocto Project Cookbook, Alex Gonzalez, PACKT publishing.
5. https://github.com/gumstix/yocto-manifest/wiki/Cross-Compile-with-QtCreator
6. http://www.jumpnowtek.com/rpi/Qt-Creator-Setup-for-RPi-cross-development.html

Slowboot