2017년 2월 12일 일요일

How to build Android sources for UDOO Neo board with Docker

이번 post에서는 Docker 환경에서 Android 6.0.1(Marshmallow) source code를 build해 보고, 이를 UDOO Neo 보드 상에서 돌려 보는 과정을 소개해 보고자 한다. 오랫만에 android source를 build해 보는 것 같다 ;)

UDOO Neo board + Docker + Android Marshmallow

<목차>
1. UDOO Neo 보드 소개
2. Android Source Download & Build 하기
3. Docker 환경에서 Android Source Build 하기
4. Android UDOO Neo board 파일 분석 및 몇가지 Tips
5. UDOO Neo 보드 부팅하기


1. UDOO Neo 보드 소개
UDOO Neo 보드! 아주 독특하고 재밌는 concept의 보드다. 일반적인 SBC(Single Board Computer)와 달리 Application processor(Cortex-A9) + Arduino processor(Cortex-M4) 형태로 구성되어 있으며, Wi-Fi/Bluetooth 모듈과 3가지 센서(3-axis Accelerometer, Gyroscope, Magnetometer)가 장착되어 있는 것이 특징이다. 따라서 고성능(android 탑재 가능)을 지향하며, arduino compatible한 IoT 장비 개발에 적합한 보드로 보인다. 앞으로 Android Things project가 보다 구체화될 경우, android things용으로 활용해 보는 것도 괜찮을 것 같다.

그림 1.1 UDOO Neo 보드 개요

