Linux Device Drivers
Creating (and testing) Linux Device Drivers using the Raspberry Pi
There are plenty of articles / websites devoted to writing a Linux Device Driver. Using some of these (documented below), we'll go over the basics, and then dive into some details. Linux device drivers fall into one of two camps, "Modular" or "Built In", depending on how it's built. It's even possible a device driver can be part of both camps. We'll examine the "Module", since if the driver is written to function well as a "module", it can often function well as a"built in" driver.
We'll start with Hello World example:
Hello World Example
Create a folder, "hello-1", and copy the following to "hello-1.c" withing that folder:
$ mkdir hello-1 $ cd hello-1 $ mousepad hello-1.c &
/* * hello-1.c - The simplest kernel module. */ #include <linux/module.h> /* Needed by all modules */ #include <linux/kernel.h> /* Needed for KERN_INFO */ int init_module(void) { printk(KERN_INFO "Hello world 1.\n"); /* * A non 0 return means init_module failed; module can't be loaded. */ return 0; } void cleanup_module(void) { printk(KERN_INFO "Goodbye world 1.\n"); }
Before we can begin to build (and test) this example kernel module, the kernel source code for current version of Linux running on the Pi needs to be installed on the unit.
Determine the version of Linux running on the Pi:
$ uname -a Example
pi@raspberrypi:~ $ uname -a Linux raspberrypi 4.19.118-v7l+ #1311 SMP Mon Apr 27 14:26:42 BST 2020 armv7l GNU/Linux
From the above example, we can see the Raspberry Pi is running 4.19.118-v7l+. This is the version of Linux contained in 2020-05-27-raspios-buster-full-armhf.img. We need to install the source code for 4.19.118-v7l+. https://www.raspberrypi.org/documentation/linux/kernel/building.md
As the Raspberry Pi "Kernel Building" example indicate, we need to install a few tools first (some of these may already be installed):
$ sudo apt install git bc bison flex libssl-dev make
Only a few of the above packages need installation (the others are already installed). The packages are small and install quickly.
The hard part is determining the "git" command needed to bring in the correct source code. (We don't want the latest, since it appears to be 4.19.127)
See: https://github.com/raspberrypi/linux https://www.raspberrypi.org/forums/viewtopic.php?t=257155 https://www.kernel.org/doc/Documentation/kbuild/modules.txt https://www.raspberrypi.org/documentation/linux/kernel/headers.md
According to the above, I'm running 32-bit armv7 with Long Addresses (for the Pi4 increased ram size) If we are not building the kernel itself (building only Modules), we only need to install the kernel header files, without the source files.
Install the kernel header files for the Raspberry Pi
pi@raspberrypi:~ $ sudo apt-get install raspberrypi-kernel-headers Reading package lists... Done Building dependency tree Reading state information... Done The following package was automatically installed and is no longer required: rpi-eeprom-images Use 'sudo apt autoremove' to remove it. The following NEW packages will be installed: raspberrypi-kernel-headers 0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded. Need to get 24.9 MB of archives. After this operation, 163 MB of additional disk space will be used. Get:1 http://archive.raspberrypi.org/debian buster/main armhf raspberrypi-kernel-headers armhf 1.20200601-1 [24.9 MB] Fetched 24.9 MB in 1min 36s (259 kB/s) Selecting previously unselected package raspberrypi-kernel-headers. (Reading database ... 156472 files and directories currently installed.) Preparing to unpack .../raspberrypi-kernel-headers_1.20200601-1_armhf.deb ... Unpacking raspberrypi-kernel-headers (1.20200601-1) ... Setting up raspberrypi-kernel-headers (1.20200601-1) ...
Assuming you copied the above hello-1.c code into the file, "hello-1.c", copy the following into "Makefile":
$ mousepad Makefile &
#Makefile for hello-1 module obj-m += hello-1.o all: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
Build the hello-1 module
$ make