[bootlin/training-materials updates] master: labs/sysdev-buildroot: build kernel and modules in the Buildroot lab (3076c225)

Michael Opdenacker michael.opdenacker at bootlin.com
Wed Nov 2 14:35:31 CET 2022


Repository : https://github.com/bootlin/training-materials
On branch  : master
Link       : https://github.com/bootlin/training-materials/commit/3076c225b063ec22c8447f183ad5e16bcdc102f7

>---------------------------------------------------------------

commit 3076c225b063ec22c8447f183ad5e16bcdc102f7
Author: Michael Opdenacker <michael.opdenacker at bootlin.com>
Date:   Fri Oct 28 17:18:04 2022 +0200

    labs/sysdev-buildroot: build kernel and modules in the Buildroot lab
    
    To address bug https://github.com/bootlin/training-materials/issues/136
    
    Signed-off-by: Michael Opdenacker <michael.opdenacker at bootlin.com>


>---------------------------------------------------------------

3076c225b063ec22c8447f183ad5e16bcdc102f7
 ...ysdev-application-development-and-debugging.tex |  33 +--
 labs/sysdev-buildroot/sysdev-buildroot.tex         | 229 +++++++++++++++------
 .../sysdev-system-integration.tex                  |  46 +++--
 3 files changed, 203 insertions(+), 105 deletions(-)

diff --git a/labs/sysdev-application-development-and-debugging/sysdev-application-development-and-debugging.tex b/labs/sysdev-application-development-and-debugging/sysdev-application-development-and-debugging.tex
index ee239fe0..74420611 100644
--- a/labs/sysdev-application-development-and-debugging/sysdev-application-development-and-debugging.tex
+++ b/labs/sysdev-application-development-and-debugging/sysdev-application-development-and-debugging.tex
@@ -345,41 +345,14 @@ step.
 Let's make a quick attempt at profiling our application with the
 \code{perf} command.
 
-To add \code{perf} to the root filesystem, we have to build it from
-kernel sources (see \kdir{tools/perf} in the kernel source code), and
-the \code{perf} version has to be in sync with the kernel version.
-
-That's why, to build \code{perf}, Buildroot builds the kernel at the
-same time. In our case, we don't have time to integrate the kernel in
-the image built by Buildroot, but that's something a real project will
-ultimately do.
-
-So, go back to Buildroot's configuration interface and, in the
+So, let's make Buildroot add \code{perf} to our root filesystem.
+Go back to Buildroot's configuration interface and, in the
 \code{Kernel} menu:
 \begin{itemize}
-\item Enable \code{Linux Kernel}
-\item Set \code{Kernel version} to \code{Custom version}
-\item Set \code{Custom version} to the exact \workingkernel ~version
-      you used.
-\item Set \code{Kernel configuration} to \code{Using a custom (def)config file})
-\item Set \code{Configuration file path} to the full path of your kernel \code{.config} file.
 \item In \code{Linux Kernel Tools}, enable \code{perf}
 \end{itemize}
 
-Then run \code{make}, and once this is done, update your root
-filesystem. This will take time to recompile the kernel again, together
-with all its modules. You can start working on the {\em Going further}
-section to save time though.
-
-By the way, why didn't we make Buildroot deploy the Linux kernel,
-modules and DTB directly to the root filesystem? We would have done that
-pretty easily, and you would do this in a real project, if we didn't
-have our of tree module.
-
-To build an external kernel module with Buildroot, it would have required
-adding a special package for this purpose, but our time is limited.
-
-Once the new root filesystem is ready, you can now run:
+Once updated the root filesystem, you can run:
 
 \begin{bashinput}
 perf record /root/nunchuk-mpd-client
diff --git a/labs/sysdev-buildroot/sysdev-buildroot.tex b/labs/sysdev-buildroot/sysdev-buildroot.tex
index dcea0ff6..cc02bf8a 100644
--- a/labs/sysdev-buildroot/sysdev-buildroot.tex
+++ b/labs/sysdev-buildroot/sysdev-buildroot.tex
@@ -1,7 +1,7 @@
 \subchapter{Using a build system, example with Buildroot}{Objectives:
   discover how a build system is used and how it works, with the
-  example of the Buildroot build system. Build a Linux system with
-  libraries and make it work on the board.}
+  example of the Buildroot build system. Build a full Linux system,
+  including the Linux kernel.}
 
 \section{Goals}
 
