\documentclass[aspectratio=169,obeyspaces,spaces,hyphens,dvipsnames]{beamer}
\usepackage[utf8]{inputenc}
\usepackage{lmodern}% http://ctan.org/pkg/lm
\usepackage{hyperref}
\usepackage{xcolor}
\usepackage{pgfplots}
\usepackage{tikz}
\usepackage[normalem]{ulem}

\mode<presentation>
\usetheme{Bootlin}

\def\signed #1{{\leavevmode\unskip\nobreak\hfil\penalty50\hskip2em
  \hbox{}\nobreak\hfil(#1)
  \parfillskip=0pt \finalhyphendemerits=0 \endgraf}}

\newsavebox\mybox
\newenvironment{aquote}[1]
  {\savebox\mybox{#1}\begin{quotation}}
  {\signed{\usebox\mybox}\end{quotation}}

\title{Getting started with Buildroot}
\authors{Thomas Petazzoni}
\email{thomas.petazzoni@bootlin.com}
\slidesurl{https://bootlin.com/pub/conferences/2019/elce/petazzoni-buildroot-tutorial/}
\institute{Bootlin}
\conference{Embedded Development Essentials}

\begin{document}

\addtocontents{toc}{\protect\setcounter{tocdepth}{-1}}
\section{Getting started with Buildroot}
\addtocontents{toc}{\protect\setcounter{tocdepth}{2}}

\begin{frame}{Thomas Petazzoni}
  \begin{itemize}
  \item CTO/Embedded Linux engineer at Bootlin
    \begin{itemize}
    \item Embedded Linux {\bf expertise}
    \item {\bf Development}, consulting and training
    \item Strong open-source focus
    \item Freely available training materials
    \end{itemize}
  \item Co-maintainer of {\bf Buildroot}
  \item Living in {\bf Toulouse}, France
  \end{itemize}
\end{frame}

\begin{frame}{Building an embedded Linux system}
  \begin{center}
    \uncover<1>{\includegraphics[width=0.2\textwidth]{build-solutions-distros.pdf}}
    \uncover<3>{\includegraphics[width=0.2\textwidth]{build-solutions-build-systems.pdf}}
    \uncover<2>{\includegraphics[width=0.2\textwidth]{build-solutions-hand-made.pdf}}
  \end{center}
  \only<1>{
    \begin{itemize}
    \item[+] Readily available
    \item[-] Large, usually 100+ MB
    \item[-] Not available for all architectures
    \item[-] Not easy to customize
    \item[-] Generally require native compilation
    \end{itemize}
  }
  \only<2>{
    \begin{itemize}
    \item[+] Smaller and flexible
    \item[-] Very hard to handle cross-compilation and dependencies
    \item[-] Not reproducible
    \item[-] No benefit from other people's work
    \end{itemize}
  }
  \only<3>{
    \begin{itemize}
    \item[+] Small and flexible
    \item[+] Reproducible, handles cross-compilation and dependencies
    \item[+] Available for virtually all architectures
    \item[-] One tool to learn
    \item[-] Build time
    \end{itemize}
  }
\end{frame}

\begin{frame}{Embedded Linux build system: principle}
  \begin{center}
    \includegraphics[width=0.9\textwidth]{buildsystem-principle.pdf}
  \end{center}
  \begin{itemize}[<+->]
  \item Building from source $\rightarrow$ lot of flexibility
  \item Cross-compilation $\rightarrow$ leveraging fast build machines
  \item Recipes for building components $\rightarrow$ easy
  \end{itemize}
\end{frame}

\begin{frame}{Buildroot at a glance}
  \begin{columns}
    \column{0.8\textwidth}
  \begin{itemize}
  \item Is an {\bf embedded Linux build system}, builds from source:
    \begin{itemize}
    \item cross-compilation toolchain
    \item root filesystem with many libraries/applications, cross-built
    \item kernel and bootloader images
    \end{itemize}
  \item {\bf Fast}, simple root filesystem in minutes
  \item {\bf Easy} to use and understand: kconfig and make
  \item {\bf Small} root filesystem, default 2 MB
  \item More than {\bf 2500 packages} available
  \item Generates filesystem images, not a distribution
  \item Vendor neutral
  \item Active community, stable releases every 3 months
  \item Started in 2001, oldest still maintained build system
  \item \url{http://buildroot.org}
  \end{itemize}
  \column{0.2\textwidth}
  \includegraphics[width=\textwidth]{logo.png}
\end{columns}
\end{frame}

\begin{frame}{Today's lab}
  \begin{itemize}
  \item {\bf Step 1}: do a minimal build for the PocketBeagle, with
    just a bootloader, Linux kernel and minimal root
    filesystem. Generate a ready-to-use SD card image.
  \item {\bf Step 2}: enable network over USB and SSH connectivity
    using Dropbear. Shows how to use a rootfs overlay and how to add
    packages.
  \item {\bf Step 3}: customize the Linux kernel configuration,
    compile a small application that uses the GPIO, first manually,
    and then using a new Buildroot package
  \item {\bf Don't hesitate to request help and ask questions!}
  \end{itemize}
\end{frame}

\begin{frame}
  \begin{center}
    \Huge{Step 1}

    Minimal build for the PocketBeagle
  \end{center}
\end{frame}

\begin{frame}[fragile]{Getting Buildroot}
  \begin{block}{Cloning Buildroot}
    \begin{verbatim}
$ git clone git://git.busybox.net/buildroot
$ cd buildroot
\end{verbatim}
  \end{block}
  Note: if cloning is too slow, you can use \code{buildroot.tar.xz}
  from the USB stick.

  \begin{block}{Create a branch based on the latest LTS}
\begin{verbatim}
$ git checkout -b ede-lab 2019.02.6
\end{verbatim}
  \end{block}


  \begin{block}{Get one U-Boot integration improvement}
    We need to cherry-pick one more recent commit, to be able to pass
    arbitrary variables to the U-Boot build:
\begin{verbatim}
$ git cherry-pick cc151c3993090a52d1fef8532f52d74ee6d924c9
\end{verbatim}
  \end{block}

\end{frame}

\begin{frame}[fragile]{Starting the configuration}
  \begin{columns}
    \column{0.5\textwidth}
    \begin{itemize}
    \item Buildroot has a large number of pre-defined configuration
      files for popular HW platforms: \code{make list-defconfigs}
    \item For learning purposes, we are going to create our own
      configuration from scratch for the Pocket Beagle
    \end{itemize}
    \begin{block}{}
\begin{verbatim}
$ make menuconfig
\end{verbatim}
    \end{block}
    \column{0.5\textwidth}
    \includegraphics[width=\textwidth]{buildroot-screenshot.png}
  \end{columns}
\end{frame}

\begin{frame}{{\em menuconfig}: Target options}
  \begin{itemize}
  \item {\bf Target architecture}: {\em ARM (little endian)}
  \item {\bf Target architecture variant}: {\em Cortex-A8}
  \end{itemize}
\end{frame}

\begin{frame}{Build options}
  \begin{itemize}
  \item {\bf Global patch directories}: \code{board/e-ale/pocketbeagle/patches/}
  \item We will need to apply one patch to Linux to improve the
    PocketBeagle Device Tree description. Buildroot automatically
    applies patches from {\em global patch directories} subfolders
    named after Buildroot packages.
  \item We will add those patches once we are done with the
    configuration.
  \end{itemize}
\end{frame}

\begin{frame}{{\em menuconfig}: Toolchain}
  \begin{itemize}
  \item {\bf Toolchain type}: {\em External toolchain}
  \item Buildroot supports:
    \begin{itemize}
    \item {\em Internal toolchain}: Buildroot builds a
      cross-compilation toolchain from scratch. Flexible, but
      additional build time needed.
    \item {\em External toolchain}: Buildroot downloads and uses a
      pre-built cross-compilation toolchain.
    \end{itemize}
  \item On ARM, the ARM-provided toolchain ({\em Arm ARM 2018.11}) is
    automatically chosen by default as an external toolchain.
  \end{itemize}
\end{frame}

\begin{frame}{{\em menuconfig}: System configuration}
  \begin{itemize}
  \item {\bf System host name}: \code{ede}
  \item {\bf System banner}: \code{Hello EDE}
  \item {\bf Init system}: keep the default of \code{Busybox},
    Buildroot also supports systemd, sysvinit.
  \item {\bf /dev management}: keep the default of \code{devtmpfs},
    Buildroot also supports udev, systemd, etc.
  \end{itemize}
\end{frame}

\begin{frame}{{\em menuconfig}: Kernel}
  \begin{itemize}
  \item Enable {\bf Linux Kernel}
  \item {\bf Kernel version}: {\em Custom version}
  \item {\bf Kernel version}: {\em 5.3}
  \item No need to specify a path to patches, we are already using the
    {\em global patch directory mechanism}
  \item {\bf Defconfig name}: \code{omap2plus}
  \item Enable {\bf Build a Device Tree Blob}
  \item {\bf In-tree Device Tree Source file names}:
    \code{am335x-pocketbeagle}
  \end{itemize}
\end{frame}

\begin{frame}{{\em menuconfig}: Target packages}
  \begin{itemize}
  \item Since {\bf Busybox} is chosen as init system, it is already
    forcefully selected.
  \item {\bf Busybox} provides all we need for a minimal Linux system,
    so no need to enable other packages.
  \item You can have a look at the choice of 2500+ packages, we'll use
    a few more in the next steps.
  \end{itemize}
\end{frame}

\begin{frame}{{\em menuconfig}: Filesystem images}
  \begin{itemize}
  \item Enable {\bf ext2/3/4 root filesystem}, and select the
    \code{ext4} variant
  \item Disable {\bf tar the root filesystem}
  \end{itemize}
\end{frame}

\begin{frame}{{\em menuconfig}: Bootloaders}
  \begin{itemize}
  \item Enable {\bf U-Boot}
  \item {\bf Build system}: {\em Kconfig}. We use a modern U-Boot!
  \item {\bf Custom version}: {\em 2019.10}
    \begin{itemize}
    \item Using a fixed version instead of the default version allows
      to ensure our build will always build that specific version we
      have tested.
    \end{itemize}
  \item {\bf Board defconfig}: \code{am335x_evm}
  \item {\bf U-Boot binary format}: \code{u-boot.img}. Indeed, U-Boot
    itself will be the second stage bootloader.
  \item Enable {\bf U-Boot needs dtc}
  \item Enable {\bf Install U-Boot SPL binary image}. This enables
    building the first stage bootloader.
  \item Set {\bf U-Boot SPL/TPL binary image name} to {\em MLO}, the
    name required on AM335x.
  \item Set {\bf Custom make options} to
    \code{DEVICE_TREE=am335x-pocketbeagle}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]{Adding the patches}
  \begin{itemize}
  \item Before starting the build, we need to add the Linux kernel and
    U-Boot patches needed to support the Pocket Beagle.

  \item Create the folder \code{board/ede/pocketbeagle/patches/}
    that we referenced as a {\em global patch directory}

  \item Copy to this folder the contents of the \code{patches/} folder
    of the USB stick.

  \end{itemize}

  \begin{block}{}
    {\small
\begin{verbatim}
$ tree board/e-ale/pocketbeagle/
board/e-ale/pocketbeagle/
- patches
  - linux
    - 0001-ARM-dts-describe-the-MCP23S18-connected-on-Pocket-Be.patch
\end{verbatim}
    }
  \end{block}

\end{frame}

\begin{frame}{Pre-populating the download folder}
  \begin{itemize}
  \item By default, Buildroot caches all the downloaded tarballs in
    \code{dl/}
  \item In order to speed up the build process and avoid long download
    times, we are going to pre-populate this download folder.
  \item Copy the \code{dl/} folder from the USB stick to the Buildroot
    source directory.
  \end{itemize}
\end{frame}

\begin{frame}[fragile]{Doing the build}

  To run the build, do:

  \begin{block}{}
\begin{verbatim}
make 2>&1 | tee build.log
\end{verbatim}
\end{block}

  This allows to complete log of the build output.

  Alternatively, there is a wrapper script provided by Buildroot:

  \begin{block}{}
\begin{verbatim}
$ ./utils/brmake
\end{verbatim}
  \end{block}

  The build will take a while (14-15 minutes on your instructor
  machine), because the \code{omap2plus_defconfig} kernel
  configuration has a LOT of features enabled.

\end{frame}

\begin{frame}{During the build: exploring the build output}
  \begin{itemize}
  \item All the output produced by Buildroot is stored in
    \code{output/}
  \item Can be customized using \code{O=} for out-of-tree build
  \item \code{output/} contains
    \begin{itemize}
    \item \code{output/build}, with one sub-directory for the source
      code of each component
    \item \code{output/host}, which contains all native utilities
      needed for the build, including the cross-compiler
    \item \code{output/host/<tuple>/sysroot}, which contains all
      the headers and libraries built for the target
    \item \code{output/target}, which contains {\em almost} the target
      root filesystem
    \item \code{output/images}, the final images
    \end{itemize}
  \item \code{dl/} contains downloaded artifacts, can be customized by
    the \code{BR2_DL_DIR} env. variable
  \end{itemize}
\end{frame}

\begin{frame}{During the build: summarized build process}
  \begin{enumerate}
  \item Check core dependencies
  \item For each selected package, after taking care of its
    dependencies: download, extract, patch, configure, build, install
    \begin{itemize}
    \item To \code{target/} for target apps and libs
    \item To \code{host/<tuple>/sysroot} for target libs
    \item To \code{host/} for native apps and libs
    \item Filesystem skeleton and toolchain are handled as regular
      packages
    \end{itemize}
  \item Copy {\em rootfs overlay}
  \item Call {\em post build} scripts
  \item Generate the root filesystem image
  \item Call {\em post image} scripts
  \end{enumerate}
\end{frame}

\begin{frame}{Build finished: what do we have ?}
  \begin{itemize}
  \item \code{ls output/images}
    \begin{itemize}
    \item \code{MLO}, the first stage bootloader
    \item \code{u-boot.img}, the second stage bootloader
    \item \code{zImage}, the Linux kernel image
    \item \code{am335x-pocketbeagle.dtb}, the Linux kernel Device Tree Blob
    \item \code{rootfs.ext4}, the root filesystem image
    \end{itemize}
  \item $\rightarrow$ this doesn't give us a bootable SD card image
  \item Let's create one using {\em genimage}
  \end{itemize}
\end{frame}

\begin{frame}{SD card image with genimage: intro}

  \begin{itemize}
  \item Tool from {\em Pengutronix}
  \item Given a configuration file, creates a block device image with
    a partition table and filesystems
  \item Need to be called at the very end of the build: we will run it
    in a {\em post image} script
  \item Our SD card image will have:
    \begin{itemize}
    \item One FAT partition with bootloader, kernel image and Device Tree
    \item One ext4 partition with the root filesystem
    \end{itemize}
  \end{itemize}

\end{frame}

\begin{frame}{SD card image with genimage: configuration}

  \begin{itemize}

  \item In \code{menuconfig}
    \begin{itemize}
    \item {\bf System configuration} $\rightarrow$ {\bf Custom scripts
        to run after creation filesystem images}, set to
      \code{board/ede/pocketbeagle/post-image.sh}
    \item {\bf Host utilities}, enable \code{host genimage},
      \code{host mtools}, \code{host dosfstools}. This will make sure
      those tools are built for the build machine
    \end{itemize}

  \item Copy \code{genimage.cfg}, \code{post-image.sh} and
    \code{uEnv.txt} from the USB stick to
    \code{board/ede/pocketbeagle}
    \begin{itemize}
    \item \code{genimage.cfg}, {\em genimage} configuration file, have
      a look at it
    \item \code{post-image.sh}, shell script that calls {\em genimage}
      with the appropriate arguments
    \item \code{uEnv.txt}, U-Boot script to boot the system
    \end{itemize}

  \end{itemize}

\end{frame}

\begin{frame}[fragile]{SD card image: building and booting}

  \begin{itemize}
  \item Start the build again with \code{make}
  \item It will only build a few additional tools (genimage, etc.) and
    produce the SD card image
  \item The SD card image will be \code{output/images/sdcard.img}
  \item Transfer to your SD card
    \begin{block}{}
\begin{verbatim}
$ sudo dd if=output/images/sdcard.img of=/dev/mmcblk0 bs=1M
\end{verbatim}
    \end{block}
  \item Insert the SD card in the PocketBeagle, and boot it (serial
    port at 115200 bps)
  \item Login as \code{root}, no password.
  \item System weights 18.4 MB, of which 12.1 MB are kernel modules
  \end{itemize}

\end{frame}

\begin{frame}[fragile]{Storing our Buildroot configuration persistently}

  \begin{itemize}

  \item Our current configuration is stored in \code{.config}
    \begin{itemize}
    \item Will be lost upon \code{make distclean}
    \item Or if we create a different configuration for a different
      project
    \end{itemize}
  \item Save it as a {\em defconfig} file:
    \begin{block}{}
\begin{verbatim}
$ make BR2_DEFCONFIG=configs/ede_pocketbeagle_defconfig savedefconfig
\end{verbatim}
    \end{block}
  \item And have a look at \code{configs/ede_pocketbeagle_defconfig}
  \end{itemize}

\end{frame}

\begin{frame}
  \begin{center}
    \Huge{Step 2}

    Network connectivity over USB: SSH
  \end{center}
\end{frame}

\begin{frame}{Network configuration: using a rootfs overlay}

  \begin{itemize}
  \item To enable network over USB, we will need:
    \begin{itemize}
    \item An init script that loads the relevant kernel modules and
      uses {\em configfs} to set up the USB gadget device. It will be
      installed as \code{/etc/init.d/S30usbgadget}.
    \item A customized \code{/etc/network/interfaces} file
    \end{itemize}
  \item We will use a {\bf root filesystem overlay} to add those
    customizations to the root filesystem.
  \item In \code{menuconfig}
    \begin{itemize}
    \item {\bf System configuration}, set {\bf Root filesystem overlay
        directories} to \code{board/ede/pocketbeagle/overlay/}
    \item {\bf System configuration}, set {\bf Root password} to a
      non-empty one
    \item {\bf Target packages}, {\bf Networking applications}, enable
      \code{dropbear}
    \end{itemize}
  \item Copy the contents of \code{overlay/} from the USB stick to
    \code{board/ede/pocketbeagle/overlay/}, and of course, have a
    look at it!
  \end{itemize}

\end{frame}

\begin{frame}[fragile]{Using the network}
  \begin{itemize}
  \item Restart the build
    \begin{block}{}
\begin{verbatim}
$ make 2>&1 | tee build.log
\end{verbatim}
    \end{block}
    \item Reflash the SD card
    \item Boot
    \item On your PC, configure the new network interface with the IP
      address 192.168.42.1
    \item If you're using network manager:
      \begin{block}{}
\begin{verbatim}
$ nmcli con add con-name buildroot-target type ethernet \
    ifname enp57s0u1u6u4 ip4 192.168.42.1/24
\end{verbatim}
      \end{block}
    \item SSH into the board, from your PC:
      \begin{block}{}
\begin{verbatim}
$ ssh root@192.168.42.2
\end{verbatim}
      \end{block}
  \end{itemize}
\end{frame}

\begin{frame}
  \begin{center}
    \Huge{Step 3}

    Developing an application
  \end{center}
\end{frame}

\begin{frame}{Adding libgpiod and GPIO support}
  \begin{itemize}
  \item We are going to write a demo application based on the
    \code{libgpiod} library, to manipulate GPIOs.
  \item Let's first add this library in your Buildroot configuration,
    in \code{menuconfig}, enable \code{BR2_PACKAGE_LIBGPIOD} and its
    tools.
  \item We also need to enable the GPIO kernel driver, using the
    option \code{CONFIG_PINCTRL_MCP23S08}. To do this, run \code{make
      linux-menuconfig}, which will open up the Linux kernel {\em
      menuconfig}, and enable the driver.
    \begin{itemize}
    \item Note: this change would be lost during a \code{make
        clean}. To make it persistent, using a configuration file
      fragment would be appropriate.
    \end{itemize}
  \item Run \code{make} to rebuild the system, reflash on the SD card,
    and reboot
  \end{itemize}
\end{frame}

\begin{frame}[fragile]{Testing GPIO support}

  \begin{itemize}
  \item We can list the list the GPIO chips using \code{gpiodetect}:
    \begin{block}{}
\begin{verbatim}
# gpiodetect
\end{verbatim}
    \end{block}

  \item We can use the GPIOs using \code{gpioset}:
    \begin{block}{}
\begin{verbatim}
# gpioset gpiochip4 0=0
# gpioset gpiochip4 1=0
# gpioset gpiochip4 1=1
# gpioset gpiochip4 0=1
\end{verbatim}
    \end{block}
  \end{itemize}

\end{frame}

\begin{frame}[fragile]{Cross-compiling a simple application}
  \begin{itemize}
  \item Let's now build a simple application to see how to use the
    Buildroot cross-compiler
  \item Copy the \code{ede-gpio-app} folder from the USB stick
    side-by-side with Buildroot:
    \begin{block}{}
\begin{verbatim}
 - buildroot/
 - ede-gpio-app/
   - ede-gpio-app.c
   - Makefile
\end{verbatim}
    \end{block}
  \item To build the application:
    \begin{block}{}
\begin{verbatim}
$ ./output/host/bin/arm-linux-gnueabihf-gcc -o ede-gpio-app \
    ../ede-gpio-app/ede-gpio-app.c -lgpiod
\end{verbatim}
    \end{block}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]{Running the application on the target}
  \begin{itemize}
  \item Copy it to the target:
    \begin{block}{}
\begin{verbatim}
$ scp ede-gpio-app root@192.168.42.2:
\end{verbatim}
    \end{block}
  \item And run it:
    \begin{block}{}
\begin{verbatim}
# ./ede-gpio-app
\end{verbatim}
    \end{block}
  \end{itemize}
\end{frame}

\begin{frame}{Buildroot package for our application}
  \begin{itemize}
  \item Building manually is fine for quick experiments, but we
    definitely want the build process to be fully automated by
    Buildroot.
  \item In order to do this, one can create new {\bf packages} for the
    different applications/libraries that should be compiled and
    installed in the target root filesystem.
  \item A package in Buildroot consists of:
    \begin{itemize}
    \item \code{package/<pkg>/Config.in}, describing the configuration
      options, in the {\em kconfig} syntax
    \item \code{package/<pkg>/<pkg>.mk}, describing how to download,
      build and install the package, written in {\em make}
    \item \code{package/<pkg>/<pkg>.hash}, containing hashes to
      validate that the downloaded have the expected contents
    \item \code{package/<pkg>/*.patch}, patches to apply to the
      package source code, if needed
    \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]{Creating the package: {\tt Config.in}}

  \begin{block}{package/ede-gpio-app/Config.in}
\begin{verbatim}
config BR2_PACKAGE_EDE_GPIO_APP
        bool "ede-gpio-app"
        depends on BR2_TOOLCHAIN_HEADERS_AT_LEAST_4_8 # libgpiod
        select BR2_PACKAGE_LIBGPIOD
        help
          This is the EDE GPIO demo application.

comment "ede-gpio-app needs kernel headers >= 4.8"
        depends on !BR2_TOOLCHAIN_HEADERS_AT_LEAST_4_8
\end{verbatim}
  \end{block}

\end{frame}

\begin{frame}[fragile]{Creating the package: including {\tt Config.in}}

  \begin{block}{package/Config.in}
\begin{verbatim}
...
       source "package/ede-gpio-app/Config.in"
...
\end{verbatim}
  \end{block}

  You can run \code{make menuconfig}, and see that your new option is there!

\end{frame}

\begin{frame}[fragile]{Creating the package: {\tt ede-gpio-app.mk}}

  \begin{block}{package/ede-gpio-app/ede-gpio-app.mk}
    {\tiny
\begin{verbatim}
################################################################################
#
# ede-gpio-app
#
################################################################################

EDE_GPIO_APP_SITE = $(TOPDIR)/../ede-gpio-app
EDE_GPIO_APP_SITE_METHOD = local
EDE_GPIO_APP_DEPENDENCIES = libgpiod

define EDE_GPIO_APP_BUILD_CMDS
    $(TARGET_MAKE_ENV) $(MAKE) $(TARGET_CONFIGURE_OPTS) -C $(@D)
endef

define EDE_GPIO_APP_INSTALL_TARGET_CMDS
    $(TARGET_MAKE_ENV) $(MAKE) $(TARGET_CONFIGURE_OPTS) -C $(@D) \
        DESTDIR=$(TARGET_DIR) install
endef

$(eval $(generic-package))
\end{verbatim}
    }
  \end{block}

\end{frame}

\begin{frame}{Creating the package: using it}

  \begin{itemize}

  \item Enable your new package in \code{make menuconfig}

  \item Run the build with \code{make}

  \item Reflash your SD card and reboot

  \item Your new application is in \code{/usr/bin} on the target

  \end{itemize}

\end{frame}

\begin{frame}{Documentation and support}
  \begin{itemize}
  \item Extensive manual:
    \url{https://buildroot.org/downloads/manual/manual.html}
  \item 3-day training course, with freely available materials:
    \url{https://bootlin.com/training/buildroot/}
  \item Mailing list:
    \url{http://lists.busybox.net/pipermail/buildroot/}
  \item IRC channel: \code{buildroot} on Freenode
  \end{itemize}
\end{frame}


\end{document}
