In this chapter, we will discuss how we can use Yocto Project to bring up BeagleBone. We will discuss the steps that are necessary to set up a host environment for Yocto Project, create images, and set up BeagleBone hardware. We will also discuss how to prepare a card and finally deploy images on the board. Fortunately, BeagleBone is one of the reference boards of Yocto Project, and it makes our lives easier. We can find the core steps for hardware setup in README.hardware
, under Poky. There is a lot of information in the Yocto Project Development Reference Manual. What will we be doing here then? The steps given under Poky assume a lot of previous knowledge and sometimes a great deal of generic approach is used there, which isn't very useful for us. We will simplify things here. During this journey, we will pay a visit to different configuration files of Yocto Project and try to develop an understanding of these files. In this chapter, we will:
Set up a host environment
Obtain Yocto Project
Build for BeagleBone
Learn about configuration files
Before we start getting sources for Yocto Project and building it, we need to prepare our host system. Yocto Project is supposed to work on any distribution of Linux known to us. There is a list of supported platforms available in the Yocto Project Reference Manual (http://www.yoctoproject.org/docs/current/ref-manual/ref-manual.html#intro-requirements).
That is not to say that Yocto Project will not work on other distributions, but the given distributions are the ones on which it is verified to work successfully.
Ubuntu 12.04 (LTS)
Ubuntu 13.10
Ubuntu 14.04 (LTS)
Fedora release 19 (Schrödinger's Cat)
Fedora release 20 (Heisenbug)
CentOS release 6.4, 6.5
Debian GNU/Linux 7.0, 7.1, 7.2, 7.3, and 7.4 (Wheezy)
openSUSE 12.2, 12.3, and 13.1
For Poky Daisy 1.6.1, the list is long. We will stick to Ubuntu 14.04 (LTS) for the rest of the book. For this release, package dependencies that need to be taken care of are divided into the following four subcategories.
These are the core tools and packages that are required to build Yocto Project. These include a GNU compiler, versioning control system, and other packages that are required to build an environment on host. Here's the command to get the essentials:
$ sudo apt-get install gawk wget git-core diffstat unzip texinfo gcc-multilib \ build-essential chrpath
If you want to use graphics support or you intend to use Eclipse IDE, then you need to install these packages:
$ sudo apt-get install libsdl1.2-dev xterm
These packages are required if you want to build a Yocto Project documentation:
$ sudo apt-get install make xsltproc docbook-utils fop dblatex xmlto
These packages are required only if you want to build an Application Development Kit (ADK):
$ sudo apt-get install autoconf automake libtool libglib2.0-dev
If you are using any distribution other than those previously listed, you will find similar commands can be used on Debian distributions, as well. For other supported distributions, consult the Yocto Project Reference Manual.
We will use the daisy branch of Poky, which is a name for 1.6.1 version of Yocto Project. We will stick to this version throughout this book. These are the steps to follow while obtaining Yocto Project:
First, create a folder called
yocto
. Then, create a directory for it:$ mkdir yocto
Change the directory to this newly created directory:
$ cd yocto
Fetch sources for Poky:
$ git clone -b daisy git://git.yoctoproject.org/poky.git
Change the directory to
poky
:$ cd poky
What is the next logical step? Have a look at the directory contents using the ls
command to see what we got. Welcome! We are in good place. Let's enjoy our journey.
By examining the contents of the poky
directory, you will notice your terminal executables, as in most of the cases while working with new technologies/packages on *nix systems. Here, we have oe-init-build-env
. This is the one responsible for creating our build environment. We will source this script and pass to it our build directory as an argument, as follows:
$ source oe-init-build-env build_bbb
The build_bbb
argument can be anything you want. I wanted to keep it simply bbb
. However, I cannot do this as my Git Aware Prompt keeps complaining about new content. If you inspect .gitignore
, you will see that it has build*
in it. So, the directory prefixed with build will be ignored. This command will land you in the newly created build directory. Before moving further, we need to examine this directory. Here, we have a subdirectory named conf
and two files, bblayers.conf
and local.conf
. We will look into bblayers.conf
in the upcoming chapters. For now, we will go through the contents of local.conf
.
First, we will encounter the following two options, which are related to each other. These options are here to tune the level of parallelism used by BitBake, the actual driver behind Yocto Project. The two options are:
BB_NUMBER_THREADS ?= "${@oe.utils.cpu_count()}"
PARALL
EL_MAKE ?= "-j ${@oe.utils.cpu_count()}"
You will find these variables twice in this file: once in the preceding form and once in the following form:
#BB_NUMBER_THREADS ?= "4" #PARALLEL_MAKE ?= "-j 4"
We are telling BitBake about the maximum number of threads it should use for the job and the maximum of jobs run in parallel. Most of the Yocto Project manuals and blogs say both of these should be equal to the number of cores available on your system. However, my experience has proven that the following formula gives the maximum throughput, that is, the minimum time of execution:
BB_NUMBER_THREADS ?= "1.5 * Number of cores" PARALLEL_MAKE ?= "-j 2 * Number of cores"
On a 16-core server, we will use the combinations of 24 and 32, whereas on an 8-core machine we will use 12 and 16. For a 4-core machine, we will use 6 and 8 as follows:
BB_NUMBER_THREADS ?= "6" PARALLEL_MAKE ?= "-j 8"
Tip
While setting these variables, do not forget the difference of -j n
for PARALLE_MAKE
. Otherwise, you will encounter errors. Also, note that BitBake requires even numbers to be enclosed in ""
.
Next, we need to select the machine. Here, we will set BeagleBone, which is already available to us. So, we will uncomment it and comment out the default selection, which is the qemux86 selection. Commenting out an existing selection is not strictly necessary since it is assigned using the ??
operator, which we will discuss in the upcoming chapters.
MACHINE ?= "beaglebone" #MACHINE ??= "qemux86"
Next, we will set our downloads
directory. This directory will be used to download sources for packages. The available configuration variable to set this configuration is DL_DIR
. If we don't set this, its default value would be used as our build directory. So, we will have this directory created under the build directory. We usually don't care much in case of
Board Support Packages (BSPs) running rm-rf
on our build directory to start a fresh build. In such cases, not caring about this variable can cause regrets, as it will download all the sources again and again, causing longer build times. We set it up in the top-level directory, which contains the poky
directory itself, so that we don't ever accidentally delete it with other expendable stuff.
DL_DIR ?= "${TOPDIR}/../../downloads"
Next, we have SSTATE_DIR
, TMPDIR
, and DISTRO
, which we will leave unchanged for now. SSTATE_DIR
is related to the shared state feature of Yocto Project. Yocto Project has a mechanism to check whether some package is already built and available, it uses the existing package and doesn't build it. TMPDIR
is the directory that contains a lot of build stuff. We will go through its contents in the upcoming chapters. Then, we have PACKAGE_CLASSES
, as follow:
PACKAGE_CLASSES ?= "package_ipk"
We will leave the remaining variables unchanged.
We can use a lot other options in this file as well. We will learn about some of these options in the upcoming chapters.
As the name suggests, bblayers.conf
is there to provide us with a mechanism to configure our Yocto Project layers. This file has configurations related to layers. We can add extra layers to this file to use the metadata available in these layers. This file further classifies layers into removable and non-removable ones, as you can see in the following code snippet:
BBLAYERSBBLAYERSBBLAYERS ?= " \ /home/irfan/yocto/poky/meta \ /home/irfan/yocto/poky/meta-yocto \ /home/irfan/yocto/poky/meta-yocto-bsp \ " BBLAYERS_NON_REMOVABLE ?= " \ /home/irfan/yocto/poky/meta \ /home/irfan/yocto/poky/meta-yocto \ "
Since we are not using any extra layers, we will leave this file unchanged.
This file is optional. You won't find it created by the build environment creation script. We mostly use system-wide or other configurations common across different builds and targets are put in this file. For example, we would use the toolchain path if we were using an external toolchain. Another option could be specifying mirror sites, we case it for this purpose. If we have this file created, BitBake looks for it and uses common configurations from this file. We override any configuration that we want modified in conf/local.conf
.
This is an optional file. Just like the previous file, you won't find it created by the build environment creation script. We can use this file to set our custom options so that we don't have to modify local.conf
manually. In most of the cases, this file is used by build systems such as Jenkins. For example, if we don't want our build directory size to explode due to space constraints, we could use the following code file in the local.conf
or auto.conf
file:
INHERIT += "rm_work"
For now, we don't need to set this. I am just mentioning it here to elaborate the preceding point. Since we will analyze the contents of the tmp/work
directory in the upcoming chapters, I would suggest that you do not use this option for the time being.
Now that we have set all the configurations, let's start our build. You can choose any of the images to build. I will prefer core-image-sato
:
$ bitbake core-image-sato
Building images for our desired target may take some time, depending on network speed and processing power. After the build is complete, you will have your images ready at tmp/deploy/images/beaglebone/
under your build directory, as shown in the following screenshot. This contains first-level bootloader MLO, second-level bootloader u-boot, kernel image, device tree blobs, a root filesystem archive, and a modules archive.
Here, you will notice that we have symbolic links as well as full names of the files, with time stamp information in most of the cases. Symbolic links always point to the latest file created. We should always try to use a symbolic link for copying to avoid any confusion.
Now that we have our images created by Yocto Project, we are ready to verify these images on our BeagleBone board:

Images directory contents
In case of other images, such as core-image-minimal, core-image-base, and core-image-sdk, the content shown in this screenshot will contain files related to those images instead of core-image-sato
.
BeagleBone Black is shipped with Angstrom images by default and partitioned as we require. However, if you have damaged it or don't want to erase the default images, then you should follow these instructions to prepare another BeagleBone for use.
If the card you have inserted has some partitions, they will be mounted automatically. To avoid any surprises like damaging the card, unmount these partitions. If you are using an SD card reader, the device for the card will be /dev/mmcblk*
. If you are using some USB card reader, then the device will be something like /dev/sdX
, where X
is a number. X
depends on the SCSI drives that are already connected to your system. We are using the first option, that is, a built-in SD card reader. You can determine which device is created for your card by issuing the dmesg
command as follows:
$ dmesg | tail [27409.486378] mmc0: new high speed SDHC card at address 0007 [27409.486640] mmcblk0: mmc0:0007 SD04G 3.70 GiB [27409.488506] mmcblk0: p1
You can also use fdisk -l
to check what device is created for your card. Now, you can use the fdisk
utility as root or with sudo
to create our required partitions, using the following steps:
Unmount any mounted partition, using the
umount
command:$ umount /dev/mmcblk0p1
Launch the
fdisk
utitility and delete the previous partition(s); in our case, it is just one:$ sudo fdisk /dev/mmcblk0 Command (m for help): d Selected partition 1
Create new partition called
BOOT
of 32 MB and type primary:Command (m for help): n Partition type: p primary (0 primary, 0 extended, 4 free) e extended Select (default p): Using default response p Partition number (1-4, default 1): Using default value 1 First sector (2048-7774207, default 2048): Using default value 2048 Last sector, +sectors or +size{K,M,G} (2048-7774207, default 7774207): +32M
Create a second partition to hold
rootfs
. We will give all the remaining space to this partition:Command (m for help): n Partition type: p primary (1 primary, 0 extended, 3 free) e extended Select (default p): Using default response p Partition number (1-4, default 2): Using default value 2 First sector (67584-7774207, default 67584): Using default value 67584 Last sector, +sectors or +size{K,M,G} (67584-7774207, default 7774207): Using default value 7774207
Make the first partition bootable by setting the boot flag:
Command (m for help): a Partition number (1-4): 1
Set the first partition as WIN95 FAT32 (LBA):
Command (m for help): t Selected partition 1 Hex code (type L to list codes): c
We are done with the filesystem modification. So, let's write it by issuing the
w
command:Command (m for help): w The partition table has been altered! Calling ioctl() to re-read partition table. Syncing disks.
Format the first partition as FAT, using the following command. We will set the label as
BOOT
so that we know what directory it will be mounted to byudisks
:$ sudo mkfs.vfat -n "BOOT" /dev/mmcblk0p1
Format the second partition as an
ext4
filesystem, using the following command. The label for this is set toROOT
, as it will contain the extracted image of rootfs.$ sudo mkfs.ext4 -L "ROOT" /dev/mmcblk0p2
I have created a simple script to perform all the preceding steps. I am listing these steps here for your understanding, so that you can do any adjustments if required.
Tip
Downloading the example code
Most of the implementation code is kept at https://github.com/YoctoForBeaglebone/ and can be pulled directly from there. If you have something to add, feel free to add it. While adding something to any repository, kindly avoid pushing directly to the repository and use Git pull request mechanism supported by GitHub.
We have formatted our card, according to the requirements. Now, we are ready to populate images to it. The partitions are usually auto mounted under /media/$USER
. If not, we can use the mount command to mount the partition to our desired location:
$ sudo mount /dev/sdb1 /media/$USER/BOOT $ sudo mount /dev/sdb2 /media/$USER/ROOT
Now, follow these steps to copy images to the card:
Copy the u-boot MLO and u-boot bootloader images into the FAT32 partition:
$ sudo cp MLO /media/$USER/BOOT $ sudo cp u-boot.img /media/$USER/BOOT
Copy the kernel image into the boot partition:
$ sudo cp uImage /media/$USER/BOOT
Copy the
.dtb
file,am335x-boneblack.dtb
, into the boot partition. This step is required only in the case ofcore-image-minimal
. It is not required in our case, as we createdcore-image-sato
, which already has this file placed at the desired location in rootfs:$ sudo cp am335x-boneblack.dtb /media/$USER/BOOT
As a root user, uncompress
core-image-sato-beaglebone.tar.bz2
to theext4
partition:$ sudo tar -xf core-image-sato-beaglebone.tar.bz2 -C /media/$USER/ROOT/
Unmount both partitions:
$ sudo umount /dev/mmcblk0p1 $ sudo umount /dev/mmcblk0p2
Remove the card from the host machine, and insert it into the SD card slot on BeagleBone Black. We have a simple script named copy_images.sh
for these steps as well.
To boot BeagleBone Black, we need the following hardware:
An SD card with images flashed
BeagleBone Black
A power adapter that can supply 5V or a micro USB cable; we should use a 5V power adapter in order to avoid a decrease in the operating frequency
USB TTL-2303(PL2303) for serial communication
USB-TTL is connected to the J1 connector of BeagleBone in the following formation:
J1 Pin |
USB TTL Function |
---|---|
1 |
GND Ground |
4 |
RXL |
5 |
TXL |
A micro USB cable should be enough in most of the cases to provide power. However, for more resource-intensive tasks, for example, if additional peripherals are required, you will need to connect a power adapter.
BeagleBone Black uses a serial debug port to communicate with the host machine. We will use minicom as a serial terminal client to communicate over the serial port. To set up minicom, perform the following steps:
Run this setup command as a privileged user:
$ sudo minicom -s
Mmicom main configuration dialogue
A menu will appear on the terminal with nine different options, as shown in the preceding screenshot. We won't be changing many of these. The up and down arrow keys can be used to select these options. We will select the third option, Serial port setup. Choose this option by pressing the Enter key. You will enter into another menu in which each option is listed, along with a corresponding key on the keyboard on the left-hand side to choose the option. Press the A key on the keyboard to set your serial device to
/dev/ttyUSB0
, and then press Enter. If you are not sure which device is created in your case, you could find this out by using the following command combination on another terminal:$ dmesg | grep "pl2303 converter" [37532.385583] pl2303 3-3:1.0: pl2303 converter detected [37532.386415] usb 3-3: pl2303 converter now attached to ttyUSB0
Press E to set the baud rate. Use the A and B keys to navigate the baud rate values. A corresponds to next and B to previous. Keep pressing B till you get
115200 8N1
. Then, press Enter to choose this setting and go back to the previous menu.Next, we need to press F and G to change enablement statuses of hardware flow control and software flow control. Both need to be set to No. Finally, the settings should look as shown in this screenshot:
Minicom Serial Port Setup dialogue
Choose Save setup as dfl to avoid reconfiguring every time and choose Exit to go to minicom. Don't exit from it if you want to observe whether there is any activity on the serial port.
Now that we have everything set up, we are ready to boot. We can just insert this card, and our board should boot from it. There might be only one issue if you have the eMMC (embedded MultiMediaCard) boot selected by default. You will have to disable it by booting up the board from the images you already have and renaming the MLO file from the eMMC partition. Alternatively, you can simply execute the following two commands on the u-boot prompt. To stop at the u-boot prompt, simply press Enter after powering up the board before timeout:
# mmc dev 1 # mmc erase 0 512
The first command will select the eMMC card, and the second one will do the erasing so that BeagleBone doesn't try to boot from eMMC.
Insert our prepared SD card and power up BeagleBone. You should get an output similar to the following one on minicom:
Booting from mmc ... ## Booting kernel from Legacy Image at 82000000 ... Image Name: Linux-3.14.0-yocto-standard Image Type: ARM Linux Kernel Image (uncompressed) Data Size: 4985768 Bytes = 4.8 MiB Load Address: 80008000 Entry Point: 80008000 Verifying Checksum ... OK ## Flattened Device Tree blob at 88000000 Booting using the fdt blob at 0x88000000 Loading Kernel Image ... OK Loading Device Tree to 8fff5000, end 8ffff207 ... OK Starting kernel …
Finally, we will land in our BeagleBone prompt:
Poky (Yocto Project Reference Distro) 1.6.1 beaglebone /dev/ttyO0 beaglebone login:
Enter root
as user, and you are in as the root user:
root@beaglebone:~#
We have already visited some configuration files during the build process. There are some more configuration files that were not discussed during the build process in order to avoid making it lengthier. These are bitbake.conf
and machine.conf
. Let's look at them.
You won't find a file with this name. Here, machine is a placeholder for the target board we are preparing our images for. For example, in our case, this file is beaglebone.conf
and in the preceding configuration, it is available as beaglebone.conf
in the poky/meta-yocto-bsp/conf/machine/
directory.
All of the machine- specific configurations are done in this file. We need to know about it and have some basic understanding of its contents so that we can modify it, if required. Let's go through it. The top-level header contains information in tags for documentation:
#@TYPE: Machine #@NAME: Beaglebone machine #@DESCRIPTION: Machine configuration for http://beagleboard.org/bone and http://beagleboard.org/black boards
The preferred xserver can be used:
PREFERRED_PROVIDER_virtual/xserver ?= "xserver-xorg" XSERVER ?= "xserver-xorg \ xf86-input-evdev \ xf86-input-mouse \ xf86-video-fbdev \ xf86-input-keyboard"
What extra recipes need to be built? These are built here:
MACHINE_EXTRA_RRECOMMENDS = " kernel-modules kernel-devicetree"
Set image dependencies:
EXTRA_IMAGEDEPENDS += "u-boot"
Architecture-specific configurations are found in tune files. Here, we will set the available one that will fulfill our requirements:
DEFAULTTUNE ?= "cortexa8hf-neon" include conf/machine/include/tune-cortexa8.inc
These tune files are present under Poky on the path that we are using in include
directive.
Here, we will specify the type of filesystem images we want to create for our machine. There are other options to choose from. Also, here, we will set extra image commands in the case of the jffs2
image:
IMAGE_FSTYPES += "tar.bz2 jffs2" EXTRA_IMAGECMD_jffs2 = "-lnp "
One of the most important options is the serial debug console. Here, we are defining our eyes with which to peek inside the board:
SERIAL_CONSOLE = "115200 ttyO0"
Here, we are tweaking our kernel options to see what recipe should be used for kernel compilation and what version of kernel needs to be built. For this, we will use the Yocto Project keywords, PREFERRED_PROVIDER
and PREFERRED_VERSION
:
PREFERRED_PROVIDER_virtual/kernel ?= "linux-yocto" PREFERRED_VERSION_linux-yocto ?= "3.14%"
We can also create another kernel image, zImage. Since this is a generic machine for BeagleBone Black and White versions, we will create device tree binary files for both of the target. You can opt not to build DTB for BeagleBone White, but this won't make much difference in terms of build time or cleanliness, if you are considering such things. Also, we can set any extra arguments that need to be passed to KERNEL
:
KERNEL_IMAGETYPE = "uImage" KERNEL_DEVICETREE = "am335x-bone.dtb am335x-boneblack.dtb" KERNEL_EXTRA_ARGS += "LOADADDR=${UBOOT_ENTRYPOINT}"
Here, we will configure most of the aspects of our bootloaders. We will set MLO as the binary name for stage-one bootloader so that we will have it created as MLO, as we saw in the images directory. We will specify a u-boot suffix, img
, to be used so that we have the u-boot.img
file created. Other options are also related to u-boot, such as these:
SPL_BINARY = "MLO" UBOOT_SUFFIX = "img" UBOOT_MACHINE = "am335x_evm_config" UBOOT_ENTRYPOINT = "0x80008000" UBOOT_LOADADDRESS = "0x80008000"
Now, we will determine the features that we want our machine to support or, more precisely, the features it has the ability to support. We will also determine which features we want turn on:
MACHINE_FEATURES = "usbgadget usbhost vfat alsa"
As the name signifies, this file is related to BitBake, the real engine behind Yocto Project, which is responsible for the simplification of our build process. This file is parsed first and then the rest of the configuration files listed in it are parsed. This file is found under poky/meta/conf/ as bitbake.conf
. This is not a small file, so we cannot go through it line by line. It contains more than 700 lines of configuration and metadata. Almost all the metadata used in our recipes is defined in this file.
It is not a standalone file. Instead, it includes other files from the conf
directory. We can find all the files that were described earlier in it. So, bitbake.conf
uses these files and the metadata definitions in them. For example, if you remember, we used some variables such as DL_DIR
, TOPDIR
, and TMPDIR
, You can find all these variables in this file, along with their default values. This file has all the metadata arranged in different sections. It contains about 20 different sections. Variables defined in one section are used in other sections. Let's have a brief look at some of these sections.
These are standard filesystem paths extensively used in different recipes. This section has further subsections. You won't need to change these variables, but you should reference these while developing recipes.
This is also a huge set of variables to define architecture-dependent metadata. These variables are prefixed with BUILD_
, HOST_
, TARGET_
, and SDK_
so as to clarify their domain of affect.
Variables from this section are extensively used in recipes. These variables are used in every recipe. We will discuss most of these variables in the upcoming chapters.
We have touched some of these variables while configuring our build. These define most of the build directory structure. This section contains a staging-related section. This section is very important for cross compilation, which is usually the case when using Yocto Project.
These variables define different properties of our root filesystem image. For example, from variables such as IMAGE_NAME
, you can infer how the name of our image, core-image-sato-beaglebone-20141126124205
, is created.
Of course, our build flags go into this section. You can see different flags related to compiler, linker, and Make in this section.
This section contains mirror definitions for speeding up the build process. Since we are creating BSPs that contain a lot of packages, we face time constraints. Yocto Project tries to tackle such obstacles in this way. Also, you can see commands to fetch from different versioning systems in this section.
In this chapter, you learned how to prepare our host system to use it as a Yocto Project development host. You also learned how to build BeagleBone images using Yocto Project, prepare an SD card, boot the board from this card, and set up serial communication to the board to take a sneak peek into it. We discussed most of the configuration files in this chapter. We took a brief look at some extra configuration files, as well. In the next chapter, you will learn about the core tool behind Yocto Project, which is BitBake, in detail. You will also learn about its various options and how we can use them to make our lives easier.