← Previous Lecture | Next Lecture →
- How to build a PREEMPT_RT kernel for Raspberry Pi using the current mainline-based workflow
- Why you no longer need a separate real-time patch file on modern Raspberry Pi kernels
- How to configure, cross-compile, and deploy the kernel to an SD card
- How to verify that PREEMPT_RT is genuinely active after boot
- Common build errors and how to resolve them
In the previous lecture of this free Linux kernel development course, you learned what PREEMPT_RT changes inside the kernel and why it matters. In this lecture, you will actually build one for a Raspberry Pi. The workflow here reflects the current, updated process for kernels based on Linux 6.12 and later, where PREEMPT_RT ships inside the Raspberry Pi kernel source tree as a ready-made configuration — a big simplification compared to the older approach of hunting for a version-matched patch file and hoping it applies cleanly.
Prerequisites
- A Raspberry Pi 4 or Raspberry Pi 5 running a 64-bit Raspberry Pi OS install
- A Linux PC or another Raspberry Pi for cross-compiling (native compiling on the Pi itself also works, just slower)
- At least 20 GB of free disk space for kernel sources and build artifacts
- A spare microSD card, or a working backup of your current one
- Comfort with the previous lecture’s concepts: threaded IRQs, rt-mutexes, and soft real-time behavior
How the Modern Build Workflow Differs from the Old Patch-Based Method
Older real-time Linux tutorials walk you through downloading a patch-<kver>-rt<nn>
file, matching it exactly to your kernel version, and applying it with the patch command —
a process that regularly failed when the patch and kernel versions drifted apart even slightly. Since
PREEMPT_RT merged into mainline Linux 6.12, the Raspberry Pi kernel source tree now ships dedicated
real-time defconfig files, so the patch-download step is gone entirely for current kernels.
| Step | Old Method (pre-6.12) | Current Method (6.12+) |
|---|---|---|
| Get RT support | Download a separate, version-matched RT patch | Already included in kernel source; no patch file needed |
| Apply RT support | Run patch -p1 and hope for no rejected hunks |
Select the RT defconfig or enable the config option directly |
| Configure | Manually toggle Preemption Model to Real-Time | Same menuconfig step, now natively part of the tree |
Step 1: Install Build Dependencies
Update your system and install the packages needed to configure and cross-compile the kernel:
sudo apt update
sudo apt install -y git bc bison flex libssl-dev make libncurses-dev \
crossbuild-essential-arm64
The crossbuild-essential-arm64 package provides the ARM64 cross-compiler toolchain, so you can
build the kernel on a faster PC and deploy the result to the Pi.
Step 2: Fetch the Raspberry Pi Kernel Source
Clone the official Raspberry Pi Linux kernel tree, using a shallow clone to save time and space:
git clone --depth=1 --branch rpi-6.12.y https://github.com/raspberrypi/linux
cd linux
Step 3: Select the Real-Time Defconfig
Set the cross-compilation environment variables, then choose the real-time-flavored default configuration
that matches your board. Raspberry Pi 4 uses bcm2711, and Raspberry Pi 5 uses
bcm2712:
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-
# For Raspberry Pi 4 / 400 / CM4:
make bcm2711_rt_defconfig
# For Raspberry Pi 5:
make bcm2712_rt_defconfig
If your kernel branch does not ship a dedicated _rt_defconfig yet, start from the standard
defconfig and enable real-time support manually with make menuconfig, as shown next.
Step 4: Verify and Fine-Tune the Configuration
Open the interactive configuration menu to confirm the real-time option is active, and disable a few debug options that are known to inflate latency measurements:
make menuconfig
| Menu Path | Option | Setting |
|---|---|---|
| General Setup > Preemption Model | Fully Preemptible Kernel (Real-Time) | Enabled (CONFIG_PREEMPT_RT=y) |
| Kernel hacking > Lock Debugging | DEBUG_LOCKDEP, DEBUG_PREEMPT | Disabled |
| Memory Debugging | DEBUG_OBJECTS, SLUB_DEBUG | Disabled |
If CONFIG_PREEMPT_RT is not visible in the Preemption Model menu, first enable
CONFIG_EXPERT under General Setup — recent kernels hide the fully preemptible option behind it.
Step 5: Add a Custom Version Suffix (Optional but Recommended)
Tag your build with a recognizable suffix so uname -a clearly shows it later:
scripts/config --set-str LOCALVERSION "-v8-realtime"
Step 6: Build the Kernel, Modules, and Device Tree Blobs
make -j$(nproc) Image.gz modules dtbs
Replace $(nproc) with the number of CPU cores available on your build machine for the fastest
possible build; this command produces the compressed kernel image, all loadable modules, and the device
tree blobs needed to describe the hardware to the kernel at boot.
Step 7: Install Modules to the Target Root Filesystem
Mount your SD card’s root filesystem partition, then install the modules directly into it. Always set
INSTALL_MOD_PATH to the mounted SD card path, never leave it unset when cross-compiling —
otherwise you risk overwriting your build machine’s own kernel modules:
sudo env PATH=$PATH make ARCH=arm64 INSTALL_MOD_PATH=/media/$USER/rootfs modules_install
Step 8: Copy the Kernel Image, Device Tree Files, and Overlays
sudo cp arch/arm64/boot/Image.gz /media/$USER/bootfs/kernel8-rt.img
sudo cp arch/arm64/boot/dts/broadcom/*.dtb /media/$USER/bootfs/
sudo cp arch/arm64/boot/dts/overlays/*.dtb* /media/$USER/bootfs/overlays/
Copying the new kernel under a distinct filename such as kernel8-rt.img, instead of
overwriting kernel8.img, keeps your original working kernel available as a fallback.
Step 9: Point the Bootloader at the Real-Time Kernel
Edit config.txt on the boot partition and add:
kernel=kernel8-rt.img
arm_64bit=1
Step 10: Boot and Verify PREEMPT_RT Is Active
Insert the SD card into the Raspberry Pi, power it on, and connect over SSH:
uname -a
cat /sys/kernel/realtime
A kernel with real-time support active will show PREEMPT_RT in the uname -a
output, and /sys/kernel/realtime will read 1. If either check fails, revisit
Step 4 and confirm CONFIG_PREEMPT_RT was actually enabled before the build.
Common Build Errors and Troubleshooting
| Symptom | Likely Cause | Fix |
|---|---|---|
| Board fails to boot after flashing | arm_64bit=1 missing in config.txt |
Add it explicitly when using a custom kernel filename |
uname -a shows PREEMPT but not PREEMPT_RT |
CONFIG_PREEMPT_RT was not actually set before building | Re-run menuconfig, confirm the setting, save, and rebuild |
| Modules fail to load after boot | Modules installed to the wrong path or version mismatch | Re-check INSTALL_MOD_PATH pointed at the correct mounted SD card partition |
| Host machine’s modules disappear | Ran modules_install without INSTALL_MOD_PATH |
Always double-check this variable before running the install target |
Best Practices for Building Real-Time Kernels
- Always keep your previous working kernel image as a boot fallback
- Use a distinct
LOCALVERSIONsuffix so you can tell builds apart at a glance - Cross-compile on a PC for significantly faster build times than compiling natively on the Pi
- Disable lock and memory debug options before running any latency benchmark
- Track the exact commit or branch you built from, so results are reproducible later
Performance and Security Considerations
A real-time kernel trades a small amount of average-case throughput for tighter worst-case latency —
expect slightly higher CPU overhead under heavy lock contention. From a security standpoint, treat a
custom-built kernel the same as any other: keep it updated against upstream security fixes, and avoid
exposing a real-time control system directly to untrusted networks, since a compromised high-priority
process can starve the rest of the system through sched_rt_runtime_us if limits are not set
appropriately.
Summary: Key Takeaways
- Modern Raspberry Pi kernels (6.12+) ship real-time defconfigs, removing the old manual patch step
- The build flow is: install toolchain, fetch source, select RT defconfig, configure, build, deploy, verify
- Always confirm PREEMPT_RT is active via
uname -aand/sys/kernel/realtimebefore trusting the build - Keep debug options disabled and a fallback kernel available at all times
Conclusion
You now have a working, verified PREEMPT_RT kernel running on Raspberry Pi hardware, built using the current mainline-based workflow rather than the older patch-file method. Having a real-time kernel installed is only half the story — the next lecture in this free Linux device drivers course and kernel series shows you how to objectively measure your system’s real-time behavior using the cyclictest tool, so you can prove your latency numbers instead of assuming them.
Frequently Asked Questions
1. Do I need to download a real-time patch file for a modern Raspberry Pi kernel?
No, not for kernels based on Linux 6.12 or later — the Raspberry Pi kernel tree includes ready-made real-time defconfigs.
2. Can I build the kernel directly on the Raspberry Pi instead of cross-compiling?
Yes, native compilation works, but it takes considerably longer than cross-compiling on a faster PC.
3. Which Raspberry Pi models are covered by this build process?
Raspberry Pi 4, Raspberry Pi 400, Compute Module 4, and Raspberry Pi 5 are all supported with their respective defconfig targets.
4. What does it mean if CONFIG_PREEMPT_RT isn’t visible in menuconfig?
It usually means CONFIG_EXPERT needs to be enabled first under General Setup, since the option is nested behind it on recent kernels.
5. Is it safe to overwrite my existing kernel.img file?
It is safer not to. Deploy the new kernel under a distinct filename and update config.txt, keeping your original kernel as a fallback.
6. How long does a full kernel build take?
It depends heavily on your build machine’s CPU core count; cross-compiling on a modern multi-core PC is typically much faster than native compilation on the Pi itself.
7. Does building a real-time kernel change my Raspberry Pi OS userspace?
No, only the kernel and its modules change. Your existing applications, packages, and filesystem remain untouched.
Next up: measure your real-time kernel’s actual latency using cyclictest.
Next Lecture: Latency Testing with cyclictest Browse All Free Courses
2 Comments