blog/posts/2019-01-16-building-a-bsp.md

157 lines
5.7 KiB
Markdown
Raw Permalink Normal View History

---
author: Sanchayan Maity
title: Building a Board Support Package using Yocto
tags: linux, yocto, openembedded
---
This post assumes a basic working knowledge of Yocto/OpenEmbedded.
At my current workplace, for the project I am handling I am responsible for
everything be it application, kernel configuration, custom drivers or existing
driver enhancements or setting up the complete board support package for the
system I am working on. I had worked on OpenEmbedded/Yocto at my previous
company however, 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 and so on.
One of the first decisions I had to make was regarding the flashing process. We
had an eMMC on-board and also a SD card. I could have my own script and using
u-boot's "mmc write" functions to format and write to the MMC. However, I decided
to go the easier [genimage](https://github.com/pengutronix/genimage) approach.
Yocto build system will build the relevant components and I could pack it in
a single image using a configuration like below.
```bash
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 I can use 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,
I felt like I wanted something more along with Docker integration. Wondering if
someone has already done this kind of work, I went searching on Google and came
across [yoe-distro](https://github.com/YoeDistro/yoe-distro).
yoe-distro provided a perfect template on which to base my work on. I only need
integrate the layers I want and it could provide the rest. Docker integration
was also included. Now, in case you are wondering why Docker is required, Yocto/
OpenEmbedded builds can be quite sensitive to host distribution setup. Also in
my case, Xilinx's support provided through Yocto would not build on Ubuntu 18.04
which I am running at work. Downgrading would result in waste of time and is not
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 me a sandboxed environment, think of
chroot or BSD jails simplified and on steroids. So I ended up integrating the
vendor specific meta layers and added my own layer to provide customisations.
Getting started with Yocto definitely requires putting in some effort, but,
once you understand how to use it, adding customisations and stuff is lot easy
or atleast has been quite easy for what I am doing.
For example, I definitely need to build the kernel from my own source tree, since
I have some patches of my own and if nothing else my own custom device trees
which enable support for custom Xilinx IP core drivers. One problem I had was
we internally use stash and trying to even just clone the source tree from stash
requires authentication. I was not sure how to do this in Yocto while without
exposing my ssh keys or account information. yoe-distro's setup helped here.
The linux source is added as a submodule just like the meta layers and then a
custom recipe builds that.
```bash
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:"
```
You can see the protocol specified is not git, but file. Another simpler example
is u-boot, where I just needed to apply my own patch on top of Xilinx's u-boot
source and just the below in a recipe appending the original one.
```bash
FILESEXTRAPATHS_prepend := "${THISDIR}/files:"
SRC_URI_append = "\
file://0001-configs-xilinx_zynqmp-Config-SD-and-eMMC-boot-for-GE.patch \
"
```
I had to include a rl78flash program which was not provided by any of the meta
layers in Yocto and even that was easy. I looked at how some other recipes
were written and came up with this and it just worked.
```bash
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, I wanted systemd as init. Adding the
below to local.conf will make systemd as init system.
```bash
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.