0% found this document useful (0 votes)
23 views

Chapter 1

Uploaded by

duyhuy362003
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
23 views

Chapter 1

Uploaded by

duyhuy362003
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 22

1

Building the System


The Linux kernel is one of the largest and most successful open source projects that has ever come
about. The huge rate of change and the number of individual contributors shows that it has a
vibrant and active community, constantly stimulating evolution of the kernel. This rate of change
continues to increase, as does the number of developers and companies involved in the process.
The development process has proved that it is able to scale up to higher speeds without trouble.
The Linux kernel together with GNU software and many other open-source components provides
a completely free operating system, GNU/Linux. Embedded Linux is the usage of the Linux kernel
and various open-source components in embedded systems.
Embedded Linux is used in embedded systems such as consumer electronics (e.g., set-top boxes,
smart TVs, PVRs (personal video recorders), IVI (in-vehicle infotainment), networking equipment
(such as routers, switches, WAPs (wireless access points) or wireless routers), machine control,
industrial automation, navigation equipment, spacecraft flight software, and medical instruments
in general).
There are many advantages of using Linux in embedded systems. The following list shows some
of these benefits:
• The main advantage of Linux is the ability to reuse components. Linux provides scalability
due to its modularity and configurability.
• Open source. No royalties or licensing fees.
• Ported to a broad range of hardware architectures, platforms and devices.
• Broad support of applications and communication protocols (e.g., TCP/IP stack, USB stack,
graphical toolkit libraries).
• Large support coming from an active community of developers.
These are the main components of an embedded Linux system: Bootloader, Kernel, System
call interface, C-Runtime library, System shared libraries and Root filesystem. Each of these
components will be described in more detail in the next sections.

[ 19 ]
Building the System Chapter 1

Bootloader
Linux cannot be started on an embedded device without a small amount of machine specific code
to initialize the system. Linux requires the bootloader code to do very little, although several
bootloaders do provide extensive additional functionality. The minimal requirements are:
• Configuration of the memory system.
• Loading of the kernel image and the Device Tree at the correct addresses.
• Optional loading of an initial RAM disk at the correct memory address.
• Setting of the kernel command-line and other parameters (e.g., Device Tree, machine type).
It is also usually expected that the bootloader initializes a serial console for the kernel in addition
to these basic tasks.
There are different bootloader options that come in all shapes and sizes. U-Boot is the standard
bootloader for ARM Linux. U-Boot source code is located at https://source.denx.de/u-boot/u-boot.
These are some of the main U-Boot features:
1. Small: U-Boot is a bootloader, and its primary purpose in the system is to load an
operating system. That means that U-Boot is necessary to perform a certain task, but it is
not worth spending significant resources on. Typically, U-Boot is stored in the relatively
small NOR flash memory, which is expensive compared to the much larger NAND
devices normally used to store the operating system and the application. A usable and
useful configuration of U-Boot, including a basic interactive command interpreter, support
for download over Ethernet and the capability to program the flash should fit in no more
than 128 KB.
2. Fast: The end user is not interested in running U-Boot. In most embedded systems, they
are not even aware that U-Boot exists. The user wants to run some application code, and
they want to do that as soon as possible after switching on the device. Initialize devices
only when they are needed within U-Boot, i.e., don't initialize the Ethernet interface(s)
unless U-Boot performs a download over Ethernet; don't initialize any IDE or USB devices
unless U-Boot actually tries to load files from these, etc.
3. Portable: U-Boot is a bootloader, but it is also a tool used for board bring-up, for
production testing and for other activities that are very closely related to hardware
development. So far, it has been ported to several hundreds of different boards on about
30 different processor families.
4. Configurable: U-Boot is a powerful tool with many, many extremely useful features.
The maintainer or user of each board will have to decide which features are important

[ 20 ]
Chapter 1 Building the System

