Yocto: Part 4 – Building a basic image for Raspberry Pi

In the previous posts, we talked about Yocto basics and setup of a host followed by a basic image build. In case you missed those posts, here they are!

Yocto: Part 1 – A Definitive Introduction

Yocto: Part 2 – Setting up Ubuntu host

Yocto: Part 3 – Build & run your first ever image

In this post, we will see how to take our work done in Part 3 forward by building a test image for the Raspberry Pi. If you are not aware of the Raspberry Pi, check out this YouTube playlist that gives a crash course into the Raspberry Pi ecosystem and basic usage.

This post assumes that a build directory has already been created. If not, please head to this post and perform the steps detailed there but stop after creating your build directory.

All set? Let’s start building an image for the Raspberry Pi 4.

Set up the build environment

Let us assume that the name of your build directory is build-rpi. Set it up by executing the following command in your poky directory.

$ source oe-init-build-env build-rpi

NOTE: Replace build-rpi with the name of your build directory.

Bitbake layer configuration for Raspberry Pi

When we built the image for QEMU, we did not have to do any layer configuration as the poky distribution itself ships with the necessary recipes for the particular QEMU machine. For instance, our machine in the last build was qemux86-64.

From the readme.md document of the meta-raspberrypi layer, we need at least meta-openembedded layer and probably some more depending on the features needed in the image. The recipes within meta-openembedded enable builds for embedded architectures like ARM, MIPS, etc. Do you need a quick refresher on Open-Embedded, recipes, etc.? Check out this crisp introduction to Yocto!

For our build, we will also add other layers necessary for networking, python, multimedia, etc. We will first download these and then add to our build configuration.

Downloading necessary layers

Let us now download the layers. It is considered a good practice to have the meta- layers in the same directory as poky so that multiple build directories can use the same. For our system, the folder structure looks something like this:

  • yocto
    • poky
    • << new layers that we will download now >>

We will first cd into the yocto directory.

$ cd ../..
$ pwd
<your yocto directory>/yocto

Let us now download the Open-Embedded source code and check out the release we want. As we saw in our last post, we are using the dunfell release.

$ git clone git://git.openembedded.org/meta-openembedded -b dunfell

Let us now download the meta-raspberrypi layer source code. This layer contains all the recipes that are necessary to build basic images for the Raspberry Pi series of boards. The layering concept we discussed in the first post is seen in action here! The meta-raspberrypi layer will contain the appropriate recipes for the kernel, drivers, configuration, etc. that will override those in the corresponding poky and meta-openembedded recipes. For example: the linux kernel configuration.

$ git clone git://git.yoctoproject.org/meta-raspberrypi -b dunfell

We have downloaded the necessary layers. Our folder structure now looks something like this.

  • yocto
    • poky
    • meta-raspberrypi
    • meta-openembedded
      • meta-oe
      • meta-networking
      • meta-python
      • meta-multimedia

Adding layer to build using bitbake commands

You can manually modify the bitbake layer configuration by editing the conf/bblayers.conf file in your active build directory. However, such an approach is prone to syntax errors which may lead to failed builds due to parser failure.

The best approach is to use the handy bitbake-layers command. To add the necessary layers to the build, execute the below from your yocto directory.

$ bitbake-layers add-layer ./meta-openembedded
$ bitbake-layers add-layer ./meta-raspberrypi
$ bitbake-layers add-layer ./meta-openembedded/meta-oe
$ bitbake-layers add-layer ./meta-openembedded/meta-python
$ bitbake-layers add-layer ./meta-openembedded/meta-networking
$ bitbake-layers add-layer ./meta-openembedded/meta-multimedia

You can now check that your layer configuration is updated by executing the below.

$ bitbake-layers show-layers

Choose the machine and the image

Image recipes are .bb files that contain complete details of how the image for that particular machine is to be built. Machine names can be found in the respective meta- layers.

Choose the machine

The machine names supported by the meta-raspberrypi layer can be seen in the meta-raspberrypi/conf/machine directory. Each .conf file is the machine configuration – the name of the machine is the name of the file (without the .conf file extension). You can list the machines supported in meta-raspberrypi by executing the below command from the yocto directory.

$ ls meta-raspberrypi/conf/machine

We want to build an image for Raspberry Pi 4, we will use the machine name as raspberrypi4.

