Issue
If your Internet of Things (IoT) device built using a Raspberry Pi is inconsistent with GPIO communication, the cause maybe the kernel. The Raspberry Pi OS ships with a kernel tuned for “desktop” applications so that is responsive to user input. For example, this may result in missed GPIO reads and writes when moving the mouse.
Solution
Switching to a real-time kernel such as RTLinux helps insure your GPIO communication is more consistent.
Building the kernel takes a long time so use the fastest Pi you have. For this tutorial, the steps were performed on a Pi400 for a SD card that will be used in a Raspberry Pi Zero 2 W.
This tutorial distills the information in the following documents into a step-by-step guide. Read these sites to best understand what each step is and how to make adjustments for your setup.
- RaspberryPi – The Linux Kernel: This document discusses various ways of building, configuring and patching the kernel. The extra information such as cross-compilation can loose a new reader. This tutorial derives much from this documentation, therefore it is highly advantageous to read this site while following this tutorial.
- Building the
PREEMPT_RT
-patched Linux Kernel: This site has helpful information on configuring the kernel. However, it seems to be dated since it is missing a step that enables the real-time kernel menu option. - Linux RT Kernel: This is the repository for the RT kernel patches.
0) Before we begin you may want to install “Raspberry Pi OS Lite” (no desktop) on a SD card using the Raspberry Pi Imager. Next update the OS to the latest version then reboot.
sudo apt update
sudo apt full-upgrade
sudo apt install raspberrypi-kernel-headers
sudo reboot
1) Install the required tools to configure and build the kernel.
sudo apt install git bc bison flex libssl-dev make libncurses5-dev
2) Create then change to the directory where the patch will be downloaded and built.
mkdir --parents ~/source && cd ~/source
3) Clone the kernel source for the Raspberry Pi.
git clone --depth=1 https://github.com/raspberrypi/linux
4) Get the RT kernel patch and apply it.
- Run the command uname -r to see which version of the Linux kernel you currently have installed.
- Search the RT kernel patch site to find the kernel patch version matching your kernel version.
- For this tutorial, uname returned “6.6.31+rpt-rpi-v8” therefore the wget URL is https://mirrors.edge.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patch-6.6.31-rt31.patch.gz
- Unzip the patch.
- Patch the linux kernel with the RT patch. Again, you will need to edit the command to specify the correct version.
wget https://mirrors.edge.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patch-6.6.31-rt31.patch.gz
gunzip patch-6.6.31-rt31.patch.gz
cd linux
patch -p1 -i ../patch-6.6.31-rt31.patch
5) Set the config variables based on this table and the version of your current kernel. This tutorial is building a 64-bit kernel.
64-bit kernel | Raspberry Pi 3, 3+, 4, 400 and Zero 2 W, and Raspberry Pi Compute Modules 3, 4 and 4S | KERNEL=kernel8 make bcm2711_defconfig |
Raspberry Pi 5 | KERNEL=kernel8 make bcm2711_defconfig |
KERNEL=kernel8
make bcm2711_defconfig
CONFIG_LOCALVERSION="-6.6.31-rt31-patched"
6) Using menuconfig, follow these steps to configure the kernel for real-time.
- Uncheck “Virtualization” in the main menu
- Select “General setup —>”
- Select “Preemption Model (Preemptible Kernel (Low-Latency Desktop)) —>”
- Check “Fully Preemptible Kernel (Real-Time)”. This is listed if step 5 is completed.
- Select “Timers subsystem –>”
- Uncheck “Old Idle dynticks config” (Skip this for pi3 models.) SEE: Linux PREEMPT-RT kernel tuning example for EPICS IOC
- Check “High Resolution Timer Support”
- Select “<Exit>” to return to menu “General setup”
- Select “<Exit>” to return to go up to top level
- Select “Kernel features —>”
- Select “Timer Frequency (250HZ) —>”
- Check “1000Hz”
- Select “<Exit>” to return to go up to top level
- Select “<Exit>” to exit and save
- Choose Yes to save your new configuration
make menuconfig
7) (Only for pi3) Set the kernel version in config.txt depending on the rt patch you’ve installed.
- Edit /boot/config.txt
- Look for section [pi3+]
- kernel=vmlinuz-6.6.31-rt31
sudo nano /boot/config.txt
8) Build and install the kernel.
make -j6 Image.gz modules dtbs
sudo make -j6 modules_install
sudo cp /boot/firmware/$KERNEL.img /boot/firmware/$KERNEL-backup.img
sudo cp arch/arm64/boot/Image.gz /boot/firmware/$KERNEL.img
sudo cp arch/arm64/boot/dts/broadcom/*.dtb /boot/firmware/
sudo cp arch/arm64/boot/dts/overlays/*.dtb* /boot/firmware/overlays/
sudo cp arch/arm64/boot/dts/overlays/README /boot/firmware/overlays/
9) If no errors have occurred, the final step is to reboot the computer. After the reboot, verify the new kernel by running uname -srvo. For this tutorial uname returned "Linux 6.6.34-rt31-v8+ #1 SMP PREEMPT_RT Mon Jun 24 00:54:08 CDT 2024 GNU/Linux". Notice "PREEMPT_RT" in the name, RT is for real time.
uname -srvo
Conclusion
Linux has different kernels tuned for specific purposes such as general desktop computing and IoT devices. The Raspberry Pi OS ships with a kernel tuned for desktop applications. For IoT development, the real-time kernel will provide a more consistent communication with sensors and PWM controlled devices.
Thank you to René Vogel for determining the settings needed for the pi3+.