and what shall be included with their specific board configuration to meet the current
requirements and restrictions.
5. Debuggable: U-Boot is not only a tool in itself, it is often also used for hardware bring-up,
so debugging U-Boot often means that you don't know if you are tracking down a problem
in the U-Boot software or in the hardware you are running on. Code that is clean and easy
to understand and debug is all the more important to everyone. One important feature of
U-Boot is to enable output to the (usually serial) console as soon as possible in the boot
process, even if this causes tradeoffs in other areas like memory footprint. All initialization
steps shall print some "begin doing this" message before they actually start and some
"done" message when they complete. The purpose of this is that you can always see which
initialization step was running if any problems occur. This is important not only during
software development, but also for the service people dealing with broken hardware in the
field. U-Boot should be debuggable with simple JTAG or BDM equipment. It should use a
simple, single-threaded execution model.

[ 21 ]
Building the System Chapter 1

Linux kernel
Linux is a clone of the operating system Unix, written from scratch by Linus Torvalds with
assistance from a loosely-knit team of hackers across the Net. It aims towards POSIX and Single
UNIX Specification compliance.
It has all the features you would expect in a modern, fully-fledged Unix implementation, including
true multitasking, virtual memory, shared libraries, demand loading, shared copy-on-write
executables, proper memory management and multistack networking including IPv4 and IPv6.
Although originally developed for 32-bit x86-based PCs (386 or higher), today Linux also runs on a
multitude of other processor architectures, in both 32-bit and 64-bit variants.
The Linux kernel is the lowest level of software running on a Linux system. It is charged with
managing the hardware, running user programs and maintaining the overall security and integrity
of the whole system. It is this kernel, which, after its initial release by Linus Torvalds in 1991,
jump-started the development of Linux as a whole. The kernel is a relatively small part of the
software on a full Linux system (many other large components come from the GNU project, the
GNOME and KDE desktop projects, the X.org project and many other sources), but the kernel is
the core which determines how well the system will work and is the piece which is truly unique to
Linux.
The kernel, which forms the core of the Linux system, is the result of one of the largest cooperative
software projects ever attempted. Regular two-to-three month releases deliver stable updates to
Linux users, each with significant new features, added device support and improved performance.
The rate of change in the kernel is high and increasing, with over 10,000 patches going into each
recent kernel release. Each of these releases contains the work of more than 1,600 developers
representing over 200 corporations.
As kernels move from the mainline into the stable category, two things can happen:
1. They can reach End of Life after a few bugfix revisions, which means that kernel
maintainers will release no more bugfixes for this kernel version, or
2. They can be put into longterm maintenance, which means that maintainers will provide
bugfixes for this kernel revision for a much longer period of time.
If the kernel version you are using is marked EOL, you should consider upgrading to the next
major version, as there will be no more bugfixes provided in the kernel version you are using.
Linux kernel is released under GNU GPL version 2 and is therefore Free Software as defined by
the Free Software Foundation. You may read the entire copy of the license in the COPYING file
distributed with each release of the Linux kernel.

[ 22 ]
Chapter 1 Building the System

Some of the subsystems the kernel is comprised of are listed below:


• /arch/<arch>: Architecture specific code.
• /arch/<arch>/<mach>: Machine/board specific code.
• /Documentation: Kernel documentation. Do not miss it!
• /ipc: Inter process communication.
• /mm: Memory management.
• /fs: File systems.
• /include: Linux kernel headers.
• /include/asm-<arch>: Architecture and machine dependent headers.
• /include/linux: Linux kernel core headers.
• /init: Linux initialization (including main.c).
• /block: Linux kernel block layer code.
• /net: Networking functionality.
• /lib: Common kernel helper functions.
• /kernel: Common kernel structures.
• /arch: Architecture specific code.
• /crypto: Cryptography code.
• /security: Security components.
• /drivers: Built-in drivers (does not include loadable modules).
• Makefile: Top Linux makefile (sets arch and version).
• /scripts: Scripts for internal or external use.
The official home for the mainline Linux kernel source code is www.kernel.org. You can download
the source code either directly from the kernel.org website as a compressed tar.xz file, or you can
download it through git, the kernel´s preferred source code control system.
There are several main categories into which kernel releases may fall:
1. Prepatch: Prepatch or "RC" kernels are mainline kernel pre-releases that are mostly aimed
at other kernel developers and Linux enthusiasts. They must be compiled from source
and usually contain new features that must be tested before they can be put into a stable
release. Prepatch kernels are maintained and released by Linus Torvalds.
2. Mainline: The mainline tree is maintained by Linus Torvalds. It's the tree where all new
features are introduced and where all the exciting new development happens. New
mainline kernels are released every 2-3 months.
3. Stable: After each mainline kernel is released, it is considered "stable". Any bug fixes for
a stable kernel are backported from the mainline tree and applied by a designated stable
kernel maintainer. There are usually only a few bugfix kernel releases until next mainline