UDOO Neo 보드의 주요 특징을 원문 그대로 정리해 보면 다음과 같다.

  • Freescale™ i.MX 6SoloX applications processor with an embedded ARM Cortex-A9 core and a Cortex-M4 Core
  • Integrated 2d/3d graphics controller
  • RAM 1GB
  • Micro HDMI interface - LVDS interface + touch (I2C signals)
  • Analog camera connection supporting NTSC and PAL - 8-bit parallel camera interface
  • MicroSD card slot onboard - 8-bit SDIO interface
  • HDMI audio transmitter - S/PIDF & I2S
  • 1x USB 2.0 Type A ports - 1x USB OTG (micro-AB connector)
  • Fast ethernet RJ45 – 10/100Mbps - Wi-Fi 802.11 b/g/n,Direct Mode SmartConfig and Bluetooth 4.0 Low Energy
  • 3x UART ports - 2x CAN Bus interfaces
  • 8x PWM signals - 3x I2C interface - 1x SPI interface - 6x multiplexable signals
  • Power Supply: 5 V DC Micro USB, 6-15 V DC Power Jack, RTC Battery Connector
  • Green Power Status LED - User Configurable LEDs (Red and Orange)
  • Integrated Sensors: 3-Axis Accelerometer - 3-Axis Magnetometer - 3-Axis Digital Gyroscope - 1x Sensor Snap-In I2C connector
  • Dimensions: 89mm x59mm (3.50″ x 2.32″)
  • Arduino-Compatible through the standard Arduino Pins layout and compatible with Arduino shields
  • 32 extended GPIOs (A9 dedicated) - 22 arduino GPIOs (M4 dedicated)
  • 6 available Pins
  • Android Lollipop & Linux UDOObuntu2 (14.04 LTS)


  • 그림 1.2 UDOO Neo 보드 구조(Top/bottom view)

    UDOO Neo 보드에 대한 보다 구체적인 사항(i.MX6 SoloX datasheet, 회로도, device tree 등)과 관련해서는 추후 별도의 blog를 통해 좀 더 분석해 보도록 하겠다.


    2. Android Source Download & Build 하기
    이번 절에서는 UDOO Neo  보드용 android source code(marshmallow)를 내려 받아 build하는 절차를 소개해 보고자 한다. 이는 앞으로 3절에서 설명하게 될 docker 환경이 필요한 이유를 보여주기 위해 필요한 사전 절차로 보면 될 듯하다.

    <Java JDK 설치>
    UDOO Neo용  android source code를 build하기 위해서는 openjdk 7이 필요하다.
    $ sudo add-apt-repository ppa:openjdk-r/ppa
    $ sudo apt-get update
    $ sudo apt-get install openjdk-7-jdk

    기존에 openjdk 8이 설치되어 있던 관계로, 특별히 아래와 같은 조치를 취해주어야 했다.
    $ sudo update-alternatives --config java
      => /etc/alternatives/java의 symbol link를 open jdk7의 그것으로 바꿔주게 됨.
    ---------------------------------------------------------------------------------------------------------------------------
    대체 항목 java에 대해 (/usr/bin/java 제공) 2개 선택이 있습니다.

      선택       경로                                                                      우선순위     상태
    ---------------------------------------------------------------------------------------------------
    * 0            /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java   1081      자동 모드
      1            /usr/lib/jvm/java-7-openjdk-amd64/jre/bin/java   1071      수동 모드
      2            /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java   1081      수동 모드

    Press <enter> to keep the current choice[*], or type selection number: 1
    update-alternatives: using /usr/lib/jvm/java-7-openjdk-amd64/jre/bin/java to provide /usr/bin/java (java) in manual mode
    chyi@earth:~/IoT/UDOO/myandroid$ java -version
    java version "1.7.0_95"
    OpenJDK Runtime Environment (IcedTea 2.6.4) (7u95-2.6.4-3)
    OpenJDK 64-Bit Server VM (build 24.95-b01, mixed mode)
    ---------------------------------------------------------------------------------------------------------------------------

    $ sudo update-alternatives --config javac
    $ sudo update-alternatives --config javap
    $ sudo update-alternatives --config javadoc
    $ sudo update-alternatives --config javah

    <Android build  절차>
    모든 환경이 준비되었으니, 이제 부터는 android source를 내려 받아 build를 해 보도록 하자.
    $ cd UDOO/
    $ mkdir myandroid
    $ mkdir bin
    $ curl http://commondatastorage.googleapis.com/git-repo-downloads/repo > ./bin/repo
    $ chmod 755 repo ./bin/repo

    $ cd myandroid/
    $ ../bin/repo init -u https://github.com/UDOOboard/android_udoo_platform_manifest -b android-6.0.1
    $ ../bin/repo sync -j5

    $ export ARCH=arm
    $ source build/envsetup.sh 
    including device/fsl/imx6/vendorsetup.sh
    including device/fsl/imx7/vendorsetup.sh
    including device/udoo/imx6/vendorsetup.sh
    including sdk/bash_completion/adb.bash

    $ lunch
    You're building on Linux
    Lunch menu... pick a combo:
         1. aosp_arm-eng
         2. aosp_arm64-eng
         3. aosp_mips-eng
         4. aosp_mips64-eng
         5. aosp_x86-eng
         6. aosp_x86_64-eng
         7. sabresd_6dq-eng
         8. sabresd_6dq-user
         9. sabreauto_6q-eng
         10. sabreauto_6q-user
         11. evk_6sl-eng
         12. evk_6sl-user
         13. sabresd_6sx-eng
         14. sabresd_6sx-user
         15. sabreauto_6sx-eng
         16. sabreauto_6sx-user
         17. evk_6ul-eng
         18. evk_6ul-user
         19. sabresd_7d-eng
         20. sabresd_7d-user
         21. a62_6dq-eng
         22. a62_6dq-user
         23. udoo_6dq-eng
         24. udoo_6dq-user
         25. udooneo_6sx-eng
         26. udooneo_6sx-user

    Which would you like? [aosp_arm-eng] udooneo_6sx-eng

    ============================================
    PLATFORM_VERSION_CODENAME=REL
    PLATFORM_VERSION=6.0.1
    TARGET_PRODUCT=udooneo_6sx
    TARGET_BUILD_VARIANT=eng
    TARGET_BUILD_TYPE=release
    TARGET_BUILD_APPS=
    TARGET_ARCH=arm
    TARGET_ARCH_VARIANT=armv7-a-neon
    TARGET_CPU_VARIANT=cortex-a9
    TARGET_2ND_ARCH=
    TARGET_2ND_ARCH_VARIANT=
    TARGET_2ND_CPU_VARIANT=
    HOST_ARCH=x86_64
    HOST_OS=linux
    HOST_OS_EXTRA=Linux-4.4.0-62-generic-x86_64-with-Ubuntu-16.04-xenial
    HOST_BUILD_TYPE=release
    BUILD_ID=6.0.1-beta2
    OUT_DIR=out
    ============================================

    $ make -j5
      => 중간에 에러가 계속 발생하여, 결국 build에 실패함.
      => 여러가지 시도를 해 보았으나, 아무래도 다른 방법을 찾아야 할 듯 보임.

    UDOO NEO 보드용 android marshmallow source code는 Ubuntu 14.04에서는 검증(정상 build 확인)되었으나, 아무래도 Ubuntu 16.04에서는 그렇지 못한 듯하다(Android web page에도 14.04를 사용하도록 권고하고 있음). 따라서 Virtual Ubuntu 14.04 환경을 만들고 여기에서 build를 시도해 보는 것이 답일 듯 보인다. Virtual 환경으로는 Oracle VirtualBox가 매우 훌륭하지만, android가 워낙 방대한 크기를 자랑(?)하기 때문에 VirtualBox에서 android를 build하는 것은 좋은 선택이 아닐 듯 싶다(과거 경험상 이건 답이 아니다). 그렇다면 어찌해야 할까 ?


    3. Docker 환경에서 Android Source Build 하기 
    이번 절에서는 Ubuntu 16.04 Host PC(64bit)에 docker를 설치하고, 다시 docker를 통해 Ubuntu 14.04 LTS(64bit)를 설치한 후 이 환경에서 android source code를 build하는 과정을 소개해 보고자 한다.
    그림 3.1 docker container 아키텍쳐

    <Docker 설치>
    $ sudo apt-get update
      => 먼저 package database를 갱신하자.

    $ sudo apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D
      => 공식 docker 저장소(repository)를 위한 GPG key를 추가한다.

    $ sudo apt-add-repository 'deb https://apt.dockerproject.org/repo ubuntu-xenial main'
      => APT source에 docker 저장소를 추가한다.

    $ sudo apt-get update
      => 다시 package database를 갱신한다.

    $ apt-cache policy docker-engine
      => ubuntu 저장소 대신에 docker 저장소로 부터 install 하도록 설정 변경한다.

    $ sudo apt-get install -y docker-engine
      => (실제로) docker를 설치한다.

    $ sudo systemctl status docker
      => 정상적으로 docker가 설치되었는지를 확인한다.
    ● docker.service - Docker Application Container Engine
       Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
       Active: active (running) since 목 2017-02-09 20:40:19 KST; 12s ago
         Docs: https://docs.docker.com
     Main PID: 10318 (dockerd)
        Tasks: 19
       Memory: 20.6M
          CPU: 451ms
       CGroup: /system.slice/docker.service
               ├─10318 /usr/bin/dockerd -H fd://
               └─10328 docker-containerd -l unix:///var/run/docker/libcontainerd/docker-containerd.soc

     2월 09 20:40:15 earth dockerd[10318]: time="2017-02-09T20:40:15.461308459+09:00" level=warning msg
     2월 09 20:40:15 earth dockerd[10318]: time="2017-02-09T20:40:15.461755681+09:00" level=warning msg
     2월 09 20:40:15 earth dockerd[10318]: time="2017-02-09T20:40:15.463056059+09:00" level=info msg="L
     2월 09 20:40:16 earth dockerd[10318]: time="2017-02-09T20:40:16.014229231+09:00" level=info msg="F
     2월 09 20:40:16 earth dockerd[10318]: time="2017-02-09T20:40:16.989395982+09:00" level=info msg="D
     2월 09 20:40:18 earth dockerd[10318]: time="2017-02-09T20:40:18.859934895+09:00" level=info msg="L
     2월 09 20:40:19 earth dockerd[10318]: time="2017-02-09T20:40:19.091618066+09:00" level=info msg="D
     2월 09 20:40:19 earth dockerd[10318]: time="2017-02-09T20:40:19.091683685+09:00" level=info msg="D
     2월 09 20:40:19 earth dockerd[10318]: time="2017-02-09T20:40:19.108524743+09:00" level=info msg="A
     2월 09 20:40:19 earth systemd[1]: Started Docker Application Container Engine.

    $ sudo usermod -aG docker $(whoami)
      => docker 명령 실행 시, sudo를 사용하지 않도록 하기 위해 docker group에 내 계정을 추가한다.
      => 이 상태에서 group 변경 사항을 반영하기 위해 logout -> login을 시도한다.

    $ docker info
      => docker 정보를 출력해 본다.

    $ docker run -it ubuntu:trusty /bin/bash
      => ubuntu 14.04(trusty)를 내려 받아 실행한다. 기본 shell 은 bash를 사용하도록 한다.
      => 참고: 위의 명령은 내부적으로 아래의 3개 명령(검색 ->  download -> 실행)을 한번에 실행하는 것과 동일한 효과가 있다.
    ---------------------------------------
    $ docker search ubuntu
    $ docker pull ubuntu
    $ docker run -it ubuntu
    ---------------------------------------

    <docker login 상태>
      => 최초 ubuntu 14.04를 설치한 상태에서는 아무런 package가 설치되어 있지 않으므로, 아래의 절차를 따라 android build에 필요한 기본 package를 내려 받도록 한다.

    # echo "debconf shared/accepted-oracle-license-v1-1 select true" | debconf-set-selections
    # echo "debconf shared/accepted-oracle-license-v1-1 seen true" | debconf-set-selections
    # apt-get update

    # apt-get install git git-core gnupg flex bison gperf build-essential zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z-dev ccache libgl1-mesa-dev libxml2-utils xsltproc unzip

    # apt-get install openjdk-7-jdk
      => android marshmallow는 openjdk 7이 필요하다.

    # apt-get install uuid uuid-dev lzop liblz-dev iblzo2-dev u-boot-tools mtd-utils android-tools-fsutils

    # exit

    참고: 위의 내용은 추후 dockerfile로 구성해 볼 필요가 있겠음.

    $ docker commit -m "android_env_for_udoo" -a "Chunghan Yi" dc26188cb1c2 chyi/udoo
     => 여기까지 수정한 사항을 일단 commit하도록 하자. 이는 마치 git으로 변경 사항을 commit하는 과정과 유사해 보임.
     => dc26188cb1c2는 "docker run -it ubuntu:trusty /bin/bash" 실행시 출력되는 값임.
     => 이 commit 과정을 진행하지 않을 경우, 다음 번 login 시 위에서 설치한 모든 내용을 잃게 됨.

    $ docker images
      => 앞서 commit하여 새로 생성된 docker image를 확인해 보도록 한다.
    REPOSITORY              TAG                 IMAGE ID            CREATED             SIZE
    chyi/udoo               latest              f522c08dd2b8        12 seconds ago      763 MB
    ubuntu                  latest              f49eec89601e        2 weeks ago         129 MB
    ubuntu                  trusty              b969ab9f929b        2 weeks ago         188 MB
    hello-world             latest              48b5124b2768        3 weeks ago         1.84 kB
    bprodoehl/android-dev   latest              718567bb2723        2 years ago         7.95 GB

    $ docker run -it chyi/udoo /bin/bash
      => 다시  ubuntu를 실행한다. 이번에는 ubuntu:trusty 대신 chyi/udoo를 입력함.

    <docker login 상태 : android source download>
      => android source를 download하도록 하자.
    # cd /home
    # mkdir myandroid bin
    # cd bin
    # curl http://commondatastorage.googleapis.com/git-repo-downloads/repo > ./repo
    # chmod 755 repo
    # cd ../myandroid
    # /home/bin/repo init -u https://github.com/UDOOboard/android_udoo_platform_manifest -b android-6.0.1
    # /home/bin/repo sync -j5
      => 무지 오래 걸림(3 ~ 4시간 소요)
    # exit

    $ docker commit -m "android_source_for_udoo" -a "Chunghan Yi" c9dd472c7995 chyi/udoo
      => 여기까지 수정한 내용을 다시 commit한다.

    $ docker images
    REPOSITORY              TAG                 IMAGE ID            CREATED             SIZE
    chyi/udoo               latest              024eb43eb4b5        38 minutes ago      40.8 GB
    ubuntu                  latest              f49eec89601e        2 weeks ago         129 MB
    ubuntu                  trusty              b969ab9f929b        2 weeks ago         188 MB
    hello-world             latest              48b5124b2768        3 weeks ago         1.84 kB
    bprodoehl/android-dev   latest              718567bb2723        2 years ago         7.95 GB

    $ docker run -it chyi/udoo /bin/bash

    <docker login 상태 : android source build>
      => build를 시도해 보도록 하자.

    root@4f33ac3a0170:/home/myandroid# export ARCH=arm

    root@4f33ac3a0170:/home/myandroid# source build/envsetup.sh
    including device/fsl/imx6/vendorsetup.sh
    including device/fsl/imx7/vendorsetup.sh
    including device/udoo/imx6/vendorsetup.sh
    including sdk/bash_completion/adb.bash

    root@4f33ac3a0170:/home/myandroid# lunch
    You're building on Linux

    Lunch menu... pick a combo:
         1. aosp_arm-eng
         2. aosp_arm64-eng
         3. aosp_mips-eng
         4. aosp_mips64-eng
         5. aosp_x86-eng
         6. aosp_x86_64-eng
         7. sabresd_6dq-eng
         8. sabresd_6dq-user
         9. sabreauto_6q-eng
         10. sabreauto_6q-user
         11. evk_6sl-eng
         12. evk_6sl-user
         13. sabresd_6sx-eng
         14. sabresd_6sx-user
         15. sabreauto_6sx-eng
         16. sabreauto_6sx-user
         17. evk_6ul-eng
         18. evk_6ul-user
         19. sabresd_7d-eng
         20. sabresd_7d-user
         21. a62_6dq-eng
         22. a62_6dq-user
         23. udoo_6dq-eng
         24. udoo_6dq-user
         25. udooneo_6sx-eng
         26. udooneo_6sx-user

    Which would you like? [aosp_arm-eng] 25

    root@4f33ac3a0170:/home/myandroid# make -j5
      => kernel build 시 bc가 없어서 에러 발생함.

    # apt-get install bc
      => kernel compile시 에러 발생하여 설치

    root@4f33ac3a0170:/home/myandroid# make -j5
      => 다시 build 시도 ! 
      => kernel에서 또 다른 error 발생, 아무래도 얘네(udoo.org)가 뭔가 잘못 만들어 배포하는 느낌 :(
    ...
      CC [M]  backports/drivers/net/wireless/ti/wl18xx/event.o
      LD [M]  backports/drivers/net/wireless/ti/wl18xx/wl18xx.o
    fatal: Not a git repository (or any of the parent directories): .git
      CHK     backports/drivers/net/wireless/ti/wlcore/version.h
      UPD     backports/drivers/net/wireless/ti/wlcore/version.h
      CC [M]  backports/drivers/net/wireless/ti/wlcore/main.o
    arm-eabi-gcc: error: backports/drivers/net/wireless/ti/wlcore/main.c: No such file or directory
    arm-eabi-gcc: fatal error: no input files
    compilation terminated.
    make[6]: *** [backports/drivers/net/wireless/ti/wlcore/main.o] Error 1
    make[5]: *** [backports/drivers/net/wireless/ti/wlcore] Error 2
    make[4]: *** [backports/drivers/net/wireless/ti] Error 2
    make[3]: *** [backports/drivers/net/wireless] Error 2
    make[2]: *** [backports] Error 2
    make[1]: *** [sub-make] Error 2
    make: *** [kernelmodules] Error 2

    #### make failed to build some targets (03:48 (mm:ss)) ####
    ---------------------------------------------------------------

    # cd kernel_imx
    # make mrproper
      => kernel build에 에러가 발생할 이유가 전혀 없는데, 실제 발생하고 있음.
      => distclean 해 보기로 함.
    # cd ..
    # make -j5
      => 다시 build 시도했으나, (kernel 문제는 해결되었으나) 다른 error 발생 
    ...
    Install: out/host/linux-x86/framework/jack.jar
    out/host/linux-x86/bin/jack-admin: line 27: USER: unbound variable
    make: *** [out/host/linux-x86/framework/jack.jar] Error 1
    make: *** Deleting file `out/host/linux-x86/framework/jack.jar'
    ----------------------------------------------------------------
    # export USER=$(whoami)
      => docker에서 build할 경우 반드시 설정해 주어야 함.
      => 다시 build 시도 !

    # make -j8 2>&1 | tee myresult.txt
      => 에러 원인을 찾기 위해 error 내용을 myresult.txt로 남기도록 함.
      => 다른 에러가 계속 발생함 .... 결국 해결 안됨 ...
      => 혹시나 하여  user mode로 build해 보기로 함.

    root@4f33ac3a0170:/home/myandroid# lunch
    You're building on Linux

    Lunch menu... pick a combo:
         1. aosp_arm-eng
         2. aosp_arm64-eng
         3. aosp_mips-eng
         4. aosp_mips64-eng
         5. aosp_x86-eng
         6. aosp_x86_64-eng
         7. sabresd_6dq-eng
         8. sabresd_6dq-user
         9. sabreauto_6q-eng
         10. sabreauto_6q-user
         11. evk_6sl-eng
         12. evk_6sl-user
         13. sabresd_6sx-eng
         14. sabresd_6sx-user
         15. sabreauto_6sx-eng
         16. sabreauto_6sx-user
         17. evk_6ul-eng
         18. evk_6ul-user
         19. sabresd_7d-eng
         20. sabresd_7d-user
         21. a62_6dq-eng
         22. a62_6dq-user
         23. udoo_6dq-eng
         24. udoo_6dq-user
         25. udooneo_6sx-eng
         26. udooneo_6sx-user

    Which would you like? [aosp_arm-eng] 26

    # make -j8 2>&1 | tee myresult3.txt
      => 헐, user mode로는 정상  build 됨. :(

    <build 결과물 확인>
    root@4f33ac3a0170:/home/myandroid/out/target/product/udooneo_6sx# ls -l
    total 535112
    -rw-r--r--  1 root root        14 Feb 10 08:04 android-info.txt
    -rw-r--r--  1 root root   6665511 Feb 10 08:09 boot-imx6sx.img
    -rw-r--r--  1 root root   6665511 Feb 10 08:09 boot.img
    -rw-r--r--  1 root root     64231 Feb 10 08:02 clean_steps.mk
    drwxr-xr-x  3 root root      4096 Feb 10 08:04 dex_bootjars
    drwxr-xr-x  2 root root      4096 Feb 10 07:05 fake_packages
    drwxr-xr-x  5 root root      4096 Feb 10 07:53 gen
    -rwxr-xr-x  1 root root     46438 Feb 10 08:05 imx6sx-udoo-neo-full-hdmi-m4.dtb
    -rw-r--r--  1 root root     88925 Feb 10 08:11 installed-files.txt
    -rwxr-xr-x  1 root root   5703088 Feb 10 08:05 kernel
    drwxr-xr-x 18 root root      4096 Feb 10 08:11 obj
    -rw-r--r--  1 root root       548 Feb 10 08:02 previous_build_config.mk
    -rw-r--r--  1 root root   4655650 Feb 10 08:10 ramdisk-recovery.img
    -rw-r--r--  1 root root    910938 Feb 10 08:09 ramdisk.img
    drwxr-xr-x  3 root root      4096 Feb 10 08:04 recovery
    -rw-r--r--  1 root root  10411308 Feb 10 08:10 recovery-imx6sx.img
    -rw-r--r--  1 root root        67 Feb 10 08:10 recovery.id
    -rw-r--r--  1 root root  10411308 Feb 10 08:10 recovery.img
    drwxr-xr-x 10 root root      4096 Feb 10 08:09 root
    drwxr-xr-x  6 root root      4096 Feb 10 07:06 symbols
    drwxr-xr-x 14 root root      4096 Feb 10 08:10 system
    -rw-r--r--  1 root root 501625152 Feb 10 08:11 system.img
    -rwxr-xr-x  1 root root    332440 Feb 10 05:31 u-boot-imx6sx.imx
    -rw-r--r--  1 root root    332440 Feb 10 05:31 u-boot.imx

    root@4f33ac3a0170:/home/myandroid/out/target/product/udooneo_6sx# exit
    exit
    chyi@earth:~$ docker commit -m "android_marshmallow_build_user_mode_done" -a "Chunghan Yi" 4f33ac3a0170 chyi/udoo
      => 지금까지 수정한 내용 commit 함.

    chyi@earth:~$ docker images
    REPOSITORY              TAG                 IMAGE ID            CREATED              SIZE
    chyi/udoo               latest              d3560a597201        About a minute ago   61.7 GB
    ubuntu                  latest              f49eec89601e        2 weeks ago          129 MB
    ubuntu                  trusty              b969ab9f929b        2 weeks ago          188 MB
    hello-world             latest              48b5124b2768        3 weeks ago          1.84 kB
    bprodoehl/android-dev   latest              718567bb2723        2 years ago          7.95 GB



    4. Android UDOO Neo board 파일 분석 및 몇가지 Tips
    먼저 원할한 source code 분석을 위해 (docker image 내에) ssh server와 사용자 계정을 추가하도록 하자.

    <첫번째 terminal>
    root@1046ecb38863:~# apt-get install ssh
    root@1046ecb38863:~# /etc/init.d/ssh restart
    root@1046ecb38863:~# adduser test1
    ...
    $ docker commit -m "add new user" -a "Chunghan Yi" 1046ecb38863 chyi/udoo
    docker run -it chyi/udoo /bin/bash

    <다른 terminal에서 접속>
    chyi@earth:~$ ssh test1@172.17.0.2

    <udoo neo board 관련 파일>

    그림 4.1 device/udoo/imx6/soc/imx6sx.mk file

    root@af1bc3d5c3f1:~/myandroid/device/udoo/udooneo_6sx# ls -la
    total 72
    drwxr-xr-x  4 root root  4096 Feb 13 05:32 .
    drwxr-xr-x 11 root root  4096 Feb 13 04:53 ..
    -rw-r--r--  1 root root   227 Feb  9 15:43 AndroidBoard.mk
    -rw-r--r--  1 root root  6486 Feb  9 15:43 BoardConfig.mk
    -rw-r--r--  1 root root  4172 Feb  9 15:43 audio_effects.conf
    -rw-r--r--  1 root root  3430 Feb  9 15:43 audio_policy.conf
    drwxr-xr-x  2 root root  4096 Feb  9 15:43 bluetooth
    -rw-r--r--  1 root root   854 Feb  9 15:43 build_id.mk
    -rw-r--r--  1 root root  1711 Feb 10 08:01 fstab.freescale
    -rw-r--r--  1 root root  1711 Feb  9 15:43 fstab_sd.freescale
    -rwxr-xr-x  1 root root 10738 Feb  9 15:43 init.rc
    drwxr-xr-x  4 root root  4096 Feb  9 15:43 overlay
    -rw-r--r--  1 root root   690 Feb  9 15:43 twrp.mk
    -rw-r--r--  1 root root   163 Feb  9 15:43 uEnv.txt

    그림 4.2 device/udoo/udooneo_6sx/BoardConfig.mk 내용 중 일부 발췌

    그림 4.3 device/udoo/udooneo_6sx/init.rc 내용 중 일부 발췌

    이 밖에도 device 디렉토리 내에는 udoo neo board  관련 다양한 board 설정 관련 파일이 존재한다. 편의상 이부분에 관한 추가 분석은 독자 여러분의 몫으로 남긴다.

    다음으로 linux kernel과 bootloader(u-boot)를 단독으로 build하는 절차를 정리해 보기로 하겠다. (당연한 얘기지만) 이 방법이 필요한 이유는 android 전체를 build하는 시간이 매우 오래 걸리므로 linux kernel과 bootloader는 개별적으로 build하는 것이 보다 효율적이기 때문이다.

    <u-boot bootloader build 절차>
      => build/core/Makefile을 참조하여 다시 작성함.

    # export ARCH=arm
    # export CROSS_COMPILE=`pwd`/prebuilts/gcc/linux-x86/arm/arm-eabi-5.3/bin/arm-eabi-
    # export O=`pwd`/out/target/product/udooneo_6sx/obj/UBOOT_OBJ
    # export PRODUCT_OUT=`pwd`/out/target/product/udooneo_6sx

    # make -C bootable/bootloader/uboot-imx distclean 
      => dist clean

    # make -C bootable/bootloader/uboot-imx udoo_neo_android_defconfig 
      => udoo neo android configuration 초기화

    make -C bootable/bootloader/uboot-imx
      => u-boot build를 시도한다.

    <u-boot-imx6sx.imx 생성 절차>
    # dd if=$(O)/SPL of=$(PRODUCT_OUT)/u-boot.imx bs=1K seek=0 conv=notrunc
    # dd if=$(O)/u-boot.img of=$(PRODUCT_OUT)/u-boot.imx bs=1K seek=68
    # cp $(PRODUCT_OUT)/u-boot.imx $(PRODUCT_OUT)/u-boot-imx6sx.imx


    <linux kernel build 절차>
    # export ARCH=arm
    # export CROSS_COMPILE=`pwd`/prebuilts/gcc/linux-x86/arm/arm-eabi-5.3/bin/arm-eabi-
    # export O=`pwd`/out/target/product/udooneo_6sx/obj/KERNEL_OBJ
    # export PRODUCT_OUT=`pwd`/out/target/product/udooneo_6sx

    # make -C kernel_imx udoo_neo_android_defconfig  LOADADDR=0x80008000
      => kernel config(udoo_neo_android_defconfig) 초기화

    # make -C kernel_imx -j4 uImage  LOADADDR=0x80008000
      => uImage 생성(build)

    # make -C kernel_imx dtbs LOADADDR=0x80008000
      => dtb file 생성

    # make -C kernel_imx modules LOADADDR=0x80008000
      => kernel module build

    <output file 생성 절차>
    # cp $(O)/arch/arm/boot/zImage $(PRODUCT_OUT)/kernel
    # cp $(O)/arch/arm/boot/dts/imx6sx-udoo-neo-full-hdmi-m4.dtb  $(PRODUCT_OUT)/imx6sx-udoo-neo-full-hdmi-m4.dtb

    개별적으로 kernel을 build하는 절차를 살펴 보았으니, 이제부터는 boot.img를 분해 & 신규 생성하는 절차를 살펴 보도록 하자. 이와 관련한 보다 자세한 사항은 (좀 오래된 내용이기는 하나 본 blogger의)아래 문서를 참조하기 바란다.
    https://github.com/ChunghanYi/linux_kernel_hacks/blob/master/android_kernel_hacks/AndroidKernelHacks_Chapter1.pdf

    <boot.img 분해하기>
    # cd out/target/product/udooneo_6sx
    # device/udoo/common/tools/split_bootimg.pl ./boot.img 
    Page size: 2048 (0x00000800)
    Kernel size: 5703088 (0x005705b0)
    Ramdisk size: 910938 (0x000de65a)
    Second size: 46438 (0x0000b566)
    Board name: 
    Command line: console=ttymxc0,115200 init=/init vmalloc=256M androidboot.console=ttymxc0 consoleblank=0 androidboot.hardware=freescale cma=128M androidboot.selinux=disabled androidboot.dm_verity=disabled no_console_suspend uart_from_osc clk_ignore_unused
    Writing boot.img-kernel ... complete.
    Writing boot.img-ramdisk.gz ... complete

    # ls -l
    total 13024
    -rw-r--r-- 1 root root 6665511 Feb 13 05:22 boot.img
    -rw-r--r-- 1 root root 5703088 Feb 13 05:22 boot.img-kernel
                                                                              => linux kernel image(zImage)
    -rw-r--r-- 1 root root  910938 Feb 13 05:22 boot.img-ramdisk.gz
                                                                              => ramdisk rootfs
    -rw-r--r-- 1 root root   46438 Feb 13 05:22 boot.img-second.gz
                                                                              => boot.img 맨 끝 영역

    <ramdisk rootfs file 분해/생성하기>
    # gzip -d boot.img-ramdisk .gz
    # cpio -i < ./boot.img-ramdisk

    그림 4.4 ramdisk rootfs 디렉토리 구성

    <ramdisk 내용 수정 후, ramdisk file 다시 묶기>
    # find . | cpio –o –H newc | gzip > ../newramdisk .cpio.gz


    <boot.img 생성하기>
    # out/host/linux-x86/bin/mkbootimg \
    --cmdline "console=ttymxc0,115200 init=/init vmalloc=256M androidboot.console=ttymxc0 consoleblank=0 androidboot.hardware=freescale cma=128M androidboot.selinux=disabled androidboot.dm_verity=disabled no_console_suspend uart_from_osc clk_ignore_unused” \
    --kernel zImage \
    --ramdisk newramdisk .cpio.gz \
    --base 0x84800000 \
    -o boot.img

    (*) 참고: --base 0x84800000 값은 device/udoo/imx6/soc/imx6sx.mk 파일 내의 BOARD_KERNEL_BASE 값을 사용해야 한다.


    5. UDOO Neo 보드 부팅하기
    UDOO Neo 보드가 (4일만에) 도착했다. :) 이번 절에서는 앞서 build한 android image를 확인하기에 앞서 udoobuntu OS image가 어찌 동작하는지를 먼저 확인해 본 후, android image를 돌려 보도록 하겠다.

    5.1 Udoobuntu 이미지로 부팅하기
    $ unzip udoobuntu-udoo-neo-desktop_2.1.2.zip

    $ sudo dd if=./udoobuntu-udoo-neo-desktop_2.1.2.img of=/dev/sdb bs=1M
    2772+0 레코드 들어옴
    2772+0 레코드 나감
    2906652672 bytes (2.9 GB, 2.7 GiB) copied, 574.938 s, 5.1 MB/s

    $ sudo sync

    (참고 사항) Udoobuntu는 그 이름에서도 알 수 있듯이 UDOO 보드용 Ubuntu를 의미하는데, Udoobuntu image를 생성하기 위해서는 아래의 명령을 사용하면 된다.
    git clone https://github.com/UDOOboard/mkudoobuntu.git
    $ cd mkudobuntu
    sudo ./mkudoobuntu.sh udoo-neo desktop
      => mkudoobuntu.sh script는 내부적으로 armbian project의 debootstrap 명령을 사용하여 ubuntu image를 만들어 낸다(예: sudo debootstrap --arch=armhf --foreign $distro $targetdir)
      => u-boot, kernel 등도 build하여 생성한다.
    -------------------------------------------------------------------------------------------------------------------------------------------

    정상적으로 image writing이 완료되었다면, microSD 카드를 보드에 삽입한 후, 전원(DC 12V/2A or USB Wall Charger 5V with Micro USB Data Cable)을 인가하도록 하자.

    그림 5.1 UDOO Neo 보드 연결 모습

    그림 5.2 UDOO Neo 콘솔 부팅 모습(115200, 8N1)

    콘솔 로긴 후, ethernet port에 대해 ip 주소(예: 192.168.1.2)를 강제로 지정하고, chrome browser로 웹 접속을 시도해 보자.

    그림 5.3 UDOO Neo 보드 웹 UI 화면

    아래 그림은 UDOO Neo 보드 웹 UI 화면 중, 아두이노 코딩을 위한 page(이번에는 Wi-Fi로 할당받은 주소로 접속을 시도함)를 보여준다.

    그림 5.4 UDOO Neo 보드 웹 UI - Arduino 코딩 화면

    UDOO Neo 웹 화면에서는 아래 그림과 같이 console terminal을 직접 띄울 수도 있다.

    그림 5.5 UDOO Neo 보드 웹 UI - Remote Terminal 화면 


    5.2 Android 이미지로 부팅하기
    자, 그럼 이제부터는 3절에서 build하여 얻은 android image를 설치해 볼 차례이다.

    $ docker run -it chyi/udoo /bin/bash
      => docker로 ubuntu를 시작한다.

    <Docker Guest OS>
    root@9867b222a162:/home/myandroid# ./prepare_distro.sh mydroid
      => udoo.org에서 제공하는  prepare_distro.sh 파일을 통해  mydroid.tar.gz file을 만들도록 한다.
    Distro Name selected: mydroid
    'out/target/product/udooneo_6sx/u-boot.imx' -> 'mydroid/u-boot.imx'
    'out/target/product/udooneo_6sx/boot.img' -> 'mydroid/boot.img'
    'out/target/product/udooneo_6sx/recovery.img' -> 'mydroid/recovery.img'
    'make_sd.sh' -> 'mydroid/make_sd.sh'
    'README_make_uSD.txt' -> 'mydroid/README_make_uSD.txt'
    'README_compile_Android.txt' -> 'mydroid/README_compile_Android.txt'
    mydroid/
    mydroid/u-boot.imx
    mydroid/boot.img
    mydroid/README_make_uSD.txt
    mydroid/make_sd.sh
    mydroid/README_compile_Android.txt
    mydroid/system_raw.img
    mydroid/recovery.img

    root@9867b222a162:/home/myandroid# scp ./mydroid.tar.gz chyi@172.17.0.1:~/IoT/UDOO/images/mine
    => scp를 사용하여 mydroid.tar.gz 파일을 Host OS로 복사한다.
    The authenticity of host '172.17.0.1 (172.17.0.1)' can't be established.
    ECDSA key fingerprint is 99:ef:ce:37:39:7f:7e:7d:7b:f0:cf:bb:ca:2b:be:93.
    Are you sure you want to continue connecting (yes/no)? yes
    Warning: Permanently added '172.17.0.1' (ECDSA) to the list of known hosts.
    ...
    --------------------------------------------------------------------

    <Host OS>
    $ docker commit -m "create mydroid.tar.gz" -a "Chunghan Yi" 9867b222a162 chyi/udoo
    sha256:e3229a376acce736815faf5612c364f7e07d2fe2cbf54515d0e0e5d40c5455e9
      => 앞서 수정한 사항을 저장하도록 한다.

    $ cd ~/IoT/UDOO/images/mine
    $ tar xvzf ./mydroid.tar.gz
       => guest OS로 부터 전달받은 mydroid.tar.gz file의 압축을 푼다.
    $ cd mydroid
    $ sudo -E ./make_sd.sh /dev/sdb
      => PC에 삽입한 microSD card의 장치명이 /dev/sdb라고 하자.
      => make_sd.sh 파일은 udoo.org에서 제공하는 파일로, microSD card에 android image를 설치(파티션 생성 및 file system을 만들어 줌)하는 역할을 담당한다.

    Trying to unmount partitions

    ############################################################################# 
    ##                                                                         ## 
    ## Going to format /dev/sdb device. Everything on this device will be lost ## 
    ##                                                                         ## 
    ##  Android Distro will be grabbed from:                                   ## 
    ##   ./  ## 
    ##                                                                         ## 
    ############################################################################# 

      Current partition table on /dev/sdb: 

    Disk /dev/sdb: 14.9 GiB, 15931539456 bytes, 31116288 sectors
    Units: sectors of 1 * 512 = 512 bytes
    Sector size (logical/physical): 512 bytes / 512 bytes
    I/O size (minimum/optimal): 512 bytes / 512 bytes
    Disklabel type: dos
    Disk identifier: 0xa4bb2440

    Device     Boot   Start     End Sectors  Size Id Type
    /dev/sdb1          2048   34815   32768   16M 83 Linux
    /dev/sdb2         36864   69631   32768   16M 84 OS/2 hidden or Intel hibernation
    /dev/sdb3         69632 4304895 4235264    2G  5 Extended
    /dev/sdb4       4304896 7088127 2783232  1.3G 83 Linux
    /dev/sdb5         71680 3143679 3072000  1.5G 83 Linux
    /dev/sdb6       3145728 4194303 1048576  512M 83 Linux
    /dev/sdb7       4196352 4212735   16384    8M 83 Linux
    /dev/sdb8       4214784 4227071   12288    6M 83 Linux
    /dev/sdb9       4229120 4233215    4096    2M 83 Linux

    Partition table entries are not in disk order.

    Continue with formatting ? (y/N)y
    Create android partition...
    1+0 records in
    1+0 records out
    1024 bytes (1.0 kB, 1.0 KiB) copied, 0.00380178 s, 269 kB/s
    Checking that no-one is using this disk right now ... OK

    Disk /dev/sdb: 14.9 GiB, 15931539456 bytes, 31116288 sectors
    Units: sectors of 1 * 512 = 512 bytes
    Sector size (logical/physical): 512 bytes / 512 bytes
    I/O size (minimum/optimal): 512 bytes / 512 bytes

    >>> Created a new DOS disklabel with disk identifier 0x316eae91.
    Created a new partition 1 of type 'Linux' and of size 16 MiB.
    /dev/sdb2: Created a new partition 2 of type 'Linux' and of size 16 MiB.
    /dev/sdb3: Created a new partition 3 of type 'Extended' and of size 2 GiB.
    /dev/sdb4: Created a new partition 4 of type 'Linux' and of size 12.7 GiB.
    /dev/sdb5: Created a new partition 5 of type 'Linux' and of size 1.5 GiB.
    /dev/sdb6: Created a new partition 6 of type 'Linux' and of size 512 MiB.
    /dev/sdb7: Created a new partition 7 of type 'Linux' and of size 8 MiB.
    /dev/sdb8: Created a new partition 8 of type 'Linux' and of size 8 MiB.
    /dev/sdb9: 
    New situation:

    Device     Boot   Start      End  Sectors  Size Id Type
    /dev/sdb1         32768    65535    32768   16M 83 Linux
    /dev/sdb2         65536    98303    32768   16M 83 Linux
    /dev/sdb3         98304  4333567  4235264    2G  5 Extended
    /dev/sdb4       4333568 31033343 26699776 12.7G 83 Linux
    /dev/sdb5         98305  3170304  3072000  1.5G 83 Linux
    /dev/sdb6       3173305  4221880  1048576  512M 83 Linux
    /dev/sdb7       4224881  4241264    16384    8M 83 Linux
    /dev/sdb8       4244265  4260648    16384    8M 83 Linux

    Partition table entries are not in disk order.

    The partition table has been altered.
    Calling ioctl() to re-read partition table.
    Syncing disks.
    Formatting partitions...
    mke2fs 1.42.13 (17-May-2015)
    Creating filesystem with 3337472 4k blocks and 835584 inodes
    Filesystem UUID: b85105a0-5792-4dcc-86bd-679e6fd5886d
    Superblock backups stored on blocks: 
    32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208

    Allocating group tables: done                            
    Writing inode tables: done                            
    Creating journal (32768 blocks): done
    Writing superblocks and filesystem accounting information: done   

    mke2fs 1.42.13 (17-May-2015)
    Creating filesystem with 384000 4k blocks and 96000 inodes
    Filesystem UUID: 29ac28e7-496b-40a7-bf14-5c50d356b205
    Superblock backups stored on blocks: 
    32768, 98304, 163840, 229376, 294912

    Allocating group tables: done                            
    Writing inode tables: done                            
    Creating journal (8192 blocks): done
    Writing superblocks and filesystem accounting information: done 

    mke2fs 1.42.13 (17-May-2015)
    Creating filesystem with 131072 4k blocks and 32768 inodes
    Filesystem UUID: 89b253fc-c096-437e-b70f-9886680aae4c
    Superblock backups stored on blocks: 
    32768, 98304

    Allocating group tables: done                            
    Writing inode tables: done                            
    Creating journal (4096 blocks): done
    Writing superblocks and filesystem accounting information: done

    mke2fs 1.42.13 (17-May-2015)
    Creating filesystem with 8192 1k blocks and 2048 inodes

    Allocating group tables: done                            
    Writing inode tables: done                            
    Creating journal (1024 blocks): done
    Writing superblocks and filesystem accounting information: done

    Flashing android images...
    324+1 records in
    324+1 records out
    332440 bytes (332 kB, 325 KiB) copied, 0.0898845 s, 3.7 MB/s
    16+0 records in
    16+0 records out
    8192 bytes (8.2 kB, 8.0 KiB) copied, 0.00372499 s, 2.2 MB/s
    813+1 records in
    813+1 records out
    6665511 bytes (6.7 MB, 6.4 MiB) copied, 1.44978 s, 4.6 MB/s
    1270+1 records in
    1270+1 records out
    10411308 bytes (10 MB, 9.9 MiB) copied, 3.72556 s, 2.8 MB/s
    74+1 records in
    74+1 records out
    1258217472 bytes (1.3 GB, 1.2 GiB) copied, 266.392 s, 4.7 MB/s
    e2fsck 1.42.13 (17-May-2015)
    Pass 1: Checking inodes, blocks, and sizes
    Pass 2: Checking directory structure
    Pass 3: Checking directory connectivity
    Pass 4: Checking reference counts
    Pass 5: Checking group summary information
    system: 2129/76320 files (0.0% non-contiguous), 124740/304772 blocks
    resize2fs 1.42.13 (17-May-2015)
    Resizing the filesystem on /dev/sdb5 to 384000 (4k) blocks.
    The filesystem on /dev/sdb5 is now 384000 (4k) blocks long.

    324+1 records in
    324+1 records out
    332440 bytes (332 kB, 325 KiB) copied, 0.142313 s, 2.3 MB/s
      
    uSD for Android 6.0.1 for: ->  <- created.

    --------------------------------------------------------------------------------------------------

    정상적으로 image writing이 완료되었다면, microSD 카드를 다시 target 보드에 삽입한 후, 전원을 인가하도록 하자.

    그림 5.6 Android 부팅 화면 1


    그림 5.7 Android 부팅 화면 2

    그림 5.8 Android 부팅 화면 1

    그림 5.9 Android 부팅 화면 2 - 메인 메뉴

    아래 그림은 adb shell로 target board에 접속한 모습을 보여준다.

    그림 5.10 adb shell 명령 실행 모습

    여기서 잠깐 ! fastboot 사용하기
    Fastboot를 사용하여 booting을 시도하거나, flash 파티션 별로 이미지를 설치하는방법과 관련하여 간략히 확인하고 넘어가기로 하자.
    <Host PC>
    sudo adb devices
      => target board가 USB를 통해 연결되어 있는지를 확인한다.
    List of devices attached 
    0f14c9d4e3167ab8 device

    sudo adb reboot-bootloader
      => target board를 fastboot mode로 전환시킨다.
      => 이 명령을 사용하는 대신 u-boot mode(콘솔)에서 fastboot 명령을 실행해도 된다.

    <Target board>
    U-Boot SPL 2015.04-gb80fafc-dirty (Feb 10 2017 - 05:31:03)
    Setting 1024MB RAM calibration data
    port 1
    SPL: u-boot second stage will be loaded from MMC0


    U-Boot 2015.04-gb80fafc-dirty (Feb 10 2017 - 05:31:03)

    CPU:   Freescale i.MX6SX rev1.2 at 792 MHz
    CPU:   Temperature 52 C
    Reset cause: WDOG
    Board: UDOO Neo Full
    I2C:   ready
    DRAM:  1 GiB
    PMIC:  PFUZE3000 DEV_ID=0x30 REV_ID=0x11
    MMC:   FSL_SDHC: 0, FSL_SDHC: 1
    *** Warning - bad CRC, using default environment

    In:    serial
    Out:   serial
    Err:   serial
    check_and_clean: reg 100, flag_set 0
    Fastboot: Normal
    flash target is MMC:0
    Net:   using phy at 0
    FEC0 [PRIME]
      <= fastboot mode로 전환됨.

    <Host PC>
    sudo fastboot devices
      => target board가 fastboot mode로 전환되었는지를 확인한다.
    2530206283809901240 fastboot

    sudo fastboot boot ./boot.img
      => boot.img 파일을 USB를 통해 내려 받아 부팅을 시도한다.
      => 테스트해 본 결과, 불행히도 이 기능은 정상 동작하지 않았다.
    downloading 'boot.img'...
    OKAY [  0.312s]
    booting...
    OKAY [  0.004s]
    finished. total time: 0.315s

    <Host PC>
    sudo fastboot devices
      => target board가 fastboot mode로 전환되었는지를 확인한다.
    2530206283809901240 fastboot

    sudo fastboot flash ./boot.img
      => boot partition의 내용을 boot.img 파일로 교체한다.
    target reported max download size of 419430400 bytes
    sending 'boot' (6509 KB)...
    OKAY [  0.286s]
    writing 'boot'...
    OKAY [  1.462s]
    finished. total time: 1.748s

    <Target board>
    U-Boot 2015.04-gb80fafc-dirty (Feb 10 2017 - 05:31:03)

    CPU:   Freescale i.MX6SX rev1.2 at 792 MHz
    CPU:   Temperature 57 C
    Reset cause: POR
    Board: UDOO Neo Full
    I2C:   ready
    DRAM:  1 GiB
    PMIC:  PFUZE3000 DEV_ID=0x30 REV_ID=0x11
    MMC:   FSL_SDHC: 0, FSL_SDHC: 1
    *** Warning - bad CRC, using default environment

    In:    serial
    Out:   serial
    Err:   serial
    check_and_clean: reg 0, flag_set 0
    Fastboot: Normal
    flash target is MMC:0
    Net:   using phy at 0
    FEC0 [PRIME]
    Normal Boot
    Hit any key to stop autoboot:  0 
    => fastboot
    Starting download of 6665511 bytes
    ..................................................
    downloading of 6665511 bytes finished
    writing to partition 'boot'
    Initializing 'boot'
    switch to partitions #0, OK
    mmc0 is current device
    Writing 'boot'

    MMC write: dev # 0, block # 32768, count 13019 ... 13019 blocks written: OK
    Writing 'boot' DONE!
      <= fastboot 명령으로 boot partition 내용이 교체됨. reset 버튼을 눌러 target board 재부팅함.
    ----------------------------------------------------------------------------------------------------------------------------//

    마지막으로 아래 그림은 Android Studio를 통해 android app을 build하고, adb로 target board에 설치한 후 실행하는 예를 보여준다.
    <Host PC>
    $ adb devices
    List of devices attached
    0f14c9d4e3167ab8 device
    emulator-5554 device

    $ adb -s 0f14c9d4e3167ab8 install ./app-debug.apk
    4364 KB/s (324222 bytes in 0.072s)
    pkg: /data/local/tmp/app-debug.apk
    Success

    그림 5.11 android app을 실행한 모습[참고 문헌 9 참조]


    (간단한 내용이기는 하지만)이상으로 UDOO Neo 보드에 docker 환경을 통해 build한 android marshmallow image를 돌려 보는 전 과정을 간략히 살펴 보았다. 다음 시간에는 UDOO Neo 보드의 특징을 좀 더 구체적으로 분석하는 시간을 가져 보도록 하겠다.

    <TODO>
      - schematic 분석
      - device tree 분석 & external pin 설정 관련 
      - u-boot, kernel 주요 코드 분석
      - arduino(cortex-m4) 파트 관련 설정 테스트 
      - android nougat porting(시간이 허락한다면)


    References
    1. http://www.udoo.org/docs-neo/Advanced_Topics/Compile_Android_From_Source.html
    2. https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-ubuntu-16-04
    3. https://docs.docker.com/engine/installation/linux/ubuntu/
    4. http://blog.nacyot.com/articles/2014-01-27-easy-deploy-with-docker/
    5. Docker Up & Running, Karl Matthias & Sean P.Kane, O'Reilly.
    6. https://source.android.com/source/downloading.html
    7. Embedded Android, Karim Yaghmour, O'Reilly.
    8. http://elinux.org/UDOO_Installing_Debian_With_Debootstrap
    9. 실전 앱 프로젝트 - 안드로이드 게임 개발편, 박승제, JPub.

    Slowboot

    2017년 1월 22일 일요일

    Atmel SAM-ICE를 이용한 u-boot & linux kernel debugging

    이번 post에서는 Atmel SAM-ICE JTAG emulator를 이용하여 SAMA5D3 Xplained board 상에서 u-boot 및 linux kernel을 debugging하는 방법을 소개해 보고자 한다.

    SAM-ICE JTAG emulator + SAMA5D3 Xplained board + Eclipse + U-Boot or Linux kernel

     

    JTAG을 활용한 debugging이 필요한 경우는, 두말할 것 없이 초기 board를 살리고자 하는 경우(예: u-boot을 수정해서 돌렸는데, console 상으로 아무런 message도 출력되지 않는 경우)나, 전혀 예상치 못한 곳에서 system이 뻗어 버리는 경우(예: chip vendor가 제공한 코드에서 가뭄에 콩나듯 한번씩 죽는 상황) 등을 해결하기 위해서일 것이다(그 밖의 경우는 직접 code를 보는게 답일 수 있다. Debugger가 모든 걸 해결해 주지는 않는다). 
    JTAG debugger로는 Trace32ARM DS-5와 같은 값 비싼 tool도 생각해 볼 수 있겠으나, 현실적으로 접하는데 어려움이 있을 수 있으니, (개인적으로 사용하기에도)저렴하면서도 충분한 효과를 볼 수 있는 방법을 고민해 볼 필요가 있어 보인다.

    <저렴하고, 효율적인 JTAG debugger>
    a) Segger J-Link EDU + Eclipse(gdb)
      => 일반적인 ARM Cortex board에 적용 가능 
    b) OpenOCD 기반 JTAG emulator + Eclipse(gdb)
      => open source임.
    ...


    <목차>
    1. Atmel SAM-ICE 소개
    2. Eclipse Debugging 환경 구축하기
      => ARM cross toolchain, JLink GDB server, Eclipse & plug-ins
    3. JTAG을 이용한 AT91Bootstrap Loader Debugging 절차 소개
    4. JTAG을 이용한 U-Boot Debugging 절차 소개
    5. JTAG을 이용한 Kernel Debugging 절차 소개
    6. KGDB를 이용한 Kernel Debugging 방법 소개


    1. Atmel SAM-ICE 소개
    SAME-ICE(Atmel 장비 전용)는 Segger 사에서 만든 J-Link를 기반으로 만든(OEM) JTAG emulator로, SAM-ICE를 사용하기 위해서는 J-Link website로 부터 관련 s/w를 내려 받아 설치해야만 한다.

    그림 1.1 Atmel SAM-ICE JTAG emulator 외관 

    그림 1.2 Atmel SAM-ICE pinout 

    SAM-ICE의 주요 특징을 열거해 보면 다음과 같다.

    아래 그림 1.3은  SAMA5D3 Xplained board의 주요 device를 그림으로 표현한 것으로, 좌측 하단에 20 pin JTAG port가 있음을 알 수 있다.

    그림 1.3 SAMA5D3 Xplained board - 좌측 하단  JTAG interface(20 pin)

    그림 1.4 SAMA5D3 Xplained board JTAG 회로도(출처 - 참고문헌 [4])

    참고) JTAG과 관련한 사항(debugging 관련 기법 포함)은 필자가 오래전에 작성해 둔 아래 문서를 참고하기 바란다.

    Atmel SAM-ICE(AT91SAM-ICE)는 아래 site에서 150$에 구매가 가능하다.


    2. Eclipse Debugging 환경 구축하기 
    이번 절에서는 SAM-ICE(J-Link)와 Eclipse를 이용하여, ARM target board에서 bootloader & kernel을 debugging하기 위해 필요한 환경 설정에 관하여 정리해 보고자 한다. 아래 그림 2.1은 Host PC(GDB, GDB Server)와 JTAG emulator(J-Link) 및 ARM target board로 구성된 전체 디버깅 환경을 하나의 그림으로 표현해 본 것이다. 이 그림에서 GDB Server는 GDB 명령을 JTAG emulator(= J-Link)가 알아볼 수 있는 형태로 전환하여 전달하는 역할을 담당한다.

    Eclipse -> GDB -> (tcp/ip) -> GDB Server -> JTAG emulator -> JTAG -> Target ARM CPU

    그림 2.1 JTAG을 이용한 Cross Platform Debugging 환경 개요(출처 - 참고문헌[3])

    참고) 위의 구성에서 Eclipse가 필요한 이유는 사용자 친화적인 debugging 환경을 제공해 주기 때문이다.

    이번 절에서 구체적으로 설명할 내용을 정리해 보면 다음과 같다.
    a) cross toolchain(gdb) 설치 방법 소개
    b) SAM-ICE 장치 연결(to SAMA5D3 Xplained board) 방법 소개
    c) JLink GDB server 설치 방법 소개
    d) Eclipse 및 Eclipse GNU ARM plug-in 및 CDT plug-in 설치 방법 소개 

    2.1 ARM Cross Toolchain 설치하기
    본 blog에서는 buildroot 환경을 토대로 debugging을 시도할 예정이다. 따라서, toolchain은 아래의 것을 활용하기로 한다. 물론 다른 toolchain을 사용해도 무방하다.
    buildroot/output/host/usr/bin/arm-linux-*

    위의 toolchain 파일 중, 실제로 debugging을 위해 필요한 파일은 arm-linux-gdb인데, buildroot에서는 이 cross gdb가 기본적으로 disable되어 있으므로, 아래와 같이 Toolchain 메뉴에서 먼저 enable 시켜 주어야만 한다.

    그림 2.2 Buildroot cross gdb 선택 화면

    $ make
    $ cd output/host/usr/bin
    $ ls -l arm-linux-gdb
      => arm-linux-gdb가 생성었는지를 확인해 본다.

    참고) 이 절에서 만든 arm-linux-gdb 파일은 Eclipse에서 사용하게 될 것이다.

    2.2 SAMA5D3 Xplained board에 SAM-ICE 연결하기
    SAM-ICE 장치를 아래 그림과 같이 SAMA5D3 Xplained board에 연결하도록 하자.

    그림 2.3 SAM-ICE를 SAMA5D3 Xplained board에 연결한 모습

    그림 2.4 SAMA5D3 Xplained board의 JTAG port(20 pins)

    주의) 케이블 연결시에는 🔺 모양이 표시된 부분이 반드시 JTAG port의 1번 pin에 연결될 수 있도록 주의하여야 한다. 연결 후에는 JLink tool(얘: JLinkExe)을 사용하여 제대로 연결되었는지를 확인해 볼 수 있다.

    2.3 JLink GDB server 설치하기
    이미 1절에서도 언급했다시피, Atmel SAM-ICE JTAG emulator는 Segger사의 JLink를 기반으로 만들어졌다. 따라서 관련 S/W(J-Link Software and Documentation Pack)Segger website에서 download 받아 사용해야 한다.

    그림 2.5 J-Link Software and Documentation Pack 다운로드

    아래 내용은 64bit Linux Host PC(x86_64)용 S/W를 내려 받아 설치하는 과정을 정리한 것이다(Windows 사용자라면 Windows용 version을 내려 받아 설치하면 된다).

    $ tar xvzf ./JLink_Linux_V612f_x86_64.tgz
    $ cd JLink_Linux_V612f_x86_64
    $ tar cvf 1.tar ./libjlinkarm.so*
    $ sudo tar xvf 1.tar -C /usr/lib; rm 1.tar
    $ sudo cp ./99-jlink.rules /etc/udev/rules.d/
      => PC(Linux)를 재부팅해 주어야 한다.

    PC를 재부팅한 후, SAM-ICE 장비가 제대로 인식되는지를 확인하기 위해서는 아래와 같이 JLinkExe 명령을 실행해 보면 된다.

    그림 2.6 JLinkExe 실행 모습

    또한, 아래와 같이 앞으로 실제로 사용하게 될 JLink GDB server가 제대로 구동되는지도 확인해 보도록 하자.

    $ cd JLink_Linux_V612f_x86_64
    ./JLinkGDBServer -device ATSAMA5D36

    그림 2.7 JLinkGDBServer 실행 모습

    참고) JLinkGDBServer 명령 실행 시, device를 지정해 주지 않았더니, JLinkGDBServer가 죽어 버리는 문제가 있었다. JLinkGDBServer에서 사용 가능한 option으로는 아래와 같은 내용을 생각해 볼 수 있겠다. 관련해서는 참고 문헌 [3]을 참조하기 바란다.
    ./JLinkGDBServer -if JTAG -endian little -device ATSAMA5D36 -select USB -noir -noreset

    그림 2.7을 보면 알 수 있듯이, JLinkGDBServer는 GDB와의 통신을 위해 2331 port를 사용하고 있다. 이 값은 나중에 eclipse 설정 시 필요한 정보이니, 잘 기억해 둘 필요가 있겠다.

    2.4 Eclipse & Plug-in 설치하기
    먼저 Eclipse website로 부터 "Eclipse IDE for C/C++ Developers for Linux"를 내려 받아 설치를 진행하도록 한다. Eclipse 설치와 관련해서는 인터넷에 관련 내용이 많이 알려져 있는 만큼, 여기서는 별도로 설명을 하지는 않겠다(참고로 필자는 Eclipse Neon.2, 4.6.2 version을 설치했음).

     Eclipse가 정상적으로 설치된 경우, 아래와 같이 eclipse 명령을 실행하도록 하자(주의: 아래와 같이 앞 부분에 option을 준 이유는 Eclipse menu가 정상 출력되도록 하기 위해서임).

    chyi@earth:~/eclipse/cpp-neon/eclipse$ UBUNTU_MENUPROXY= ./eclipse

    다음으로 해야할 일은 GNU ARM Eclipse plug-in을 설치하는 일인데, 이와 관련해서는 아래 site 내용을 참조하기 바란다.

    그림 2.8 GNU ARM Plug-in 설치 방법 관련 site 내용

    위의 site 내용을 간단히 요약해 보면, Eclipse Menu 중 Help -> Eclipse Marketplace를 선택한 상태에서, 위의 site의 "Install" 버튼을 Marketplace 팝업 위에 가져다 놓으면(drag-and-drop), 설치가 자동으로 진행되게 된다는 것이다. 아래 그림은 Marketplace를 이용하여 설치하는 과정을 보여준다.

    그림 2.9 Eclipse Marketplace를 이용해 GNU ARM plug-in을 설치하는 모습

    이번에는 CDT(C/C++ Development Tooling) plug-in을 설치할 차례이다. 이를 설치하는 절차는 간단하다. Eclipse Menu -> Help -> Install New Software를 선택한 상태에서 아래 그림과 같이 Work with: 항목을 CDT - http://download.eclipse.org/tools/cdt/releases/9.2으로 선택 한 후, 설치를 진행해 주면 된다.

    그림 2.10 Eclipse CDT plug 설치 모습

    지금까지 설치한 plug-in을 확인하기 위해서는 Eclipse Menu -> Help -> About Eclipse -> Installation Details 버튼을 눌러 결과를 확인해 보기 바란다.

    그림 2.11 Eclipse Plug-in 설치 내용 확인

    이상으로 SAM-ICE 및 Eclipse 디버깅 환경을 위한 모든 준비가 마무리 되었다. 이제 부터는 본격적으로 debugging 절차에 들어가 보도록 하자.


    3. JTAG을 이용한 AT91Bootstrap Loader Debugging 절차 소개
    이번 절에서는 secondary bootloader인 AT91Bootstrap loader를 debugging해 보는 절차를 소개하도록 하겠다.

    a) Project 생성하기
    File -> New -> Makefile Project with Existing Code 선택 후, 아래 그림 3.1과 같이 적절히 값을 입력하여 project를 하나 생성해 본다.

    그림 3.1 AT91Bootstrap loader용 project 생성 모습

    b) build하기
    Project -> Build Project를 선택하여 build를 진행한다.

    그림 3.2 AT91Bootstrap loader project build 모습

    c) Debugging 환경 설정하기
    Run -> Debug Configurations... 선택 후, 좌측 GDB Hardware Debugging을 선택(mouse 우 click) 후, New하여 새로운 debugging 환경을 생성한다. 이후 아래(그림 3.3 ~ 3.6)와 같이 값을 차례로 입력하도록 한다.

    그림 3.3 at91bootstrap_configuration - Main tab 설정

    그림 3.4 at91bootstrap_configuration - Debugger tab 설정


    그림 3.5 at91bootstrap_configuration - Startup tab 설정


    그림 3.6 at91bootstrap_configuration - Common tab 설정

    이제 모든 준비가 끝났다. Debugging을 시작하기 전에, 다시 아래 조건을 새롭게 확인한 상태에서 "Debug" 버튼(위 그림 3.6 우측 하단 버튼)을 눌러 debugging을 시작해 보도록 하자.

    <debugging 시작 조건>
    a) SAMA5D3 Xplained board를 재시작하고, u-boot prompt 상태에서 멈추도록 한다.
    b) ./JLinkGDBServer -device ATSAMA5D36를 다시 시작한다.

    Debug 버튼을 선택한다. 잠시 후, JLink GDB Server가 아래와 같이 동작(elf file을 loading하고, read 명령 등을 실행함)을 시작해야 한다.

    그림 3.7 JLink GDB Server의 동작 모습

    약간의 시간이 경과한 후, 아래와 같은 화면이 뜨면 성공이다.

     그림 3.8 AT91Bootstrap loader debugging 화면(초기 모습)

    <F6> 키를 눌러 다음 단계로 Step Over해 보도록 하자.

    그림 3.9 AT91Bootstrap loader debugging 화면(F6 키 선택 후 모습)

    이후 부터는 본인이 원하는 형태로 다양한 debugging을 시도해 볼 수 있을 것이다.


    4. JTAG을 이용한 U-Boot Debugging 절차 소개
    U-boot을 debugging하는 절차는 AT91bootstrap loader의 그것과 동일하다. 다만, 아래의 차이가 있을 뿐이다.

    Existing Code Location: /home/chyi/Atmel/buildroot/output/build/uboot-linux4sam_5.5
    C/C++ Application명: /home/chyi/Atmel/buildroot/output/build/uboot-linux4sam_5.5/u-boot

    참고) debugging에 사용되는 u-boot 파일의 형식은 ELF(Executable and Linkable Format)인데, ELF는 실행 파일, object 파일, shared library 및 core dump를 위한 표준 파일 형식을 말한다.

    U-boot debugging을 시도하기에 앞서, 대략적은 u-boot bootloader의 코드 흐름을 분석해 보고, debugger로 분석한 내용과 비교해 보는 것도 좋을 듯 싶다.

    $ grep -rl "sama5" *
      => grep으로 u-boot code 중 SAMA5D3 Xplained board와 관련 내용을 추려 본다.
      => 이 밖에도 코드를 이것 저것 살펴 보면서 SAMA5D3 Xplained board와 연관되는 string을 찾아낸 후, 다시 grep을 시도해 보도록 한다.

    코드 4.1 SAMA5D3 Xplained 보드용 u-boot 주요 코드 검색


    대략적인 코드 흐름은 다음과 같다(예상된다).

    arch/arm/cpu/armv7/start.S    ...... 코드 시작 Point !
    |
    V


    코드 4.2 SAMA5D3 Xplained 용 u-boot code 흐름(main code flow)

    아래 내용은 Eclipse로 u-boot을 debugging하는 모습(F6, F5 키를 적절히 선택하면서 다음 단계로 진행)을 보여준다.

    <debugging 시작 조건>
    a) SAMA5D3 Xplained board를 재시작하고, u-boot prompt 상태에서 멈추도록 한다.
    b) ./JLinkGDBServer -device ATSAMA5D36를 다시 시작한다.

    이후 Eclipse를 다시 구동하고, Debug 버튼을 선택한다.

    그림 4.1 u-boot 디버깅 화면 1

    그림 4.2 u-boot 디버깅 화면 2


    그림 4.3 u-boot 디버깅 화면 3

     그림 4.4 u-boot 디버깅 화면 4

    그림 4.5 u-boot 디버깅 화면 5

    <TBD> 현재 breakpoint 명령이 제대로 먹히지 않는 것 같다. 추가 검토가 필요하다.


    5. JTAG을 이용한 Kernel Debugging 절차 소개
    Linux kernel을 debugging하는 절차 역시 AT91bootstrap loader or u-boot bootloader와 동일하다. 차이점을 정리해 보면 다음과 같다.

    Existing Code Location: /home/chyi/Atmel/buildroot/output/build/linux-linux4sam_5.5
    C/C++ Application명: /home/chyi/Atmel/buildroot/output/build/linux-linux4sam_5.5/vmlinux

    또한 linux kernel을 debugging 하기 위해서는 반드시 아래 kernel feature를 enable해 주어야 한다.

    $ make linux-menuconfig

    Kernel hacking -->
        Compile-time checks and compiler options --->
            [*] Compile the kernel with debug info

    그림 5.1 kernel debug feature를 enable 시키는 모습

    Linux kernel의 경우는 size가 매우 크므로, JLinkGDBServer를 통해 vmlinux 파일을 memory로 load하는 시간이 매우 오래 걸린다. 또한 at91bootstrap loader나 u-boot 처럼, debugging 절차가 단순하지도 않다. 따라서 보다 세밀한 접근 방법이 필요해 보인다. 이 부분은 다음 시간에 추가로 검토해 보도록 하겠다.

    <debugging 시작 조건>
    a) SAMA5D3 Xplained board를 재시작하고, u-boot prompt 상태에서 멈추도록 한다.
    b) ./JLinkGDBServer -device ATSAMA5D36를 다시 시작한다.
    c) u-boot을 먼저 debugging한다 - 단, kernel 시작 전에 멈추도록 한다(breakpoint 지정)

    <TBD> 실제 vmlinux debugging 모습 정리해야 함.


    6. KGDB를 이용한 Kernel Debugging 방법 소개
    KGDB를 이용한 kernel debugging 방법은 JTAG이 없을 경우 kernel을 효과적으로 debugging할 수 있는 방법이다. 하지만, 아래와 같은 제약 사항을 안고 있는 것도 사실이다. 이런 제약 사항에도 불구하고, booting 중 특정 device driver에서 문제(panic, Oops)가 발생할 경우, 효과적으로 debugging할 수 있는 방법임에는 틀림이 없을 것 같다. 따라서 이번 절에서는 KGDB를 이용한 kernel debugging 기법을 소개하고자 한다.

    <제약 조건>
    a) bootloader 등 kernel booting 이전 단계에 대해서는 debugging이 불가하다.
    b) kernel의 경우도 serial console이 초기화되기 전까지의 상황에 대해서는 역시 debugging이 불가하다.

    6.1 KGDB를 위해 kernel 재 build하기
    먼저 KGDB를 사용하기 위해서는 몇가지 kernel feature를 enable시켜 주어야 한다.

    $ cd buildroot
    make linux-menuconfig
    Kernel hacking --->
       Compile-time checks and compiler options  --->
           [*] Compile the kernel with debug info

       [*] KGDB: kernel debugger  --->
           <*>   KGDB: use kgdb over the serial console

    그림 6.1 KGDB enable 모습

    make
      => output/build/linux-linux4sam_5.5/vmlinux 파일이 생성될 것임.

    6.2 KGBD 동작 확인하기 
    SAMA5D3 Xplained board의 u-boot prompt 상에서 아래 명령을 실행해 준다(NFS booting을 하기 위함임). NFS booting과 관련해서는 이전 blog(2절)를 참조하기 바란다.

    <SAMA5D3 Xplained target board - u-boot 명령>
    => setenv nb1 'setenv bootargs root=/dev/nfs rw nfsroot=${serverip}:${rootpath} ip=${ipaddr}:${serverip}::${netmask}::eth0:off console=ttyS0,115200 kgdboc=ttyS0,115200 kgdbwait'

    => setenv nb2 'tftp 0x22000000 zImage; tftp 0x21000000 at91-sama5d3_xplained_pda4.dtb; bootz 0x22000000 - 0x21000000'

    => run nb1; run nb2

    그림 6.2 kgdbwait에 의해 부팅 중 대기 상태에서 빠진 모습

    위의 그림에서도 알 수 있듯이 "kgdboc=ttyS0,115200 kgdbwait" command line 명령에 의해, kernel은 아래 message를 마지막으로 출력한 채 대기 상태에 빠지게 된다.

    ...
    console [ttyS0] enabled
    KGDB: Registered I/O driver kgdboc
    KGDB: Waiting for connection from remote gdb...
      <= 이 상태에서 대기하게 됨.
    =============================================

    이 상태에서 Host PC에서 gdb(arm cross gdb)를 이용하여 vmlinux(ELF file)에 대한 debugging을 시도해 보면 다음과 같다.

    <Host PC - gdb 명령>
    export PATH=/home/chyi/Atmel/buildroot/output/host/usr/bin:$PATH
    $ cd build/linux-linux4sam_5.5
    arm-linux-gdb ./vmlinux
    GNU gdb (GDB) 7.11.1
    Copyright (C) 2016 Free Software Foundation, Inc.
    License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
    and "show warranty" for details.
    This GDB was configured as "--host=x86_64-pc-linux-gnu --target=arm-buildroot-linux-gnueabihf".
    Type "show configuration" for configuration details.
    For bug reporting instructions, please see:
    <http://www.gnu.org/software/gdb/bugs/>.
    Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.
    For help, type "help".
    Type "apropos word" to search for commands related to "word"...
    Reading symbols from ./vmlinux...done.
    (gdb) target remote /dev/ttyUSB0    <= kgdb와 /dev/ttyUSB0 포트를 통해 연결
    Remote debugging using /dev/ttyUSB0
    0xc0069a2c in arch_kgdb_breakpoint () at kernel/debug/debug_core.c:1070
    1070 wmb(); /* Sync point before breakpoint */
    (gdb) list
    1065  * the debugger.
    1066  */
    1067 noinline void kgdb_breakpoint(void)
    1068 {
    1069 atomic_inc(&kgdb_setting_breakpoint);
    1070 wmb(); /* Sync point before breakpoint */
    1071 arch_kgdb_breakpoint();
    1072 wmb(); /* Sync point after breakpoint */
    1073 atomic_dec(&kgdb_setting_breakpoint);
    1074 }
    (gdb)

    <TBD> gdb 대신 eclipse로 debugging하는 내용 정리해야 함.


    이상으로 JTAG을 활용한 debugging 기법에 관하여 간략히 정리해 보았다. 내용 중 미비한 부분은 추가로 정리 & 검토해 볼 것을 약속하며 이번 post를 마무리 하고자 한다.


    References
    1. http://www.at91.com/linux4sam/bin/view/Linux4SAM/AT91BootstrapDebugEclipse
    2. AT91SAM-ICE_User_Guide.pdf, Atmel.
    3. https://www.segger.com/admin/uploads/productDocs/UM08001_JLink.pdf
    4. Atmel-11269-32-bit-Cortex-A5-Microcontroller-SAMA5D3-Xplained_User-Guide.pdf, Atmel.
    5. Mastering Embedded Linux Programming, Chris Simmonds, PACKT publishng.

    <Internet>
    6. https://www.element14.com/community/community/designcenter/single-board-computers/riotboard/blog/2014/07/24/debugging-u-boot-on-riotboard-using-eclipse-and-jlink-under-linux
    7. http://electro-don.tistory.com/entry/Eclipse-Yagarto-Segger-JLink-%EB%A1%9C-ARM-%EA%B0%9C%EB%B0%9C%ED%99%98%EA%B2%BD-%EA%B5%AC%EC%B6%95-%EC%A0%95%EB%A6%AC
    8. http://www.sw-at.com/blog/2011/02/11/linux-kernel-development-and-debugging-using-eclipse-cdt/
    9. http://stackoverflow.com/questions/13085211/linux-debugging-with-jtag-arm9at91sam9g25-amontec-openocd-gdb-eclipse
    10. https://boundarydevices.com/debugging-using-segger-j-link-jtag/


    Slowboot