BeaglePlay: Part 1 – Building a base image using Yocto

The out-of-the-box experience of the BeaglePlay is pretty awesome with the full-blown Debian image and all. Wait – what is the BeaglePlay, you ask? Check out this post that talks about all things good and not-so-good about this new SBC.

About the BeaglePlay: At the heart of the BeaglePlay is TI’s AM625 processor. It is a powerful multi-core processor powered by 4x Cortex-A53 cores, an impressive mid-end GPU from Imagination Technologies, and 1x Cortex-M4F CPU to take care of real-time tasks.
On the connectivity front, the BeaglePlay provides ethernet, Wi-Fi, BLE and even sub-1 GHz connectivity.

The on-board eMMC comes pre-loaded with a Debian image which is pretty feature-rich in itself and you may never need to change it as such.

But what’s the fun in that? Let us build our own basic Yocto image for the BeaglePlay.

Wait… what’s Yocto?

If you already know what Yocto is and have used it, skip right ahead to the next section. If not, read on!

Since you have not skipped this section, you are probably just starting off with Yocto or are curious to know more. Check out this 10-part series of posts I have written about Yocto that starts from the very basics and explores key concepts that a developer needs to know.

Since Yocto is a popular build system used by embedded linux developers (professionals as well as hobbyists alike), getting support from the community during the development process is easy.

But the developer’s experience can easily be marred by lack of software maintenance leading to incompatibility with newer Yocto versions. Fortunately, Texas Instruments is one of the best at maintaining linux software for their processors – so that’s a relief.

So, what do we need to build our Yocto image?

An advice before we start

Yocto builds are resource-intensive – in terms of time, processing power, memory and patience! From my experience, try to meet the below requirements for a good experience.

  • RAM – Anything less than 16 GB of RAM on your build PC is going to be a headache – stuff will build… but it will fail a lot first throwing weird errors as the build processes will run out of RAM quite frequently. On top of the RAM, you can choose to have a large swap area (say, 20 GB) but that is going to be slow as well.
  • Hard disk space – At least 150 GB of hard disk space on the build PC is highly recommended while starting off. You will be surprised how large some of the build artifacts are for some frameworks like Wayland Weston, NodeJS, etc.
  • CPU specification – Newer the processor, the better it is. More the number of cores in the processor, the better it is.

PRO-TIP: If you are doing this on an old computer which you can’t upgrade (I am using an 8 GB DDR3 + 5th gen i5 machine from 2015 ), it is a good idea to reduce the number of parallel threads so as to not run out of RAM. It will increase the build time by 2-3 times but ensures that the build does not fail.
This thread has more info – change the settings to 1.

Yocto pre-requisites

Yocto requires some packages to be already present on the build PC. If they are not present, it will tell you what is missing and you can install it in most cases. We will be using the Kirkstone version.

https://docs.yoctoproject.org/4.0.11/ref-manual/system-requirements.html

PRO-TIP: Installing these pre-requisite packages beforehand will go a long way in ensuring builds don’t break when you are grabbing that much-needed sleep while the build system is baking the recipes you ordered it to.

Baking the image!

There is an EASY way and a HARD way to build your image.

The EASY way – You should go for this method if you already know enough about Yocto and just want an image to work with and customise later on if needed.

The HARD way – If the goal is to learn a bit more about how Yocto builds happen, to understand where some of the magic happens, how the bitbake layers are configured, identifying and satisfying dependencies, etc. – you should try out this method.

NOTE: Most of the steps here covered in the HARD way are actually generic and can be easily re-applied for different processors and hardware based on them.

Let us look at the EASY way first.

The EASY way – Using TI’s documentation

TI maintains a linux SDK for developers to quickly develop software for their processors. This SDK is updated from time-to-time and keeps pace with the latest linux kernel LTS versions. As a part of this SDK documentation, there is a guide that talks about how to build an image using Yocto. One can simply follow the guide and generate the image they need. Most of the setup stuff is automated thru scripts – thus simplifying your life. Depending on who you are, that may or may not be a good thing!

If a working image is all you need, just follow this well-written guide.

The HARD way – Setting up the build system manually

Are you still reading? Good. Let us take the harder route to get to an image. We will divide this process into several steps as below.

Step 1 – Reconnaissance