[ 23 ]
Building the System Chapter 1

kernel becomes available -- unless it is designated a "longterm maintenance kernel". Stable


kernel updates are released on as-needed basis, usually 2-3 a month.
4. Longterm: There are usually several "longterm maintenance" kernel releases provided for
the purposes of backporting bugfixes for older kernel trees. Only important bugfixes are
applied to such kernels, and they don't usually see very frequent releases, especially for
older trees.
In the following image, extracted from www.kernel.org, you can see the latest stable kernel, kernels
under development (mainline, next), stable and long term kernels.

In addition to the official versions of the kernel, there are many third-parties (chip-vendors,
sub-communities) that supply and maintain their own version of the kernel sources by forking
from the official kernel tree. The intent is to separately develop support for a particular piece of
hardware or subsystem and to integrate this support to the official kernel at a later point. This
process is called mainlining and describes the task to integrate the new feature or hardware
support to the upstream (official) kernel. These are called Distribution kernels.
It is easy to tell if you are running a Distribution kernel. Unless you downloaded, compiled and
installed your own version of kernel from www.kernel.org, you are running a Distribution kernel. To
find out the version of your kernel, run uname -r after booting the processor.

[ 24 ]
Chapter 1 Building the System

You will work with the longterm kernel 5.4.y releases to develop all the drivers throughout this
book.

System call interface and C runtime library


The system call is the fundamental interface between an application and the Linux kernel. System
calls are the only means by which a user space application can interact with the kernel. In other
words, they are the bridge between user space and kernel space. The strict separation of user
and kernel space ensures that user space programs cannot freely access kernel internal resources,
thereby ensuring the security and stability of the system. The system calls elevate the privilege of
the user process.
The system call interface is generally not invoked directly (even though it could be) but rather
through wrapper functions in the C runtime library. Some of these wrapper functions are only
very thin layers over the system call (just checking and setting the call parameters) while others
add additional functionality. The following image shows some system calls and their descriptions:

The C runtime library (C-standard library) defines macros, type definitions and functions for
string handling, mathematical functions, input/output processing, memory allocation and several
other functions that rely on OS services. The runtime library provides applications with access to
OS resources and functions by abstracting the OS System call interface.
Several C runtime libraries are available: glibc, uClibc, eglibc, dietlibc, newlib. The choice of the C
library must be made at the time of the cross-compiling toolchain generation, as the GCC compiler
is compiled against a specific C library.
The GNU C library, glibc, is the default C library used for example in the Yocto project. The
GNU C Library is primarily designed to be a portable and high performance C library. It follows
all relevant standards including ISO C11 and POSIX.1-2008. It is also internationalized and has

[ 25 ]
Building the System Chapter 1

one of the most complete internationalization interfaces known. You can find the glibc manual at
https://www.gnu.org/software/libc/manual/.

System shared libraries