@@ -14,6 +14,9 @@ The automated build system will also allow us to add more packages
 and play real audio on our system, thanks to the {\em Music Player
 Daemon (mpd)} (\url{https://www.musicpd.org/} and its {\em mpc} client.
 
+As in a real project, we will also build the Linux kernel from
+Buildroot, and install the kernel modules in the root filesystem.
+
 \section{Setup}
 
 Go to the \code{$HOME/__SESSION_NAME__-labs/buildroot} directory.
@@ -32,6 +35,8 @@ are:
 \item \code{boot} contains the Makefiles and configuration items
   related to the compilation of common bootloaders (GRUB, U-Boot,
   Barebox, etc.)
+\item \code{board} contains board specific configurations and
+  root filesystem overlays.
 \item \code{configs} contains a set of predefined configurations,
   similar to the concept of defconfig in the kernel.
 \item \code{docs} contains the documentation for Buildroot. You can
@@ -53,60 +58,23 @@ are:
   configuration items to generate the cross-compiling toolchain.
 \end{itemize}
 
-\section{Prepare an overlay directory}
-
-To play audio in this lab, we will need to add the kernel modules to
-the root filesystem generated by Buildroot, and make sure that the
-\code{snd-usb-audio} module is automatically loaded at boot time. Note
-that it would be better to have the Linux kernel built by Buildroot,
-so that the kernel modules are automatically installed into the root
-filesystem. But for our quick experiment, we'll just copy the kernel
-modules we already have.
+\section{Board specific configuration}
 
-So, let's prepare an overlay directory (in the main lab directory)
-that Buildroot will use after building the root filesystem:
+As we will want Buildroot to build a kernel with a custom configuration
+and a custom filesystem, let's add our own subdirectory under
+\code{board}:
 
 \begin{bashinput}
-mkdir -p rootfs-overlay/lib
-cp -a ../tinysystem/nfsroot/lib/modules rootfs-overlay/lib/
+mkdir -p board/bootlin/stm32mp1-training
 \end{bashinput}
 
-Let's also add a custom configuration for MPD, as the standard one
-provided by Buildroot doesn't support allowing to change the audio
-playback volume with all sound cards we have tested. We will simply
-add this file to our overlay:
+Then, copy your kernel configuration:
 
 \begin{bashinput}
-mkdir -p rootfs-overlay/etc
-cp data/mpd.conf rootfs-overlay/etc/
+cp ../../kernel/linux/.config board/bootlin/stm32mp1-training/linux.config
 \end{bashinput}
 
-Also add a \code{etc/init.d/S03modprobe} executable file
-to the overlay directory, with the below contents:
-
-\begin{verbatim}
-#!/bin/sh
-modprobe snd-usb-audio
-modprobe nunchuk
-\end{verbatim}
-
-The \code{S03} prefix of this file makes sure it is executed
-before {\em Music Player Daemon}, which will have a greater
-prefix (\code{S95}). That's necessary because this daemon will
-fail to start is audio is not available.
-
-We're also loading the \code{nunchuk.ko} module as we are
-going to test the Nunchuk later in this lab.
-
-Let's also add music files \footnote{For the most part, these are public domain
-music files, except a small sample file... See the \code{README.txt}
-file in the directory containing the files.}
-for MPD to play:
-
-\begin{bashinput}
-mkdir -p rootfs-overlay/var/lib/mpd/music
-cp data/music/* rootfs-overlay/var/lib/mpd/music/
-\end{bashinput}
+We will configure Buildroot to use this kernel configuration.
 
 \section{Configure Buildroot}
 
@@ -116,6 +84,8 @@ In our case, we would like to:
 \item Generate an embedded Linux system for ARM;
 \item Use an already existing external toolchain instead of having
   Buildroot generating one for us;
+\item Compile the Linux kernel and deploy its modules in the root
+  filesystem;
 \item Integrate {\em BusyBox}, {\em alsa-utils}, {\em libgpiod},
   {\em mpd}, {\em mpc} and {\em evtest} in our embedded Linux system;
 \item Integrate the target filesystem into a tarball
@@ -170,10 +140,18 @@ button whenever you need more details about a given option:
     \code{Toolchain has C++ support?}.
     Buildroot will check these parameters anyway.
   \end{itemize}
-\item \code{System configuration}
+\item \code{Kernel}
   \begin{itemize}
-  \item \code{Root filesystem overlay directories}: \code{../rootfs-overlay}
-  \end{itemize}
+  \item Enable \code{Linux Kernel}
+  \item Set \code{Kernel version} to \code{Custom Git repository}
+  \item Set \code{Custom repository version} to \code{bootlin-labs}
+  \item Set \code{URL of custom repository} to code{file:///../../kernel/linux}
+	(you can also use an absolute path)
+  \item Set \code{Kernel configuration} to \code{Using a custom (def)config file})
+  \item Set \code{Configuration file path} to \code{board/bootlin/stm32mp1-training/linux.config}
+  \item Select \code{Build a Device Tree Blob (DTB)}
+  \item Set \code{In-tree Device Tree Source file names} to \code{stm32mp157a-dk1-custom}
+\end{itemize}
 \item \code{Target packages}
   \begin{itemize}
   \item Keep \code{BusyBox} (default version) and keep the BusyBox
@@ -235,9 +213,10 @@ explore its contents:
   {\em makedevs}, {\em fakeroot}).
 
 \item \code{images}, which contains the final images produced by
-  Buildroot. In our case it's just a tarball of the filesystem, called
-  \code{rootfs.tar}, but depending on the Buildroot configuration,
-  there could also be a kernel image or a bootloader image.
+  Buildroot. In our case it contains a tarball of the filesystem, called
+  \code{rootfs.tar}, plus the compressed kernel and Device Tree binary.
+  Depending on the configuration, there could also a bootloader binary
+  or a full SD card image.
 
 \item \code{staging}, which contains the “build” space of the target
   system. All the target libraries, with headers and documentation. It
@@ -262,16 +241,80 @@ exported over NFS. Go into this directory, and untar the rootfs using:
 \bashcmd{$ tar xvf ../buildroot/output/images/rootfs.tar}
 
 Add our \code{nfsroot} directory to the list of directories exported
-by NFS in \code{/etc/exports}, and make sure the board uses it too.
+by NFS in \code{/etc/exports}.
+
+Also update the kernel and Device Tree binaries used by your board,
+from the ones compiled by Buildroot in \code{output/images/}.
 
 Boot the board, and log in (\code{root} account, no password).
 
 You should now reach a shell.
 
-Check that the \code{snd_usb_audio} module is loaded as expected.
+\section{Loading the USB audio module}
+
+You can check that no kernel module is loaded yet. Try to load the
+\code{snd_usb_audio} module from the command line.
+
+This should work. Check that Buildroot has deployed the modules
+for your kernel in \code{/lib/modules}.
+
+Let's automate this now!
+
+Look at the \code{/etc/inittab} file generated by Buildroot (ask your
+instructor if you have any questions), and at the contents of the
+\code{/etc/init.d/} directory, in particular of the \code{rcS} file.
+
+You can see that \code{rcS} executes or sources all the \code{/etc/init.d/S??*}
+files. We can add our own which will load the toplevel modules that we
+need.
+
+Let's do this by creating an {\em overlay directory}, typically under
+our board specific directory, that Buildroot will add after building the
+root filesystem:
+
+\begin{bashinput}
+mkdir -p board/bootlin/stm32mp1-training/rootfs-overlay/
+\end{bashinput}
+
+Then add a custom startup script, by adding an \code{etc/init.d/S03modprobe}
+executable file to the overlay directory, with the below contents:
+
+\begin{verbatim}
+#!/bin/sh
+modprobe snd-usb-audio
+\end{verbatim}
+
+Then, go back to Buildroot's configuration interface:
+\begin{itemize}
+\item \code{System configuration}
+  \begin{itemize}
+  \item Set \code{Root filesystem overlay directories} to
+        \code{board/bootlin/stm32mp1-training/rootfs-overlay}
+  \end{itemize}
+\end{itemize}
+
+Build your image again. This should be quick as Buildroot doesn't need
+to recompile anything. It will just apply the root filesystem overlay.
+
+Update your \code{nfsroot} directory, reboot the board and check
+that the \code{snd_usb_audio} module is loaded as expected.
+
+You can run \code{speaker-test} to check that audio indeed works.
 
 \section{Testing music playback with mpd and mpc}
 
+The next thing we want to do is play real sound samples with
+the {\em Music Player Daemon (MPD)}. So, let's add music files
+\footnote{For the most part, these are public domain
+music files, except a small sample file... See the \code{README.txt}
+file in the directory containing the files.}
+for MPD to play:
+
+\begin{bashinput}
+mkdir -p board/bootlin/stm32mp1-training/rootfs-overlay/var/lib/mpd/music
+cp ../data/music/* board/bootlin/stm32mp1-training/rootfs-overlay/var/lib/mpd/music
+\end{bashinput}
+
 Using the \code{ps} command, check that the \code{mpd} server
 was started by the system, as implemented by the
 \code{/etc/init.d/S95mpd} script.
@@ -326,6 +369,20 @@ Here are a few further commands for controlling playback:
 \item \code{mpc toggle}: toggle between pause and playback modes.
 \end{itemize}
 
+If you find that changing the volume is not available, you can
+add a custom configuration for MPD, as the standard one
+provided by Buildroot doesn't support allowing to change the audio
+playback volume with all sound cards we have tested. We will simply
+add this file to our overlay:
+
+\begin{bashinput}
+cp ../data/mpd.conf board/bootlin/stm32mp1-training/rootfs-overlay/etc/
+\end{bashinput}
+
+Run Buildroot again, update your root filesystem, reboot (to get MPD
+restarted with the new configuration file), and make sure modifying
+the volume now works.
+
 Later, we will compile and debug a custom MPD client application.
 
 \section{Analyzing dependencies}
@@ -351,11 +408,56 @@ required to compile {\em Meson} for the host, and in turn,
 {\em Python 3} for the host too. This substantially contributed to the
 build time.
 
+\section{Adding a Buildroot package}
+
+We would also like to build our Nunchuk external module with Buildroot.
+Fortunately, Buildroot has a \code{kernel-module} infrastructure
+to build kernel modules.
+
+First, create a \code{nunchuk-driver} subdirectory under \code{package}
+in Buildroot sources.
+
+The first thing is to create a \code{package/nunchuk-driver/Config.in} file
+for Buildroot's configuration:
+
+\begin{verbatim}
+config BR2_PACKAGE_NUNCHUK_DRIVER
+        bool "nunchuk-driver"
+        depends on BR2_LINUX_KERNEL
+        help
+                Linux Kernel module for the I2C Nunchuk.
+\end{verbatim}
+
+Then include this file from \code{package/Config.in}, for example right
+before the line including \code{package/nvidia-driver/Config.in},
+so that the alphabetic order of configuration options is kept.
+
+Then, the next and last thing you need to do is create
+\code{package/nunchuk-driver/nunchuk-driver.mk} describing how to build
+the package:
+
+\begin{verbatim}
+NUNCHUK_DRIVER_VERSION = 1.0
+NUNCHUK_DRIVER_SITE = $(HOME)/embedded-linux-labs/hardware/data/nunchuk
+NUNCHUK_DRIVER_SITE_METHOD = local
+NUNCHUK_DRIVER_LICENSE = GPL-2.0
+
+$(eval $(kernel-module))
+$(eval $(generic-package))
+\end{verbatim}
+
+Then, configure Buildroot to build your package, run Buildroot and
+update your root filesystem.
+
+Can you load the \code{nunchuk} module now? If everything's fine, add a
+line to \code{/etc/init.d/S03modprobe} for this driver, and update your
+root filesystem once again.
+
 \section{Testing the Nunchuk}
 
-Now that we have compiled \code{evtest} for the target, thanks to
-Buildroot, we can now test the input events coming from the
-Nunchuk.
+Now that we have the \code{nunchuk} driver loaded and that Buildroot compiled
+\code{evtest} for the target, thanks to Buildroot, we can now test the input
+events coming from the Nunchuk.
 
 \begin{bashinput}
 # evtest
@@ -377,6 +479,17 @@ By the way, you can also test which input events are exposed by the
 driver for your audio headset, which doesn't mean that they physically
 exist.
 
+\section{Commit your changes}
+
+As we are going to reuse our Buildroot changes in the next labs,
+let's commit them into a branch:
+
+\begin{bashinput}
+git checkout -b bootlin-labs
+git add board/bootlin/ package/nunchuk-driver/
+git commit -as -m "Bootlin lab changes"
+\end{bashinput}
+
 \section{Going further}
 
 {\em If you finish your lab before the others}
diff --git a/labs/sysdev-system-integration/sysdev-system-integration.tex b/labs/sysdev-system-integration/sysdev-system-integration.tex
index 3a696be4..379dda59 100644
--- a/labs/sysdev-system-integration/sysdev-system-integration.tex
+++ b/labs/sysdev-system-integration/sysdev-system-integration.tex
@@ -14,29 +14,25 @@ Since {\em systemd} requires the GNU C library, we are going
 to make a new Buildroot build in a new working directory, and
 using a different cross-compiling toolchain.
 
-So, create the \code{$HOME/__SESSION_NAME__-labs/integration} directory.
+So, create the \code{$HOME/__SESSION_NAME__-labs/integration} directory
+and go inside it.
 
-Make a new clone of Buildroot from the existing local Git repository.
-
-\section{Root filesystem overlay}
-
-Copy the root filesystem overlay from the previous lab, but remove
-the \code{etc/init.d/S03modprobe} file, as with {\em systemd}, the
-way to load modules will be different:
+Make a new clone of Buildroot from the existing local Git repository,
+and checkout our \code{bootlin-labs} branch:
 
 \begin{bashinput}
-cp -a ../buildroot/rootfs-overlay .
-rm -rf rootfs-overlay/etc/init.d
+git clone $HOME/embedded-linux-labs/buildroot/buildroot
+cd buildroot
+git checkout bootlin-labs
 \end{bashinput}
 
-We also have to move the modules in \code{/lib/modules} to
-\code{/usr/lib/modules} in the overlay, because using {\em systemd}
-will require Buildroot to make \code{/lib} become a symbolic
-link to \code{/usr/lib}:
+\section{Root filesystem overlay}
+
+Remove \code{etc/init.d/} from the root filesystem overlay.
+It was adapted to {\em BusyBox init}, not to {\em systemd}:
 
 \begin{bashinput}
-mkdir rootfs-overlay/usr
-mv rootfs-overlay/lib rootfs-overlay/usr/
+rm -r ./board/bootlin/stm32mp1-training/rootfs-overlay/etc/init.d/
 \end{bashinput}
 
 \section{Buildroot configuration}
@@ -63,7 +59,19 @@ Configure Buildroot as follows:
   \begin{itemize}
   \item \code{Init system}: \code{systemd}
   \item \code{Run a getty (login prompt) after boot}, \code{TTY port}: \code{ttySTM0}
-  \item \code{Root filesystem overlay directories}: \code{../rootfs-overlay}
+  \item \code{Root filesystem overlay directories}: \code{board/bootlin/stm32mp1-training/rootfs-overlay}
+  \end{itemize}
+\item \code{Kernel}
+  \begin{itemize}
+  \item Enable \code{Linux Kernel}
+  \item Set \code{Kernel version} to \code{Custom Git repository}
+  \item Set \code{URL of custom repository} to \code{file:///../../kernel/linux}
+        (you can also use an absolute path)
+  \item Set \code{Custom repository version} to \code{bootlin-labs}
+  \item Set \code{Kernel configuration} to \code{Using a custom (def)config file})
+  \item Set \code{Configuration file path} to \code{board/bootlin/stm32mp1-training/linux.config}
+  \item Select \code{Build a Device Tree Blob (DTB)}
+  \item Set \code{In-tree Device Tree Source file names} to \code{stm32mp157a-dk1-custom}
   \end{itemize}
 \item \code{Target packages}
   \begin{itemize}
@@ -81,6 +89,10 @@ Configure Buildroot as follows:
     \item Select \code{ltrace}
     \item Select \code{strace}
     \end{itemize}
+  \item \code{Hardware handling}
+    \begin{itemize}
+    \item Select \code{nunchuk driver}
+    \end{itemize}
   \item \code{Networking applications}
     \begin{itemize}
     \item Select \code{dropbear}, a lightweight SSH server used instead




More information about the training-materials-updates mailing list