본문 바로가기

임베디드

Buildroot 테스트

최신 stable version인 buildroot-2019.11 다운로드 후 압축을 푼다.

 

아래 절차대로 FoxNux용 BSP(Board Support Package)를 만들어 보았다.

 

<1> board/foxnuxone/ 폴더 만들기

 

<2> board/foxnuxone/boot.cmd 파일 만들기 (u-boot이 자동실행하는 스크립트)

setenv bootargs console=ttyS0,115200 panic=5 console=tty0 rootwait root=/dev/mmcblk0p2 earlyprintk rw
load mmc 0:1 0x41000000 zImage
load mmc 0:1 0x41800000 sun8i-s3-foxnux-one.dtb
bootz 0x41000000 - 0x41800000

 

<3> board/foxnuxone/genimage-foxnuxone.cfg 파일 만들기 (SD 카드용 부팅 이미지에 포함될 파일들의 레이아웃)

image boot.vfat {
        vfat {
                files = {
                        "zImage",
                        "sun8i-s3-foxnux-one.dtb",
                        "boot.scr"
                }
        }
        size = 8M
}

image sdcard.img {
        hdimage {
        }

        partition u-boot {
                in-partition-table = "no"
                image = "u-boot-sunxi-with-spl.bin"
                offset = 8192
                size = 1040384 # 1024KB - 8192
        }

        partition boot {
                partition-type = 0xC
                bootable = "true"
                image = "boot.vfat"
        }

        partition rootfs {
                partition-type = 0x83
                image = "rootfs.ext4"
                size = 0
        }
}

 

<4> board/foxnuxone/readme.txt 만들기 (혹시 남이 보았을때 이해할 수 있도록, 또한 내가 뭘 했는지 기록을 남겨야 한다)

# FoxNux One (Allwinner S3 platform)

Intro
=====

This directory contains a buildroot configuration for building a FoxNux One.

How to build it
===============

Configure Buildroot
-------------------

There is only one LicheePi Zero defconfig files in Buildroot:

  $ make foxnux_one_defconfig

Build the rootfs
----------------

Note: you will need to have access to the network, since Buildroot
will download the packages' sources.

You may now build your rootfs with:

  $ make

(This may take a while, consider getting yourself a coffee ;-) )

Result of the build
-------------------