System shared libraries are libraries that are loaded by programs when they start. When a shared
library is installed properly, all programs that start afterwards automatically use the new shared
library. System shared libraries are typically linked with a user space application to provide its
access to a specific system functionality. This system functionality can be either self-contained
like compression or encryption algorithms or require access to underlying kernel resources or
hardware. In the latter case, the library provides a simple API that abstracts the complexities of the
kernel or direct driver access.
In other words, system shared libraries encapsulate system functionality and therefore are an
essential building block when building applications that interact with the system.
Every shared library has a special name called the "soname". The soname has the prefix "lib",
the name of the library, the phrase ".so", followed by a period and a version number that is
incremented whenever the interface changes (as a special exception, the lowest-level C libraries
don't start with "lib"). A fully-qualified soname includes as a prefix the directory it's in. In a
working system, a fully-qualified soname is simply a symbolic link to the shared library's "real
name".
Every shared library also has a "real name", which is the filename containing the actual library
code. The real name adds a period to the soname, a minor number, another period and the release
number. The last period and the release number are optional. The minor number and release
number support configuration control by letting you know exactly what version(s) of the library
are installed. Note that these numbers might not be the same as the numbers used to describe the
library in documentation, although that does make things easier.
In addition, there's the name that the compiler uses when requesting a library, (call it the "linker
name"), which is simply the soname without any version number.
The following system shared libraries are required by the LSB (Linux Standard Base) specification
and therefore must be available on all LSB compliant systems:

• Libc: Standard C library (C runtime library). Elementary language support and OS


platform services. Direct access to the OS System-Call-Interface.
• Libm: Math Library. Common elementary mathematical functions and floating point
environment routines defined by System V, ANSI C, POSIX, etc.

[ 26 ]
Chapter 1 Building the System

• Libpthread: POSIX thread library. Functionality now in libc, maintained to provide


backwards compatibility.
• Libdl: Dynamic Linker Library. Functionality now in libc, maintained to provide
backwards compatibility.
• Libcrypt: Cryptology Library. Encryption and decryption handling routines.
• Libpam: PAM (Pluggable Authentication Module) library. Routines for the PAM.
• Libz: Compression/decompression library. General purpose data compression and
deflation functionality.
• Libncurses: CRT screen handling and optimization package. Overall screen, window
and pad manipulation; output to windows and pads; reading terminal input; control
over terminal and cursor input and output options; environment query routines; color
manipulation; use of soft label keys.
• Libutil: System utilities library. Various system-dependent utility routines used in a
wide variety of system daemons. The abstracted functions are mostly related to pseudo-
terminals and login accounting.
Libraries are placed in the following standard root filesystem locations:
• /lib: Libraries required for startup.
• /usr/lib: Most system libraries.
• /usr/local/lib: Non-system libraries.
Note: A large part of the text of this section has been extracted from the Linux Documentation
Project. You can find all the complete information at https://tldp.org/HOWTO/Program-Library-
HOWTO/shared-libraries.html.

Root filesystem
The root filesystem is where all the files contained in the file hierarchy (including device nodes) are
stored. The root filesystem is mounted as /, containing all the libraries, applications and data.
The folder structure of the root filesystem is defined by FHS (Filesystem-Hierarchy-Standard). The
FHS defines the names, locations and permissions for many file types and directories. It thereby
ensures compatibility between different Linux distributions and allows applications to make
assumptions about where to find specific system files and configurations.
An embedded Linux root filesystem, usually includes the following:
• /bin: Commands needed during bootup that might be used by normal users (probably
after bootup).

[ 27 ]
Building the System Chapter 1

• /sbin: Like /bin, but the commands are not intended for normal users, although they may
use them if necessary and allowed; /sbin is not usually in the default path of normal users,
but will be in root's default path.
• /etc: Configuration files specific to the machine.
• /home: Like My Documents in Windows.
• /root: The home directory for user root. This is usually not accessible to other users on the
system.
• /lib: Essential shared libraries and kernel modules.
• /dev: Device files. These are special virtual files that help the user interface with the
various devices on the system.
• /tmp: Temporary files. As the name suggests, programs running often store temporary files
in here.
• /boot: Files used by the bootstrap loader. Kernel images are often kept here instead of in
the root directory. If there are many kernel images, the directory can easily grow too large,
and it might be better to keep it in a separate filesystem.
• /mnt: Mount point for mounting a filesystem temporarily.
• /opt: Add-on application software packages.
• /usr: Secondary hierarchy.
• /var: Variable data.
• /sys: Exports information about devices and drivers from the kernel device model to user
space, and it is also used for configuration.
• /proc: Represent the current state of the kernel.

Linux boot process


These are the main stages of the Linux boot process for the BCM2837 SoC:
1. The boot process begins at POR (Power On Reset), where the hardware reset turns ON the
VideoCore GPU (CPU is OFF), which executes the 1st stage bootloader from the on-chip
boot ROM. At this point, DRAM memory controller is disabled.
2. The 1st stage bootloader reads the 2nd stage bootloader (bootcode.bin) from the SD card,
loads it into the GPU´s L2 cache and executes it on the GPU. The 2nd stage bootloader
sets up the DRAM memory controller, then loads the GPU firmware (start.elf) from the SD
card and runs it. The GPU firmware reads the system configuration parameters (config.
txt), loads a kernel image (kernel7.img) and a Device Tree file (bcm2710-rpi-3-b.dtb) into the
DRAM memory, and releases the reset signal on the ARM CPU.
3. The image kernel7.img is then run on the ARM CPU.

[ 28 ]
Chapter 1 Building the System

4. The kernel runs low level kernel initialization, enabling MMU, creating the initial table of
memory pages and setting up caches. This is done in arch/arm/kernel/head.s. The file head.s
contains CPU architecture specific, but platform independent initialization code. Then, the
system switches to the non architecture specific kernel startup function start_kernel().
5. The kernel runs start_kernel() located in init/main.c that:
• Initializes the kernel core (e.g., memory, scheduling, interrupts).
• Initializes statically compiled drivers.
• Mounts the root filesystem based on bootargs passed to the kernel from U-Boot.
• Executes the first user process, init. The init process, by default, is /init for initramfs
and /sbin/init for a regular filesystem. The three init programs that you usually find on
embedded Linux devices are BusyBox init, System V init and systemd.

Building an embedded Linux system for the Raspberry


Pi
Building an embedded Linux system requires you to:
1. Select a cross toolchain. The toolchain is the starting point for the development process, as
it is used to build all subsequent software packages. The toolchain consists of the following
parts: Assembler, Compiler, Linker, Debugger, Runtime Libraries and Utilities. A cross
compiler is a compiler capable of creating executable code for a platform other than the
one on which the compiler is running.
2. Select the different packages that will run on the target (bootloader, kernel and root
filesystem).
3. Configure and build these packages.
4. Deploy them on the device.
There are several different ways to build an embedded Linux system:
1. Manually (creating your own scripts): This option gives you total control, but it is also tedious
and harder to reproduce builds on other machines. It also requires a good understanding of
the software component installation process. For example, create a root filesystem from the
ground up by yourself means:
• Download the source code of all software components (libraries, utilities and applications).
• Solve all dependencies and version conflicts, and apply patches.
• Configure each software component.
• Cross-compile each software component.

[ 29 ]
Building the System Chapter 1

• Install each software component.


2. Using complete distributions (e.g., Ubuntu/Debian): Easy to get started, but harder to
customize. A Linux distribution is a preselected kernel version and a root filesystem with a
preselected set of libraries, utilities and applications.
3. Using build frameworks (e.g., Buildroot, Yocto): This option allows you to customize and
reproduce builds easily. This is becoming the most popular option in the embedded Linux
space. A Build framework typically consists of scripts and configuration meta-data that control
the build process. The Build framework typically downloads, configures, compiles and installs
all required components of the system, taking version conflicts and dependencies into account.
It allows, for example to create a customized root filesystem. The Build framework output is a
complete image, including toolchain, bootloader, kernel and root filesystem.

Raspberry Pi OS
Raspberry Pi OS is the recommended operating system for normal use on a Raspberry Pi. Raspberry
Pi OS is a free operating system based on Debian, optimised for the Raspberry Pi hardware.
Raspberry Pi OS comes with over 35,000 packages: precompiled software bundled in a nice format
for easy installation on your Raspberry Pi. Raspberry Pi OS is a community project under active
development, with an emphasis on improving the stability and performance of as many Debian
packages as possible.
You will install on a Micro SD a Raspberry Pi OS image based on kernel 5.4.y. Go to https://
downloads.raspberrypi.org/raspios_full_armhf/images/raspios_full_armhf-2020-12-04/ and download the
2020-12-02-raspios-buster-armhf-full.zip image.
To write the compressed image on the Micro SD card, you will download and install Etcher. This
tool, which is an Open Source software, is useful since it allows to get a compressed image as
input. More information and extra help is available on the Etcher website at https://etcher.io/.
Once the image is installed on the Micro SD card, you will insert the Micro SD into the SD card
reader on your host PC, then you will enable UART, SPI and I2C peripherals in the programmed
Micro SD. Open a terminal application on your host PC, and type the following commands:
~$ lsblk
~$ mkdir ~/mnt
~$ mkdir ~/mnt/fat32
~$ mkdir ~/mnt/ext4
~$ sudo mount /dev/mmcblk0p1 ~/mnt/fat32

See the files in the fat32 partition. Check that config.txt is included:
~$ ls -l ~/mnt/fat32/

[ 30 ]
Chapter 1 Building the System

Update the config.txt file, adding the next values:


~$ cd ~/mnt/fat32/
~/mnt/fat32$ sudo nano config.txt
dtparam=i2c_arm=on
dtparam=spi=on
dtoverlay=spi0-cs
# Enable UART
enable_uart=1
kernel=kernel7.img
~$ sudo umount ~/mnt/fat32

You can also update previous settings (after booting the Raspberry Pi board) through the
Raspberry Pi Configuration application found in Preferences on the menu.

The Interfaces tab is where you turn these different connections on or off so that the Pi recognizes
that you’ve linked something to it via a particular type of connection.

[ 31 ]
Building the System Chapter 1

Connect and set up hardware


Follow the next steps to get everything connected to your Raspberry Pi. It’s important to do this in
the right order so that all your components are safe:
1. Insert the Micro SD card you’ve set up with Raspberry Pi OS into the Micro SD card slot
on the underside of your Raspberry Pi board.

[ 32 ]
Chapter 1 Building the System

2. Connect your screen to the single Raspberry Pi’s HDMI port. You can also connect a
mouse to a USB port and keyboard in the same way.

3. Connect the Ethernet port on Raspberry Pi to an Ethernet socket on your host PC.

[ 33 ]
Building the System Chapter 1

4. The serial console is a helpful tool for debugging your board and reviewing system log
information. To access the serial console, connect a USB to TTL Serial Cable to the device
UART pins as shown below.

5. Plug the USB power supply into a socket and connect it to your Raspberry Pi’s power port.

The hardware setup is already done!!

[ 34 ]
Chapter 1 Building the System

You should see a red LED light up, which indicates that the Raspberry Pi board is connected to
power. As it starts up, you will see raspberries appear in the top left-hand corner of your screen.
After a few seconds the Raspberry Pi OS Desktop will appear.

For the official Raspberry Pi OS, the default user name is pi, with password raspberry.
To find out the version of the booted kernel, run uname -r on the Raspberry Pi terminal:
pi@raspberrypi:~$ uname -r
5.4.79-v7+

Reset the board. You can disconnect your screen from the Raspberry Pi’s HDMI port during the
development of the labs (you will only need to connect a screen in the LAB 10.3).
pi@raspberrypi:~$ sudo reboot

To see Linux boot messages on the console, add loglevel=8 in the file cmdline.txt under /boot.
pi@raspberrypi:~$ sudo nano /boot/cmdline.txt

To change your current console_loglevel simply write to this file:


pi@raspberrypi:~$ echo <loglevel> > /proc/sys/kernel/printk

For example:
pi@raspberrypi:~$ echo 8 > /proc/sys/kernel/printk

Now, every kernel message will appear on your console, as all priority higher than 8 (lower loglevel
values) will be displayed. Please note that after reboot, this configuration is reset. To keep the

[ 35 ]
Building the System Chapter 1

configuration permanently, just append the following kernel.printk value to the /etc/sysctl.conf file,
then reboot the processor:
kernel.printk = 8 4 1 3
pi@raspberrypi:~$ sudo nano /etc/sysctl.conf
pi@raspberrypi:~$ sudo reboot

Setting up an ethernet communication


Connect an Ethernet cable between your host PC and the Raspberry Pi board. Set up the IP
Address of the host PC.
1. On the host side, click on the Network Manager tasklet on your desktop, and select Edit
Connections. Choose "Wired connection 1" and click "Edit".
2. Choose the "IPv4 Settings" tab, and select Method as "Manual" to make the interface use
a static IP address, for example 10.0.0.1. Click "Add", and set the IP address, the Netmask
and Gateway as follow:
Address: 10.0.0.1
Netmask: 255.255.255.0
Gateway: none or 0.0.0.0
Finally, click the "Save" button.
3. Click on "Wired connection 1" to activate this network interface.

Copying files to your Raspberry Pi


You can access the command line of a Raspberry Pi remotely from another computer or device
on the same network using SSH. Make sure the Raspberry Pi is properly set up and connected.
Configure on the Raspberry Pi the eth0 interface with IP address 10.0.0.10:
pi@raspberrypi:~$ sudo ifconfig eth0 10.0.0.10 netmask 255.255.255.0

Raspbian has the SSH server disabled by default. You have to start the service on the Pi:
pi@raspberrypi:~# sudo /etc/init.d/ssh restart

Now, verify that you can ping your Linux host machine from the Raspberry Pi. Exit the ping
command by typing "Ctrl-c":
pi@raspberrypi:~# ping 10.0.0.1

You can also ping from Linux host machine to the target. Exit the ping command by typing
"Ctrl-c".
~$ ping 10.0.0.10

[ 36 ]
Chapter 1 Building the System

By default, the root account is disabled, but you can enable it by using this command and giving it
a password, for example "pi":
pi@raspberrypi:~$ sudo passwd root

Now, you can log into your pi as the root user. Open the sshd_config file, and change
PermitRootLogin to yes (also comment the line out). After editing the file, type "Ctrl+x", then type
"yes", and press "enter" to exit:
pi@raspberrypi:~$ sudo nano /etc/ssh/sshd_config

Building the Linux kernel


There are two main methods for building the kernel. You can build locally on the Raspberry Pi,
which will take a long time, or you can cross-compile, which is much quicker, but requires more
setup. You will use the second method.
Install Git and the build dependencies:
~$ sudo apt install git bc bison flex libssl-dev make libc6-dev libncurses5-dev

On your host PC, create the linux_rpi3 folder, where you are going to download the kernel sources:
~$ mkdir linux_rpi3
~$ cd linux_rpi3/

Get the kernel sources. The git clone command below will download the current active branch
without any history. Omitting the --depth=1 will download the entire repository, including the full
history of all branches, but this takes much longer and occupies much more storage.
~/linux_rpi3$ git clone --depth=1 -b rpi-5.4.y https://github.com/raspberrypi/linux

Install the 32-bit toolchain for a 32-bit kernel:


~$ sudo apt install crossbuild-essential-armhf

Compile the kernel, modules and Device Tree files. First, apply the default configuration:
~/linux_rpi3/linux$ KERNEL=kernel7
~/linux_rpi3/linux$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- bcm2709_defconfig

Configure the following kernel settings that will be needed during the development of the labs:
~/linux_rpi3/linux$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
Device drivers >
[*] SPI support --->
<*> User mode SPI device driver support

Device drivers >


<*> Industrial I/O support --->
-*- Enable buffer support within IIO

[ 37 ]
Building the System Chapter 1

-*- Industrial I/O buffering based on kfifo


<*> Enable IIO configuration via configfs
-*- Enable triggered sampling support
<*> Enable software IIO device support
<*> Enable software triggers support
Triggers - standalone --->
<*> High resolution timer trigger
<*> SYSFS trigger

Device drivers >


<*> Userspace I/O drivers --->
<*> Userspace I/O platform driver with generic IRQ handling

Device drivers >


Input device support --->
-*- Generic input layer (needed for keyboard, mouse, ...)
<*> Polled input device skeleton

For the LAB 12.1, you will need the functions that enable the triggered buffer support. If they are
not defined accidentally by another driver, there's an error thrown out while linking. To solve
this problem, you can select, for example, the HTS221 driver, which includes this triggered buffer
support:
Device drivers >
<*> Industrial I/O support > Humidity sensors --->
<*> STMicroelectronics HTS221 sensor Driver

Save the configuration, and exit from menuconfig.


Compile kernel, Device Tree files and modules in a single step:
~/linux_rpi3/linux$ make -j4 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage modules dtbs

Having built the kernel, you need to copy it onto your Raspberry Pi device and also install the
modules. Insert the previously programmed Micro SD into the SD card reader on your host PC,
and execute the following commands:
~$ lsblk
~$ mkdir ~/mnt
~$ mkdir ~/mnt/fat32
~$ mkdir ~/mnt/ext4
~$ sudo mount /dev/mmcblk0p1 ~/mnt/fat32
~$ sudo mount /dev/mmcblk0p2 ~/mnt/ext4/
~$ cd linux_rpi3/linux
~/linux_rpi3/linux$ sudo env PATH=$PATH make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
INSTALL_MOD_PATH=~/mnt/ext4 modules_install

[ 38 ]
Chapter 1 Building the System

Finally, update kernel, Device Tree files and modules:


~/linux_rpi3/linux$ sudo cp ~/mnt/fat32/kernel7.img ~/mnt/fat32/kernel7-backup.img
~/linux_rpi3/linux$ sudo cp arch/arm/boot/zImage ~/mnt/fat32/kernel7.img
~/linux_rpi3/linux$ sudo cp arch/arm/boot/dts/*.dtb ~/mnt/fat32/
~/linux_rpi3/linux$ sudo cp arch/arm/boot/dts/overlays/*.dtb* ~/mnt/fat32/overlays/
~/linux_rpi3/linux$ sudo cp arch/arm/boot/dts/overlays/README ~/mnt/fat32/overlays/
~$ sudo umount ~/mnt/fat32
~$ sudo umount ~/mnt/ext4

Insert the Micro SD card you’ve set up in the Micro SD card slot on the underside of your
Raspberry Pi, and connect the Raspberry Pi´s UART (through a USB to serial adapter) to a Linux
PC's USB. On Linux PC, launch Minicom utility as shown below (for debugging purpose):
~$ sudo minicom –s

Set baud rate and other setting as per below:


1. Baud rate 115200
2. Parity none
3. Hardware flow control/software flow control none
4. Serial device /dev/ttyUSB0
5. Parity none
After the Raspberry Pi board boots up, it will display a login console on Minicom terminal on
Linux. The username for the board is "pi" and password is "raspberry".
To find out the version of your new kernel, boot the system and run uname -r:
pi@raspberrypi:~$ uname -r
5.4.83-v7+

If you modify and compile the kernel or Device Tree files later, you can copy them to the
Raspberry Pi remotely using the secure copy protocol (SCP). You need to connect previously an
Ethernet cable between the Raspberry Pi board and your host PC.
~/linux_rpi3/linux$ scp arch/arm/boot/zImage [email protected]:/boot/kernel7.img

Copy the following .dtb file if you are using the Raspberry Pi 3 Model B board:
~/linux_rpi3/linux$ scp arch/arm/boot/dts/bcm2710-rpi-3-b.dtb [email protected]:/boot/

Copy the following .dtb file if you are using the Raspberry Pi 3 Model B+ board:
~/linux_rpi3/linux$ scp arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dtb [email protected]:/boot/

[ 39 ]

You might also like