Book Image

Linux Device Driver Development Cookbook

By : Rodolfo Giometti
Book Image

Linux Device Driver Development Cookbook

By: Rodolfo Giometti

Overview of this book

Linux is a unified kernel that is widely used to develop embedded systems. As Linux has turned out to be one of the most popular operating systems worldwide, the interest in developing proprietary device drivers has also increased. Device drivers play a critical role in how the system performs and ensure that the device works in the manner intended. By exploring several examples on the development of character devices, the technique of managing a device tree, and how to use other kernel internals, such as interrupts, kernel timers, and wait queue, you’ll be able to add proper management for custom peripherals to your embedded system. You’ll begin by installing the Linux kernel and then configuring it. Once you have installed the system, you will learn to use different kernel features and character drivers. You will also cover interrupts in-depth and understand how you can manage them. Later, you will explore the kernel internals required for developing applications. As you approach the concluding chapters, you will learn to implement advanced character drivers and also discover how to write important Linux device drivers. By the end of this book, you will be equipped with the skills you need to write a custom character driver and kernel code according to your requirements.
Table of Contents (14 chapters)
10
Additional Information: Managing Interrupts and Concurrency

Setting up the host machine

As every good device driver developer knows, a host machine is absolutely necessary.
Even if the embedded devices are getting more powerful nowadays (and the ESPRESSObin
is one of these), there are some resource-consuming tasks where a host machine can help.
That's why, in this section, we're going to show how to set up our host machine.

The host machine we decide to use could be a normal PC or a virtualized one—they are equivalentbut the important thing is that it must run a GNU/Linux-based OS.

Getting ready

In this book, I will use an Ubuntu 18.04 LTS based system but you can decide to try to replicate some settings and installation commands that we will use during the course of this book into another major Linux distribution, with little effort for a Debian derivative, or in a bit more of a complicated manner in the case of non-Debian derivative distributions.

I'm not going to show how to install a fresh Ubuntu system on a PC nor on a virtualized machine since it's a really easy task for a real programmer; however, as the last step of this chapter (the Doing native compiling on foreign hardware recipe), I will introduce, with detailed steps about how to install it, an interesting cross-platform environment that proved useful to compile foreign target code on the host machine as we were on the target. This procedure is very useful when we need several different OSes running on your development PC.

So, at this point, the reader should have their own PC running (natively or virtualized) a fresh installed Ubuntu 18.04 LTS OS.

The main usage of a host PC is to edit and then cross-compile our new device drivers and to manage our target device via the serial console, to create its root filesystem, and so on.

In order to do it properly, we need some basic tools; some of them are general while others depend on the specific platform onto which we are going to write our drivers.

General tools are surely an editor, a version control system, and a compiler and its related components, while specific platform tools are essentially the cross-compiler and its related components (on some platforms we may need additional tools but our mileage may vary and, in any case, each manufacturer will give us all of the needed requirements for a comfortable compilation environment).

About the editor: I'm not going to spend any words on it because the reader can use whatever they want (regarding myself, for example, I'm still programming with vi editor) but regarding others tools, I'll have to be more specific.

How to do it...

Now that our GNU/Linux distribution is up and running on our host PC we can start to install some programs we're going to use in this book:

  1. First of all, let's install the basic compiling tools:
$ sudo apt install gcc make pkg-config \
bison flex ncurses-dev libssl-dev \
qemu-user-static debootstrap
As you know already, the sudo command is used to execute a command as a privileged user. It should be already present in your system, otherwise you can install it by using the apt install sudo command as the root user.
  1. Next, we have to test the compiling tools. We should be able to compile a C program. As a simple test, let's use the following standard Hello World code stored in the helloworld.c file:
#include <stdio.h>

int main(int argc, char *argv[])
{
printf("Hello World!\n");

return 0;
}
Remember that code can be downloaded from our GitHub repository.
  1. Now, we should be able to compile it by using the following command:
$ make CFLAGS="-Wall -O2" helloworld
cc -Wall -O2 helloworld.c -o helloworld

In the preceding command, we used both the compiler and the make tool, which is required to compile every Linux driver in a comfortable and reliable manner.

You can get more information regarding make by taking a look at https://www.gnu.org/software/make/, and for gcc, you can go to https://www.gnu.org/software/gcc/.
  1. Finally, we can test it on the host PC, as follows:
$ ./helloworld 
Hello World!
  1. The next step is to install the cross-compiler. Since we're going to work with an ARM64 system, we need a cross-compiler and its related tools. To install them, we simply use the following command:
$ sudo apt install gcc-7-aarch64-linux-gnu
Note that we can also use an external toolchain as reported in the ESPRESSObin wiki at http://wiki.espressobin.net/tiki-index.php?page=Build+From+Source+-+Toolchain; however, the Ubuntu toolchain works perfectly!
  1. When the installation is complete, test our new cross-compiler by using the preceding Hello World program, as follows:
$ sudo ln -s /usr/bin/aarch64-linux-gnu-gcc-7 /usr/bin/aarch64-linux-gnu-gcc
$ make CC=aarch64-linux-gnu-gcc CFLAGS="-Wall -O2" helloworld
aarch64-linux-gnu-gcc-7 -Wall -O2 helloworld.c -o helloworld
Note that I've removed the previously compiled helloworld program in order to be able to correctly compile this new version. To do so, I used the mv helloworld helloworld.x86_64 command due to the fact I'll need the x86 version again.

Also, note that since Ubuntu doesn't automatically create the standard cross-compiler name, aarch64-linux-gnu-gcc, we have to do it manually by using the preceding ln command before executing make.
  1. OK, now we can verify that newly created version of the helloworld program for ARM64 by using the following file command. This will point out which platform the program is compiled for:
$ file helloworld
helloworld: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, for GNU/Linux 3.7.0, BuildID[sha1]=c0d6e9ab89057e8f9101f51ad517a253e5fc4f10, not stripped

If we again use the file command on the previously renamed version, helloworld.x86_64, we get the following:

$ file helloworld.x86_64 
helloworld.x86_64: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=cf932fab45d36f89c30889df98ed382f6f648203, not stripped
  1. To test whether this new release is really for the ARM64 platform, we can use QEMU, which is an open source and generic machine emulator and virtualizer that is able to execute foreign code on the running platform. To install it, we can use apt command as in the preceding code, specifying the qemu-user-static package:
$ sudo apt install qemu-user-static
  1. Then, we can execute our ARM64 program:
$ qemu-aarch64-static -L /usr/aarch64-linux-gnu/ ./helloworld
Hello World!
To get further information about QEMU, a good staring point is its home page at https://www.qemu.org/.
  1. The next step is to install the version control system. We must install the version control system used for the Linux project, that is, git. To install it, we can use the following command in a similar manner as before:
$ sudo apt install git

If everything works well, we should be able to execute it as follows:

$ git --help
usage: git [--version] [--help] [-C <path>] [-c <name>=<value>]
[--exec-path[=<path>]] [--html-path] [--man-path]
[--info-path] [-p | --paginate | --no-pager]
[--no-replace-objects] [--bare] [--git-dir=<path>]
[--work-tree=<path>] [--namespace=<name>]
<command> [<args>]

These are common Git commands used in various situations:

start a working area (see also: git help tutorial)
clone Clone a repository into a new directory
init Create an empty Git repository or reinitialise an existing one
...
In this book, I'm going to explain every git command used but for complete knowledge of this powerful tool, I suggest you start reading https://git-scm.com/.

See also