After building, you should obtain this tree:

    output/images/
    +-- boot.scr
    +-- boot.vfat
    +-- rootfs.ext2
    +-- rootfs.ext4 -> rootfs.ext2
    +-- rootfs.tar
    +-- sdcard.img
    +-- sun8i-s3-foxnux-one.dtb
    +-- u-boot.bin
    +-- u-boot-sunxi-with-spl.bin
    `-- zImage

How to write the SD card
========================

Once the build process is finished you will have an image called
"sdcard.img" in the output/images/ directory.

Copy the bootable "sdcard.img" onto an SD card with "dd":

  $ sudo dd if=output/images/sdcard.img of=/dev/sdX

Alternatively, you can use the Etcher graphical tool to burn the image
to the SD card safely and on any platform:

https://etcher.io/

Once the SD card is burned, insert it into your LicheePi Zero board,
and power it up. Your new system should come up now and start a
console on the UART0 serial port.
~                                 

 

<5> board/foxnuxone/post-build.sh 만들기 ( "chmod +x board/foxnuxone/post-build.sh" 실행가능하도록 속성 변경 필요)

#!/bin/sh
BOARD_DIR="$( dirname "${0}" )"
MKIMAGE="${HOST_DIR}/bin/mkimage"
MKSWAP="${HOST_DIR}/sbin/mkswap"
BOOT_CMD="${BOARD_DIR}/boot.cmd"
BOOT_CMD_H="${BINARIES_DIR}/boot.scr"

# U-Boot script
"${MKIMAGE}" -C none -A arm -T script -d "${BOOT_CMD}" "${BOOT_CMD_H}"

# Swap
sed -i '/^\/swap/d' "${TARGET_DIR}/etc/fstab"
echo "/swap             none            swap    defaults        0       0" >> "${TARGET_DIR}/etc/fstab"

 

<6> board/foxnuxone/post-image.sh 만들기 ("chmod +x board/foxnuxone/post-image.sh" 실행가능하도록 속성 변경 필요)

#!/bin/bash

set -e

BOARD_DIR="$(dirname $0)"
BOARD_NAME="$(basename ${BOARD_DIR})"
GENIMAGE_CFG="${BOARD_DIR}/genimage-${BOARD_NAME}.cfg"
GENIMAGE_TMP="${BUILD_DIR}/genimage.tmp"

rm -rf "${GENIMAGE_TMP}"

genimage                           \
        --rootpath "${TARGET_DIR}"     \
        --tmppath "${GENIMAGE_TMP}"    \
        --inputpath "${BINARIES_DIR}"  \
        --outputpath "${BINARIES_DIR}" \
        --config "${GENIMAGE_CFG}"

exit $?

 

<7> configs/foxnux_one_defconfig 만들기

# Target options
BR2_arm=y
BR2_cortex_a7=y
BR2_ARM_FPU_VFPV4=y

# Toolchain
# External Linaro ARM 2017.11 toolchain
BR2_TOOLCHAIN_EXTERNAL=y

# System configuration
BR2_TARGET_GENERIC_HOSTNAME="foxnux-one"
BR2_TARGET_GENERIC_ISSUE="Welcome to Buildroot for the FoxNux One"
BR2_TARGET_GENERIC_ROOT_PASSWD="foxnux"
# Run a getty (login prompt) after boot on ttyS0 @ 115200 bps
BR2_TARGET_GENERIC_GETTY_PORT="ttyS0"
BR2_TARGET_GENERIC_GETTY_BAUDRATE_115200=y
# Custom scripts for image creation
BR2_ROOTFS_POST_BUILD_SCRIPT="board/foxnuxone/post-build.sh"
BR2_ROOTFS_POST_IMAGE_SCRIPT="board/foxnuxone/post-image.sh"

# Kernel
# Custom 5.5 kernel from FoxNux Github repository
BR2_LINUX_KERNEL=y
BR2_LINUX_KERNEL_CUSTOM_GIT=y
BR2_LINUX_KERNEL_CUSTOM_REPO_URL="https://github.com/foxnux/linux"
BR2_LINUX_KERNEL_CUSTOM_REPO_VERSION="c94a39f556bcb41152b3f5049f27f480fcebfa8b"
# In-tree kernel configuration
BR2_LINUX_KERNEL_DEFCONFIG="foxnux"
# AllWinner S3-based DTS
BR2_LINUX_KERNEL_DTS_SUPPORT=y
BR2_LINUX_KERNEL_INTREE_DTS_NAME="sun8i-s3-foxnux-one"

# Target packages

# E2fsprogs package for resize2fs
BR2_PACKAGE_E2FSPROGS=y
BR2_PACKAGE_E2FSPROGS_RESIZE2FS=y

# RTL8723BS package for Wi-Fi firmware
# BR2_PACKAGE_RTL8723BS=y

# Dhcpcd package DHCP client for Wi-Fi
BR2_PACKAGE_DHCPCD=y

# WPA_supplicant package for Wi-Fi Authentication
# BR2_PACKAGE_WPA_SUPPLICANT=y
# BR2_PACKAGE_WPA_SUPPLICANT_AUTOSCAN=y

# Filesystem images
BR2_TARGET_ROOTFS_EXT2=y
BR2_TARGET_ROOTFS_EXT2_4=y

# Bootloaders
# Custom U-Boot from Lichee-Pi Github repository
BR2_TARGET_UBOOT=y
BR2_TARGET_UBOOT_BUILD_SYSTEM_KCONFIG=y
BR2_TARGET_UBOOT_CUSTOM_GIT=y
BR2_TARGET_UBOOT_CUSTOM_REPO_URL="https://github.com/foxnux/u-boot"
BR2_TARGET_UBOOT_CUSTOM_REPO_VERSION="s3-foxnux"
BR2_TARGET_UBOOT_BOARD_DEFCONFIG="foxnux_S3"
BR2_TARGET_UBOOT_FORMAT_CUSTOM=y
BR2_TARGET_UBOOT_FORMAT_CUSTOM_NAME="u-boot-sunxi-with-spl.bin"

# Host utilities
# Required host utilities for building an SDCard image
BR2_PACKAGE_HOST_DOSFSTOOLS=y
BR2_PACKAGE_HOST_DTC=y
BR2_PACKAGE_HOST_GENIMAGE=y
BR2_PACKAGE_HOST_MTOOLS=y
BR2_PACKAGE_HOST_UBOOT_TOOLS=y

 

빌드 명령은 간단한데.. 최종 이미지를 얻는데까지 삽질이 좀 있었다.

dtb 이름 오타와 post-build, post-image 스크립트 속성 변경등등.... 

make foxnux_one_defconfig
make

 

서버에서 빌드가 끝나면 아래 명령을 이용하여 local에 이미지 파일을 복사하여 SD카드에 flashing 한다.

scp odroider@192.168.0.251:~/buildroot-2019.11/output/images/sdcard.img .

 

부팅은 잘 된다. 10초 이내에 어플까지 기동시킬 수 있을것 같다.

툴체인, 부트로더, 커널, 루트파일 시스템까지 자동으로 패치하고 빌드하고 최종 SD카드용 이미지까지 만들어낸다.

빌드루트의 "Making Embedded Linux Easy" 캐치프레이가 좋다. 

오래전에는 디렉토리 구조를 하나하나 만들고, Busybox 빌드해서 넣고, 설정 파일 만들고, 디바이스 노드 만들고, 루프백장치 파일에서 완전 수동으로 작업했었는데, 이제는 양산용 이미지를 한방에 만들수 있다. 정말 편리한 세상이다.

 

아직 자동로그인이 안된다.. 시리얼 콘솔로 자동로그인? 아님 LCD 콘솔로 자동로그인?

좀 더 공부해 보자!!

 

LCD 콘솔은 자동 로그인이 되도록 하였다.

먼저 Root filesystem overlay에 대해 알아야 한다. 오버레이는 마지막 빌드 프로세스 단계에서 Buildroot 루트 파일시스템의 최상위에 복사되는 간단한 디렉토리 구조이다. 실행파일, 라이브러리, 그 외 포함하고 싶은 것들을 추가할 수 있다.

커널 부팅 직후에 실행되는 inittab을 수정하여 자동 로그인 기능을 구현해 보자.

 

오버레이 디렉토리를 만들고 빌드가 완료된 target 디렉토리에서 inittab 파일을 복사한다.

mkdir board/foxnuxone/rootfs_overlay
mkdir board/foxnuxone/rootfs_overlay/etc
cp output/target/etc/inittab board/foxnuxone/rootfs_overlay/etc/inittab

inittab 파일의 32번째 줄에 "console::respawn:-/bin/sh"을 추가한다. 그 결과는 아래와 같다.

LCD default console에 로그인 절차없이 바로 shell prompt가 뜨도록 하는 명령어다.

# /etc/inittab
#
# Copyright (C) 2001 Erik Andersen <andersen@codepoet.org>
#
# Note: BusyBox init doesn't support runlevels.  The runlevels field is
# completely ignored by BusyBox init. If you want runlevels, use
# sysvinit.
#
# Format for each entry: <id>:<runlevels>:<action>:<process>
#
# id        == tty to run on, or empty for /dev/console
# runlevels == ignored
# action    == one of sysinit, respawn, askfirst, wait, and once
# process   == program to run

# Startup the system
::sysinit:/bin/mount -t proc proc /proc
::sysinit:/bin/mount -o remount,rw /
::sysinit:/bin/mkdir -p /dev/pts /dev/shm
::sysinit:/bin/mount -a
::sysinit:/sbin/swapon -a
null::sysinit:/bin/ln -sf /proc/self/fd /dev/fd
null::sysinit:/bin/ln -sf /proc/self/fd/0 /dev/stdin
null::sysinit:/bin/ln -sf /proc/self/fd/1 /dev/stdout
null::sysinit:/bin/ln -sf /proc/self/fd/2 /dev/stderr
::sysinit:/bin/hostname -F /etc/hostname
# now run any rc scripts
::sysinit:/etc/init.d/rcS

# Put a getty on the serial port
ttyS0::respawn:/sbin/getty -L  ttyS0 115200 vt100 # GENERIC_SERIAL
console::respawn:-/bin/sh

# Stuff to do for the 3-finger salute
#::ctrlaltdel:/sbin/reboot

# Stuff to do before rebooting
::shutdown:/etc/init.d/rcK
::shutdown:/sbin/swapoff -a
::shutdown:/bin/umount -a -r

 

make menuconfig를 실행하고, System configuration의 Root filesystem overlay directories항목에 "board/foxnuxone/rootfs_overlay"를 입력하고 저장한다.

.config 파일이 아래와 같이 변경되었다면 정상이다.

BR2_ROOTFS_OVERLAY="board/foxnuxone/rootfs_overlay"

빌드루트 컴파일하고 SD카드에 이미지를 다시 기록하고 정상 동작함을 확인하였다. 10초 부팅은 무난해 보인다.

 

다음에는 GUI 어플리케이션을 올려보아야 겠다. Qt5 예제를 돌려보았다.

overlay 폴더에 /etc/init.d/S00myapp이라는 파일을 만들고 아래 내용을 넣어 시스템이 부팅하면서 자동으로 Qt 예제가 실행되도록 하였다.

#!/bin/sh
export QT_QPA_FONTDIR=/usr/share/fonts/ttf-bitstream-vera
export QT_QPA_PLATFORM=linuxfb:tty=/dev/fb0
/usr/lib/qt/examples/widgets/touch/pinchzoom/pinchzoom &

 

그런데 16초(우분투)에서 10초(빌드루트) 정도로 부팅시간이 줄었지만, 이제는 10여초의 부팅시간이 많이 답답하게 느껴진다.

최종적으로 부팅시간을 5초 이내로 줄일 수 있을까? 아래 내용을 참고해 보자.

https://www.qt.io/blog/2016/05/25/fast-booting-qt-devices-part-3-optimizing-system-image

저렇게만 빨리 부팅이 될수 있다면 MCU대신 MPU + Linux 사용에 대한 요구가 훨씬 많아질 것이다.

 

u-boot에서 falcon 모드로 u-boot.bin대신하여 kernel+dtb 이미지를 바로 읽어서 부팅하면 1~2초 정도 줄어들까?

현재 커널 부팅은 2~3초 정도라서 단축할 부분이 얼마나 있을지 모르겠다.

커널 부팅 직후 root file system을 마운트하는데 시간이 많이 걸리는것 같다. 이 부분을 눈여겨 보아햐 하겠다.

 

시리얼 포트에서 나오는 메시지를 분석해서 부팅 구간별로 소요 시간 프로파일링 하는 방법도 있다. 

https://embexus.com/2017/05/16/embedded-linux-fast-boot-techniques/

 

부트로더 1초, 커널 2초, 어플구동 1초 = 대략 4~5초 이내에 어플까지 시작된다면 아주 매력적일것 같다.

'임베디드' 카테고리의 다른 글

SPI 포트 기능 테스트  (3) 2020.01.11
UART 포트 기능 테스트  (0) 2020.01.10
ADC 키패드 입력 테스트  (0) 2020.01.06
카메라 입력 테스트  (0) 2020.01.03
동영상 재생 테스트  (0) 2020.01.02