Choose the image

To see the images that you can build, see the contents of the meta-raspberrypi/recipes-core/images folder. To do so, execute the below command from the yocto directory.

$ ls meta-raspberrypi/recipes-core/images

You should see rpi-basic-image.bb, rpi-hwup-image.bb and rpi-test-image.bb. The images names are the names of these files without the .bb file extension.

In this post, we will build the rpi-test-image.

Set the machine variable

By default, the build target machine is chosen to be qemux86-64. This needs to be changed to raspberrypi4. We will do this in the conf/local.conf file located in our build directory. We will first navigate to the active build directory and then make the necessary modification.

$ cd poky/build-rpi
$ vim conf/local.conf

NOTE: Replace build-rpi with the name of your build directory if using a different name.

NOTE: You can use any other editor if vim is not available or your preference.

Navigate to the presently uncommented line which sets the machine variable, comment it out by putting a # in front of it and the set raspberrypi4 as the machine. Below is how the final result should look like.

# MACHINE ??= "qemux86-64"
MACHINE ??= "raspberrypi4"

PRO-TIP: To test this Raspberry Pi 4 image, it is useful to have the serial console enabled. To do so, add the below line towards the end of the conf/local.conf file.

ENABLE_UART = "1"

The serial console on the Raspberry Pi 4 boards is available on pin numbers 8 (GPIO14 – TXD) and 10 (GPIO15 – RXD) of the 40-pin IO connector.

We are now ready to do our build. We will follow the same approach we followed last time i.e. first only fetch the resources needed for the build and then perform the build itself.

Fetch and Build!

You can now execute the below command for only fetching the necessary resources without starting the build.

$ bitbake rpi-test-image --runall=fetch

Depending on your internet connection and the CPU capability, it can take anywhere between few minutes to few tens of minutes to complete this process.

Once done, we can start the build by executing the below command.

$ bitbake rpi-test-image

Depending on your internet connection and the CPU capability, it can take anywhere between a few tens of minutes to maybe a few hours to do this build. Patience is the key!

That’s it – if all went well, you have built a test image for Raspberry Pi 4 using Yocto!

See you in the next post!

13 thoughts on “Yocto: Part 4 – Building a basic image for Raspberry Pi

  1. Hello – I keep getting stuck on the above command “bitbake-layers add-layer ./meta-openembedded”, which returns “Specified layer directory /home//yocto/meta-openembedded doesn’t contain a conf/layer.conf file” and won’t add the layer. Can you please provide suggestions, as I am stuck on this section? Thank you!

  2. Hello Kickstart – I too am having the same problem as Kevin above. Also, when attempting to add the meta-raspberrypi layer, I get an “Unable to find bblayers.conf”. The layer fails to get added to the list as well…

    1. I suspect the solution to your second issue is to cd to /build-rpi directory and run “bitbake-layers add-layer ../../meta-openembedded/meta-oe”. There’s a lot of small details which are incorrect in this series of tutorials and I am frustrated.

      1. Appreciate the feedback here. The root-cause seems to be that the folder organization for meta-embedded has changed slightly from dunfell to kirkstone. Executing the steps from the blog post on a dunfell clone work correctly.

        Could you share the branch you are on?

      2. bitbake-layers add-layer ./meta-openembedded this shows error while bitbake-layers add-layer ../../meta-openembedded/meta-oe this dosent show any error why is that

  3. I have been using the dunfell branch as instructed. Thank you.

    Related to discrepancies, I’ve observed the following in part 7 of this series FYI…
    a. Filename “hwtarlocal0.1.bb” should be “hwtarlocal_0.1.bb”
    b. Line “SRC_URI = “file://hwtarlocal-${PV}.tar.gz”” should be “file://hwtarlocal_${PV}.tar.gz””
    c. Rename download tarfetch file to “hwtarfetch_0.1.tar.gz”

    1. Awesome! Thanks for helping to improve this content. I will make these mods to the post.

      Also, I managed to RC the open embedded thing you ran into. It was an error at my end – I was trying out something (making a high-level layer.conf that would have BBFILE PATTERN look at meta-* folders to avoid individually adding internal layers) but then abandoned it as it would not pass the Yocto layer check script.
      Will add a section on this attempt and correct the meta-openembedded reference above.

Leave a Reply