Introduction
This is the chapter web page to support the content in Chapter 16 of the book: Exploring Raspberry Pi – Interfacing to the Real World with Embedded Linux. The summary introduction to the chapter is as follows:
In this chapter, you are introduced to Linux kernel programming on an embedded device such as the Raspberry Pi (RPi). Kernel programming is an advanced topic that requires in-depth study of the source code for the Linux kernel; however, this chapter is structured as a practical step-by-step guide to the focused task of writing Linux loadable kernel modules (LKMs) that interface to general-purpose inputs/outputs (GPIOs). The first example is a straightforward “Hello World” module that can be used to establish a configuration for LKM development on the RPi. The second LKM example introduces interrupt service routines (ISRs), and interfaces a simple GPIO button and LED circuit to Linux kernel space. Two further examples are provided that introduce the kobject interface and the use of kernel threads to build kernel-space sysfs devices for the RPi. By the end of this chapter, you should be familiar with the steps required to write kernel code, and appreciate the programming constraints that such development entails.
After completing this chapter, you should hopefully be able to do the following:
- Write a basic Linux loadable kernel module (LKM) that can receive a kernel argument.
- Build, load, and unload a custom LKM on a desktop machine and/or the RPi.
- Undertake the steps required to build a module for embedded devices that can control GPIOs.
- Appreciate some of the concepts required to build LKMs on an embedded Linux device, such as interrupts, kobjects, and kernel threads.
Digital Media Resources
Video Demonstration
A short YouTube video is provided here that presents an overview of the functionality of the type of LKMs that are developed in this chapter.
The LKM examples in Chapter 16 focus on interfacing to GPIOs and the use of sysfs. However, you might also be interested in a blog discussion “Writing a Linux Kernel Module — Part 2: A Character Device,” on writing a straightforward character driver that can be used to pass information between a Linux user-space program and a loadable kernel module (LKM), which is running in Linux kernel space. In this example, a C user-space application sends a string to the LKM. The LKM then responds with the message that was sent along with the number of letters that the sent message contains. Later in the article I describe why we need to solve synchronization problems that arise with this approach, and I provide a version of the program that uses mutexes to provide a solution.
External Resources
Errata
None for the moment
Recommended Books on the Content in this Chapter
First build of on rpi. In the book: “Finally, you can build the LKM with a call to make. Do not use sudo make;…”. Got error when running as pi user:
pi@ba0025A0011 ~/exploringpi $ make
make -C /lib/modules/4.4.41+/build/ M=/home/pi/exploringpi modules
make[1]: *** /lib/modules/4.4.41+/build/: Permission denied. Stop.
Makefile:4: recipe for target ‘all’ failed
make: *** [all] Error 2
Instead, I returned to root (sudo bash) in order to compile the LKM,
pi@ba0025A0011 ~/exploringpi $ sudo bash
root@ba0025A0011:/home/pi/exploringpi# make
make -C /lib/modules/4.4.41+/build/ M=/home/pi/exploringpi modules
make[1]: Entering directory ‘/usr/src/raspberrypi-linux-4897c5c’
CC [M] /home/pi/exploringpi/hello.o
Building modules, stage 2.
MODPOST 1 modules
CC /home/pi/exploringpi/hello.mod.o
LD [M] /home/pi/exploringpi/hello.ko
make[1]: Leaving directory ‘/usr/src/raspberrypi-linux-4897c5c’
Got a segmentation fault when trying to insert the module hello.ko. Any suggestions for how to debug the problem?
root@ba0025A0011:/home/pi/exploringpi# insmod hello.ko
Message from syslogd@ba0025A0011 at Jan 12 07:52:43 …
kernel:[ 163.531914] Internal error: Oops: 5 [#1] ARM
Message from syslogd@ba0025A0011 at Jan 12 07:52:43 …
kernel:[ 163.591118] Process insmod (pid: 2668, stack limit = 0xd847a188)
Message from syslogd@ba0025A0011 at Jan 12 07:52:43 …
kernel:[ 163.594115] Stack: (0xd847be88 to 0xd847c000)
…
Another try. Started with a new wheezy image, then update and upgrade, resulting in (uname -r) 4.1.19+.
Followed the instructions in ch16 for rpi (instead of rpi2/3). Everything went smooth until insmod
root@raspberrypi:/home/pi/exploringrpi/chp16/hello# insmod hello.ko
Error: could not insert module hello.ko: Invalid module format
pi@raspberrypi ~ $ tail /var/log/messages
Jan 12 10:17:28 raspberrypi kernel: [ 2723.011383] hello: disagrees about version of symbol module_layout
Suggestions for how to proceed?
Checked with modinfo
pi@raspberrypi ~/exploringrpi/chp16/hello $ modinfo hello.ko
filename: /home/pi/exploringrpi/chp16/hello/hello.ko
version: 0.1
description: A simple Linux LKM for the RPi.
author: Derek Molloy
license: GPL
srcversion: 579146BC11D4158697739F2
depends:
vermagic: 4.1.21 mod_unload modversions ARMv6
parm: name:The name to display in /var/log/kern.log (charp)
Vermagic info is not the same as uname -r (4.1.19+) – can that be the cause for the error message from insmod?
Have tried to build hello.c with other Module.symvers found at https://github.com/raspberrypi/firmware/commits/master/extra/Module.symvers. Tried both 4.1.19 and 4.1.21. However, for both of these, make returns the following error
pi@raspberrypi ~/exploringrpi/chp16/hello $ make
make -C /lib/modules/4.1.19+/build/ M=/home/pi/exploringrpi/chp16/hello modules
make[1]: Entering directory ‘/usr/src/raspberrypi-linux-ff45bc0’
CC [M] /home/pi/exploringrpi/chp16/hello/hello.o
Building modules, stage 2.
MODPOST 1 modules
FATAL: parse error in symbol dump file
scripts/Makefile.modpost:90: recipe for target ‘__modpost’ failed
make[2]: *** [__modpost] Error 1
Makefile:1387: recipe for target ‘modules’ failed
make[1]: *** [modules] Error 2
make[1]: Leaving directory ‘/usr/src/raspberrypi-linux-ff45bc0’
Makefile:4: recipe for target ‘all’ failed
make: *** [all] Error 2
Checkout rpi-source from https://github.com/notro/rpi-source/wiki. It’s makes it super easy to install the linux headers on rpi 1 and 2.