The very first (and perhaps the most important step of all) to ensure a working build in the very first go is getting a clear idea of the some key aspects of the build mentioned below.

  • Yocto version – Identifying the right Yocto version so that existing recipes (if any) don’t break. There may be minor (eg: recipe syntax) or major (eg: linux kernel version) differences between Yocto versions. If you have an existing recipe or layer that is written for a particular version, it is a good idea to choose that rather than going for the latest always. Some examples are warrior, zeus, thud, sumo, dunfell, kirkstone, etc.

    For this build, we will choose the kirkstone version.
  • Distribution – Poky is the most commonly used distribution for Yocto. Simply put, a distribution defines top-level settings for your build system. For example, features like bluetooth, wifi, keyboard, etc. are distribution-specific features that can be enabled across all images that you plan to build.

    For this build, the distribution that we will use is poky.
    NOTE: TI SDK uses the arago distribution.
  • Layers – This is perhaps the most-defining step of the entire process. Identifying the layers needed for the development along with their version (often having the same name as the Yocto version) is key to getting stuff to build successfully.

    For this build, to get an idea of the layers that are necessary for us, we will refer to the readme inside the meta-ti layer to get an idea of what its dependencies are and then we will add those layers to our bitbake configuration.
  • Image – We need to zero down on the image we want to build. It is a good practice to start off with the most basic image one can build. This allows us to confirm that the build system works and its dependencies are met as well as that the image formats generated by the build system are usable (eg: WIC format, stand-alone binaries, etc.).

    For this build, we will use the core-image-minimal which is the most basic bootable image supported by poky.
  • Toolchain (optional) – If you are going to use a specific toolchain, this would be the right time to identify which one you want to use and what specific version you need. This is optional if you are using poky as it has its own toolchain.

    For this build, we will use the poky toolchain itself.

This concludes our reconnaissance. Rest of the steps are more execution-oriented.

Step 2 – Build system creation

We now know exactly what we want in our build system. Let us now set up the build system based on the inputs obtained during our reconnaissance.

  • Create a working directory – To keep things clean, we will first create a working directory and then place all the stuff into it.
$ mkdir workdir
$ cd workdir
  • Get poky – Since we will be using poky as our distribution, we need to get poky sources. Throughout this process, note that we will be cloning just the kirkstone branch. If you so please, you can clone the entire repo first and then check out the kirkstone branch.
$ git clone -b kirkstone https://git.yoctoproject.org/poky
  • Get the layer dependencies – A quick look at the readme inside the meta-ti-bsp layer tells us that it depends on openembedded-core and meta-arm. However, it is important to note that poky already has openembedded-core integrated. So, we don’t need to clone it again. Let us get the other dependency i.e. meta-arm.

WARNING: We see that although openembedded-core is a documented dependency, we don’t clone it. If you do clone it and try to add it in the layer configuration, you run the risk of duplicated BBFILES settings.

$ git clone -b kirkstone git://git.yoctoproject.org/meta-arm
  • Get meta-ti – Now that we have all the dependencies in place, let us get meta-ti from TI’s git server.
$ git clone -b kirkstone https://git.ti.com/cgit/arago-project/meta-ti
  • Create build environment – To create our build environment, we will use the handy oe-init-build-env script located inside poky.
$ cd poky
$ source oe-init-build-env build-ti
# If there are no errors, you have successfully created your 
# build environment - there is also helpful text about what 
# targets are available to you, etc.

Step 3 – Build system customization

We now have a build system that we can use. Let us now customize it for building our intended image i.e. core-image-minimal for the BeaglePlay!

  • Configure layers – Inside the build-ti folder, there is a file named bblayers.conf inside the conf folder. The simplest option is to add our layers there one by one such that the file entries look like below.
    NOTE: The first three entries would be present already – you just have to add the next three layers. You need to modify the below to reflect the paths in your PC.
...
...
BBLAYERS ?= " \
  /home/shashank/work/yocto/poky/meta \
  /home/shashank/work/yocto/poky/meta-poky \
  /home/shashank/work/yocto/poky/meta-yocto-bsp \
  /home/shashank/work/yocto/meta-arm/meta-arm-toolchain \
  /home/shashank/work/yocto/meta-arm/meta-arm \
  /home/shashank/work/yocto/meta-ti/meta-ti-bsp \
  "

PRO-TIP: You could also use a handy command-line tool called bitbake-layers to add, remove and show current layers. This has been discussed in this post about Yocto development.

  • Specify the BeaglePlay as the target – We will now modify the local.conf file inside the conf folder to specify that the build target is the BeaglePlay. The exact name to be used can be seen from the list of machines supported by meta-ti – see the meta-ti/meta-ti-bsp/conf/machine folder.

