Embedded workflow with buildroot for Raspberry Pi: toolchain


During our experiments with electronics and as part of ongoing effort to find out best setup for next robot we decided to experiment with different Raspberry Pi versions. Getting Raspbian is super easy and described elsewhere. This allows to start developing in no time. But if we speak about time, being debian, it relatively complex system and it takes time to boot. Additionaly it take a lot of space and requires read-write partition, which doesn't work well in robot scenario where robot could be restarted at any time or loose power. That's why I decided to experiment with other options. 

Having some experience with openembedded on the beagleboard I wanted to check something else and this time had a look to Buildroot. Buildroot environment is conceptionally similar to openembedded as it allows to build completely custom embedded linux distribution. First impression shows that it is smaller, which on the negative side has much less packages, but on the pro side it is simpler. It is based on Makefiles, which are very well understood. Here I would like to document steps taken to setup and use buildroot to build custom image.


Target for this series is to setup comfortable wokrflow with following requirements:
  • Buildroot based images
  • Separated toolchain and image setup, which allows to re-build image without re-building toolchain
  • Toolchain allows building u-boot and other custom software with easy deployment
  • Possibility to build from the same source different targets, for example, pi and qemu
  • Image is built with ramdisk in one big zImage file
  • The image should as slim as possible to minimize startup time targeting first interaction with user under 2 seconds
  • The system should not write anything to the filesystem
  • Alternative booting scenarios such as nfsroot mounted for iterative development should be possible
  • Development system should separate board specifics so that update to new version is pretty easy
  • Example of custom kernel module should be present. I will try to integrate small LCD display and show welcome message on the start


The development happens on the Debian jessy, which at the moment 04/2015 is testing. User is able to do sudo and all development happens in "~/work/" folder.

# This is base for project
~ -> mkdir work; cd work/

# Directory structure 
~/work -> mkdir src # this is where all unpacked sources are stored
~/work -> mkdir dl  # this folder contains downloaded packages
~/work -> mkdir pi  # here we build pi image
~/work -> mkdir tc  # this is folder for toolchain build

# buildroot get from git for easy updates
~/work -> cd src/
~/work/src -> git clone git://git.buildroot.net/buildroot 
~/work/src -> cd buildroot/
~/work/src/buildroot -> git checkout 2015.02   # current stable version
~/work/src/buildroot -> cd ../

Short version 

The prepared package could be downloaded from github and will get toolchain working in no time. For those who want to do it manually and learn a bit you can skip to longer version below.

# Get piwf 
~/work/src -> git clone git://github.com/veter-team/piwf.git; cd piwf/
~/work/scr/piwf -> git checkout toolchain
~/work/src/buildroot -> cd ../../tc/

# Let's create Makefile and initial .config
~/work/tc -> make O=$PWD -C ../src/buildroot BR2_EXTERNAL=../piwf pitc_defconfig 

# Time for coffee, on my notebook it takes with download around 10 minutes
~/work/tc -> make 
~/work/tc -> ls host/usr/
arm-buildroot-linux-uclibcgnueabi  bin  include  lib  libexec  share

Here is your brand new buildroot toolchain for Raspberry Pi.

Long version

Now let us create overlay for buildroot with custom configuration. The overlay will contain additional files with buildroot structure and custom packages. The overlay is refered with BR2_EXTERNAL variable and pretty good documented in buildroot manual.

# Let us create overlay
~/work/src -> mkdir -p piwf/configs; cd piwf/
# Required for BR2_EXTERNAL and will be used to add packages
~/work/src/piwf -> touch Config.in external.mk

# Always good idea to put files under git
~/work/src/piwf -> git init
~/work/src -> cd ../tc/

# Let's create Makefile and initial .config
~/work/tc -> make O=$PWD -C ../src/buildroot raspberrypi_defconfig

# Show me the options
~/work/tc -> make menuconfig

Now you presented with a lot of options. On this stage we would like to switch off as many packages as possible. Target is to build only toolchain and no native packages. After all these packages switched off, the buildroot still copies skeleton of rootfs, but it just takes space. The [*] should be switched on and if below table show [ ] it should be switched off. The rest of the options could be left as it is as they are already off.

Build options ->
    ($(BASE_DIR)/../src/piwf/configs/pitc_defconfig) Location to save buildroot config
    ($(BASE_DIR)/../dl) Download dir
    [*] Enable compiler cache
Toolchain ->
    Kernel Headers (Linux 3.18.x kernel headers) 
    [*] Enable large file support
    [*] Enable IPv6 support
    [*] Enable RPC support
    [*] Enable WCHAR support
    [*] Enable stack protection support
    Binutils version (binutils 2.25)
    *** GCC version ***
        GCC Compiler version (gcc 4.9.x)
    [*] Enable C++ support
    [*] Enable compiler tls support
    [*] Purge unwanted locales
        (C en_US)

System Configuration ->
    Init System -> None
    /bin/sh -> None
    Root FS skeleton (custom target skeleton)

Kernel ->
    [ ] Linux Kernel

Target Packages ->
    [ ] Busybox
    Hardware handling ->
       Firmware ->
           [ ] rpi-firmware
Filesystem images
    [ ] tar the root filesystem

It is time to exit and on the question save ".config" file. Now ".config" file contains only options required for toolchain. Obviously, if the requirements are different, for example, IPV6 support is needed, it should be switched on. But presented here options should be enough for most of the cases.

# Let save config in our overlay
~/work/tc -> make savedefconfig

# And now building
~/work/tc -> make
~/work/tc -> ls host/usr/
arm-buildroot-linux-uclibcgnueabi  bin  include  lib  lib exec  share

The toolchain is built and the defaut config for toolchain is saved in overlay. Time to commit changes.

~/work/tc -> cd ../src/piwf/
~/work/src/piwf -> git add .
~/work/src/piwf -> git commit -m "Added initial toolchain"
~/work/src/piwf -> git tag -a "toolchain" -m "Toolchain article"

Building actual image with this toolchain will be discussed in next article.


  1. More that can be done with Raspberry Pi! Thanks for the info. From kids doing homework to researchers, there is definitely something everyone can take advantage of.

  2. This is great wonderful information.. awesome ideas Thanks.

  3. Where can I find the next article? (Building actual image with this toolchain will be discussed in next article)

  4. Excuse me, thanks for explaining, but when i come to the make command in the short version i get an error and i didn't find a solution. The error is :
    make[1]: *** [core-dependencies] Error 1
    Makefile:16: recipe for target '_all' failed
    make: *** [_all] Error 2


Post a Comment