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.
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 PREEMPT-RT kernel tuning example for EPICS IOC: In addition to switching to a real-time kernel, this site discusses additional tuning options such as switching the system timers for better performance.
- Linux RT Kernel: This is the repository for the RT kernel patches.
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.
A) Run the command uname -r to see which version of the Linux kernel you currently have installed. For this tutorial, uname returned “5.15.38-rt41-v8+” therefore, the code below is fetching the closest matching version of the patch.
B) Next search the RT kernel patch site to find the kernel patch for your kernel version.
C) Update the command below with the correct version by replacing the section “/5.15/older/patch-5.15.36-rt41.patch.gz”.
D) Unzip the patch.
E) 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/5.15/older/patch-5.15.36-rt41.patch.gz
gunzip patch-5.15.36-rt41.patch.gz
cd linux
patch -p1 -i ../patch-5.15.36-rt41.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.
32-bit kernel | Raspberry Pi 1, Zero and Zero W, and Raspberry Pi Compute Module 1 | KERNEL=kernel make bcmrpi_defconfig |
Raspberry Pi 2, 3, 3+ and Zero 2 W, and Raspberry Pi Compute Modules 3 and 3+ | KERNEL=kernel7 make bcm2709_defconfig |
|
Raspberry Pi 4 and 400, and Raspberry Pi Compute Module 4 | KERNEL=kernel7l make bcm2711_defconfig | |
64-bit kernel | Raspberry Pi 3, 3+, 4, 400 and Zero 2 W, and Raspberry Pi Compute Modules 3, 3+ and 4 | KERNEL=kernel8 make bcm2711_defconfig |
KERNEL=kernel8
make bcm2711_defconfig
CONFIG_LOCALVERSION="-5.15.36-rt41-patched"
6) Using the menu config, follow these steps to configure the kernel for real-time.
A) Uncheck “Virtualization” in the main menu
B) Select “General setup —>”
C) Select “Preemption Model (Preemptible Kernel (Low-Latency Desktop)) —>”
D) Check “Fully Preemptible Kernel (Real-Time)”. This is listed if step 5 is completed.
E) Go up a level to “General setup —>”
F) Select “Timers subsystem –>”
G) Uncheck “Old Idle dynticks config” SEE: Linux PREEMPT-RT kernel tuning example for EPICS IOC
H) Select “Timer tick handling (Idle dynticks system (tickles idle)) —>”
I) Check “Periodic timer ticks (constant rate, no dynticks)”
J) Save and Exit
make menuconfig
7) Build and install the kernel.
make -j4 Image.gz modules dtbs
sudo make modules_install
sudo cp arch/arm64/boot/dts/broadcom/*.dtb /boot/
sudo cp arch/arm64/boot/dts/overlays/*.dtb* /boot/overlays/
sudo cp arch/arm64/boot/dts/overlays/README /boot/overlays/
sudo cp arch/arm64/boot/Image /boot/$KERNEL.img
8) If no errors have occurred, the final step is to reboot the computer. After the reboot, verify the new kernel by running uname -srvo.
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.