blog/content/posts/building-a-bsp.md

5.6 KiB

+++ title = "Building a Board Support Package using Yocto" date = 2019-01-16 +++

This post assumes a basic working knowledge of Yocto/OpenEmbedded.

At the current workplace, for the project, am responsible for everything be it app, kernel configuration, custom drivers or existing driver enhancements or setting up the complete board support package for the system. While having worked on OpenEmbedded/Yocto at the previous company, had no experience setting up a complete BSP. This meant having a custom meta layer for this project along with the required layers for Yocto to work and also the vendor specific layer which in this case was Xilinx, but, could be any for that matter. Accordingly, one would include meta-samsung, meta-ti or meta-intel etc.

One of the first decisions to make was regarding the flashing process. There was an eMMC on-board and also a SD card. It's possible to have one's own script and then use u-boot's mmc write functions to format and write to the MMC. However, decided to go for the easier genimage approach. Yocto build system builds the relevant components and can pack it in a single image using a configuration like below.

image boot.vfat {
    vfat {
        files = {
            "BOOT.bin",
            "emergency.ub",
            "image.ub",
            "system.dtb",
            "Image"
        }
    }
    size = 128M
}

image ged.img {
    hdimage {
    }

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

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

This gives a single file with an img extension which can be used to flash the SD card or eMMC using the dd command.

Now, to use Yocto requires the use of several meta layers to be put together. One way is to use the repo tool which is also used in the Android world. However, there was a need for something more along with Docker integration. Wondering if someone has already done this kind of work, went searching on Google and came across yoe-distro.

yoe-distro provided a perfect template on which to base the work on. Only need integrate the layers required and it does the rest. Docker integration is also included. Now, in case you are wondering why Docker is required, Yocto/ OpenEmbedded builds can be sensitive to host distribution setup. Also in this case, Xilinx's support provided through Yocto would not build on Ubuntu 18.04. Downgrading would result in waste of time and isn't actually a solution. Even if worked on Ubuntu 18.04, future upgrades may result in the build not working.

Docker solves this problem by providing a sandboxed environment, think of chroot or BSD jails simplified and on steroids. So ended up integrating the vendor specific meta layers and added custom layer to provide customisations. Getting started with Yocto definitely requires putting in some effort, but, adding customisations and stuff is lot easy or at least has been easy for what was being done.

For example, there is a need to build the kernel from source, since there are some custom patches and if nothing else custom device trees which enable support for custom Xilinx IP core drivers are needed. One problem was internally the use of Atlassian Stash and trying to even just clone the source tree from Stash requires authentication. Wasn't sure how to do this in Yocto while without exposing SSH keys or account information. yoe-distro setup helped here.

The linux source is added as a git submodule just like the meta layers and then a custom recipe builds that.

SRC_URI = "git://${TOPDIR}/sources/ged4k-linux-kernel;protocol=file;branch=ged4k_v2018.2"
SRCREV = "fbec50e15d7b04f44690eb115d2cddd4423e0326"

SRC_URI_append += " file://defconfig \
                    file://fragment.cfg \
                    "

FILESEXTRAPATHS_prepend := "${THISDIR}/files:"

As can be seen, the protocol specified isn't git, but file. Another simpler example is u-boot, where there is a need to apply a custom patch on top of Xilinx's u-boot source and just the below in a recipe appending the original one.

FILESEXTRAPATHS_prepend := "${THISDIR}/files:"
SRC_URI_append = "\
    file://0001-configs-xilinx_zynqmp-Config-SD-and-eMMC-boot-for-GE.patch \
"

Also had to include a rl78flash program which wasn't provided by any of the meta layers in Yocto and even that was easy. Looked at how some other recipes were written and came up with this and it just worked.

SUMMARY = "RL78 Flash Tool"
DESCRIPTION = "Software to program RL78 microcontrollers via Serial Bootloader"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"

SRCREV = "d0f5f05fbbce0a278658ca0caf67f293dcd26ee3"
SRC_URI = "git://github.com/msalau/rl78flash.git;protocol=https;branch=master \
          file://rl78flash.patch \
          "

S = "${WORKDIR}/git"

EXTRA_OEMAKE = "'CC=${CC}' 'CFLAGS=${CFLAGS}'"

do_compile() {
    oe_runmake
}

do_install() {
    install -d ${D}${bindir}
    install -m 0755 ${WORKDIR}/git/rl78flash ${D}${bindir}
}

Yocto by default uses sysvinit, however, wanted to use systemd as init. Adding the below to local.conf makes systemd as the init system.

DISTRO_FEATURES_append = " systemd"
DISTRO_FEATURES_BACKFILL_CONSIDERED += "sysvinit"
VIRTUAL-RUNTIME_init_manager = "systemd"
VIRTUAL-RUNTIME_initscripts = "systemd-compat-units"

It has been a lot fun learning how to put together a board support package and Yocto has given so much flexibility.