Let us now specify that our target is beagleplay. Open the conf/local.conf file and make the edit as below.

...
...
#MACHINE ??= "qemux86-64"
MACHINE ??= "beagleplay"
...
...

Step 4 – Build time!

Now, let us build. If there are any issues with layer configuration or missing packages on the host or incomplete locale configuration, you will encounter them now. To try the build, execute the below.

NOTE: The first command below will only try to fetch the sources first. If you have an unstable internet connection, it is a good idea to download all the sources first and then proceed for the build by dropping the --runall=fetch argument.

$ bitbake core-image-minimal --runall=fetch
...
...
...
$ bitbake core-image-minimal

If all goes well, you should expect to see console output like the below. Some parts are omitted – only the important aspects are mentioned below.

...
...
Build Configuration (mc:default):
BB_VERSION           = "2.0.0"
BUILD_SYS            = "x86_64-linux"
NATIVELSBSTRING      = "ubuntu-20.04"
TARGET_SYS           = "aarch64-poky-linux"
MACHINE              = "beagleplay"
DISTRO               = "poky"
DISTRO_VERSION       = "4.0.12"
TUNE_FEATURES        = "aarch64"
TARGET_FPU           = ""
meta                 
meta-poky            
meta-yocto-bsp       = "kirkstone:d6b8790370500b99ca11f0d8a05c39b661ab2ba6"
meta-arm-toolchain   
meta-arm             = "kirkstone:c39bb4ce3b60b73d35c5fb06af012432e70d6b38"
meta-ti-bsp          = "kirkstone:7e1a048bc0f116842a6076cd284d80dc0eae01f8"
...
...
Build Configuration:
BB_VERSION           = "2.0.0"
BUILD_SYS            = "x86_64-linux"
NATIVELSBSTRING      = "ubuntu-20.04"
TARGET_SYS           = "arm-poky-linux-gnueabi"
MACHINE              = "beagleplay-k3r5"
DISTRO               = "poky"
DISTRO_VERSION       = "4.0.12"
TUNE_FEATURES        = "arm armv7a vfp thumb callconvention-hard"
TARGET_FPU           = "hard"
meta                 
meta-poky            
meta-yocto-bsp       = "kirkstone:d6b8790370500b99ca11f0d8a05c39b661ab2ba6"
meta-arm-toolchain   
meta-arm             = "kirkstone:c39bb4ce3b60b73d35c5fb06af012432e70d6b38"
meta-ti-bsp          = "kirkstone:7e1a048bc0f116842a6076cd284d80dc0eae01f8"
...
...

Although we specified only the beagleplay machine, we also see another machine called beagleplay-k3r5 in our logs. This is because meta-ti has multiconfig configured – the name of the additional machine for multiconfig is of the format <base-machine>-k3r5. More on this in a future post!

Step 5 – Running the image!

At the end of the rather lengthy build process, you would have a freshly baked SD card image ready for use. Use your favourite SD card writer tool (mine is Balena Etcher) to write this image and plug it into your BeaglePlay.

Connect your PC to the DEBUG UART console (J6 on the BeaglePlay), plug in the SD card, power on the BeaglePlay and soon enough, you should see your image boot to the login prompt.

Good job – you have baked your first Yocto image for the BeaglePlay!

Summary

In this post, we saw how we can build a Poky image for the BeaglePlay.

TI’s SDK uses the Arago distribution which is different from Poky. If you already have an existing setup based on Poky (eg: you did a build on Raspberry Pi or the Jupiter Nano) and wish to reuse it – you can as demonstrated by the generic process above.

Lastly, we were able to build and test a basic image that we can use as a base for future developments.

3 thoughts on “BeaglePlay: Part 1 – Building a base image using Yocto

  1. This is really helpful, and I’m looking forward to part 2. Though after following these steps I’m having trouble understanding where I need to go to get output to the hdmi display. Right now I only have access to the new system across serial.

    I wonder if you could point in the right direction on where I should go to build off of this.

  2. Hello, very helpfull – I build the image, it boots up but neither the serial console or the eth0 comes up. What am I missing?

  3. I was using TARGET_SYS = “arm-poky-eabi”, whereas you use TARGET_SYS = “arm-poky-linux-gnueabi”. If I change to that, the python3_3.10.13 recipe fails during config.
    I use the latest on the kirkstone branch. Any ideas what is wrong?

Leave a Reply