In this article, I present a step-by-step procedure to natively patch and build a 64-bit Fully Preemptible Kernel (Real-Time) for my Raspberry Pi 4B (Pi 4B). We start with a pre-made operating system image that includes a desktop environment. After building and installing the real-time patch kernel, querying the kernel information with the command uname -a
should report something similar to:
Linux picnc 6.6.59-rt45-v8-behai-rt-build+ #1 SMP PREEMPT_RT Sat Nov 2 10:20:46 AEDT 2024 aarch64 GNU/Linux
This indicates that the token PREEMPT_RT
is present in the output. Natively in this instance means that we patch and build the kernel using the very Pi 4B on which the newly built kernel is installed.
Let's first describe the steps and then provide some background information on why I looked into this.
βΆ We will now discuss the step-by-step procedure.
β΅ I use a newly installed Ubuntu 24.04.1 LTS to write the target operating system (OS) image onto a microSD card. We need to install Raspberry Pi Imager
:
$ sudo apt install rpi-imager
There should not be any problem. Raspberry Pi Imager v1.8.5
should appear in the Ubuntu application list. π₯ I first tried to install it on Ubuntu 22.10 Kinetic, but it reported a lot of errors, which I tried to fix without success.
βΆ Use Raspberry Pi Imager
to write a pre-made OS image onto a microSD card. This application should be self-explanatory. For Operating System
, I select Raspberry Pi OS (other)
, then Raspberry Pi OS Full (64-bit)
. Please see the screenshots below:
The NEXT
button lets us configure the new OS. Please see the illustration below:
In the SERVICES
tab, we can enable SSH. The writing of the OS image should not take too long. After finishing writing, we should be able to boot without any issues. My hostname
is picnc.local
, and my username
is behai
. Both of the following commands should work:
$ ping picnc.local
$ ssh behai@picnc.local
We can query the kernel information with:
$ uname -a
In my case, the output is:
Linux picnc 6.6.51+rpt-rpi-v8 #1 SMP PREEMPT Debian 1:6.6.51-1+rpt3 (2024-10-08) aarch64 GNU/Linux
Note the PREEMPT
token. We are going to change that to PREEMPT_RT
.
We can also use the following commands to query the kernel information:
$ uname -r
$ uname -srm
$ hostnamectl
$ cat /proc/version
π The following steps are extracted from the Raspberry Pi page The Linux kernel. This official page covers multiple OSes. I have arranged the steps to suit the OS that I am using.
β· Download the latest kernel source code. Please refer to this official section. Change to the $HOME
directory:
$ cd $HOME
And run the command:
$ git clone --depth=1 https://github.com/raspberrypi/linux
This downloads the kernel source code to $HOME/linux
. Please note that the git
utility is included with the OS image. It can be installed with:
$ sudo apt install git
βΈ Patch the real-time kernel. Please refer to this official section.
β Determine the current kernel version:
$ uname -r
The output will be something like:
6.6.51+rpt-rpi-v8
β Determine the kernel source version. Change to the kernel source directory:
$ cd linux
Run the following command to get the kernel source version:
$ head Makefile -n 4
The output will be something like:
# SPDX-License-Identifier: GPL-2.0
# SPDX-License-Identifier: GPL-2.0
VERSION = 6
PATCHLEVEL = 6
SUBLEVEL = 59
In this instance, the kernel source version is 6.6.59
. At the time, there was no version 6.6.59
of the real-time kernel patch at https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/, so I used patch version 6.6.58
instead. Please note that on the internet, there are numerous mentions of this issue. Sometimes patches are behind, and using a not-so-older version of the patch should be okay.
β Apply the target real-time kernel patch. π Please recall that the present working directory is $HOME/linux
. The following commands download, uncompress, and patch the kernel source code with the target real-time kernel patch:
$ wget https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/patch-6.6.58-rt45.patch.gz
$ gunzip patch-6.6.58-rt45.patch.gz
$ cat patch-6.6.58-rt45.patch | patch -p1
βΉ Configure the kernel. Please refer to this official section.
β Install build tools/dependencies:
$ cd $HOME
$ sudo apt install libncurses5-dev flex build-essential bison libssl-dev bc make
$ cd linux
I don't think it's necessary to navigate to the $HOME
directory to perform the installation, but I prefer to do so.
β Prepare the default kernel configuration: $HOME/linux/.config
. Please refer to this official section. π The present working directory is $HOME/linux
. Run the following commands:
$ KERNEL=kernel8
$ make bcm2711_defconfig
The last output lines of the second command are:
...
#
# configuration written to .config
#
β Check real-time configuration items in /home/behai/linux/.config
. Open /home/behai/linux/.config
and look for the following real-time entries:
...
CONFIG_PREEMPT_BUILD=y
# CONFIG_PREEMPT_NONE is not set
# CONFIG_PREEMPT_VOLUNTARY is not set
CONFIG_PREEMPT=y
# CONFIG_PREEMPT_RT is not set
CONFIG_PREEMPT_COUNT=y
CONFIG_PREEMPTION=y
# CONFIG_PREEMPT_DYNAMIC is not set
...
Based on my previous failed attempts, I want to ascertain that PREEMPT_RT
is not turned on. And indeed, it is not.
βΊ Customise the kernel version using LOCALVERSION
. Please refer to this official section.
In /home/behai/linux/.config
, locate the LOCALVERSION
entry, which should be:
CONFIG_LOCALVERSION="-v8"
And update it to:
CONFIG_LOCALVERSION="-v8-behai-rt-build"
In the next section on menuconfig
, we will verify that this manual update takes effect.
β» Using the UI tool menuconfig
to configure the kernel to Fully Preemptible Kernel (Real-Time). Please refer to this official section. π The present working directory is $HOME/linux
.
-- Please note that this UI tool also updates the $HOME/linux/.config
file.
Run the command:
$ make menuconfig
If everything goes well, and it should, you will get the UI shown below:
Use the up and down arrow keys to move between the vertical entries, use the left and right arrow keys to move between the horizontal entries at the bottom of the screen. Press the Enter key to select the highlighted item. Activate the < Load >
menu item. The following pop-up appears:
Select < Ok >
to confirm using the $HOME/linux/.config
configuration file, which has been loaded by default.
Activate the first menu item General setup --->
. On the next screen, select Preemption Model (Preemptible Kernel (Low-Latency Desktop)) --->
as shown below:
In the pop-up dialog, select ( ) Fully Preemptible Kernel (Real-Time)
as per the screenshot below:
The main screen should show Preemption Model (Fully Preemptible Kernel (Real-Time)) --->
as per the following screenshot:
Recall that in a previous section, we customised the kernel version LOCALVERSION
. The third entry in the previous screen confirms this manual customisation as shown below:
Save the changes and exit menuconfig
. π₯ As a precaution, rerun menuconfig
to confirm that your changes were saved.
π As a final verification, ensure that CONFIG_PREEMPT_RT
is updated to y
. Open /home/behai/linux/.config
and look for the following real-time entries:
...
# CONFIG_PREEMPT_NONE is not set
# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set
CONFIG_PREEMPT_RT=y
CONFIG_PREEMPT_COUNT=y
CONFIG_PREEMPTION=y
...
βΌ We now discuss the actual kernel build process.
β Install kernel headers. Please refer to this official section. Run the following commands:
$ cd $HOME
$ sudo apt install linux-headers-rpi-v8
$ cd linux
β Build the kernel. Please refer to this official section. π The present working directory is $HOME/linux
.
My Pi 4B has 8GB of RAM and 4 cores. The build process takes around 2 hours. To determine the number of cores, run the command:
$ nproc
We use the number of cores in the build command:
$ make -j4 Image.gz modules dtbs
It takes a few hours. We can do something else in the meantime, but keep an eye on it.
β½ Install the newly built kernel. Please refer to this official section. π The present working directory is still $HOME/linux
.
β First, install the kernel modules onto the boot media:
$ sudo make -j4 modules_install
β Then, install the kernel and Device Tree blobs into the boot partition, backing up the original kernel with the commands listed below. Please recall that the temporary environment variable $KERNEL
is defined in this step. If you were interrupted and had to turn off the computer or terminated the SSH session, you will need to set it again.
$ 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/
βΎ Finally, reboot to ensure that the OS works π and the kernel is indeed a Fully Preemptible Kernel (Real-Time)
kernel.
To reboot:
$ sudo reboot
Ping should respond successfully:
$ ping picnc.local
SSH should work:
$ ssh behai@picnc.local
The response I received was:
Linux picnc 6.6.59-rt45-v8-behai-rt-build+ #1 SMP PREEMPT_RT Sat Nov 2 10:20:46 AEDT 2024 aarch64
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Sat Nov 2 12:03:31 2024
Please note the tokens 6.6.59-rt45-v8-behai-rt-build+
and PREEMPT_RT
in the first line. We have successfully built and installed a Fully Preemptible Kernel (Real-Time)
kernel. βοΈ I also ran the commands to query the kernel information as discussed in a prior section.
π₯ As a final note on this OS, the open-source Remote Desktop Protocol server xrdp does not seem to work properly. After writing the initial OS image, I installed this xrdp
server, but Windows Remote Desktop Connection just shows a blank black screen. A few days prior, I tried this same image, but the release date was 04/July/2024, as seen in the screenshot below:
And Remote Desktop Connection worked perfectly. Raspberry Pi updated this image while I was still trying to resolve this Fully Preemptible Kernel (Real-Time)
issue.
β· As mentioned at the beginning, in this section I'm discussing why I have looked into this issue. I am interested in learning CNC, and my goal is to build my own CNC machine. I know nothing about CNC and electronics. I have been doing a little bit of basic physical computing with the Pi 4B using Python. In the process, I have learned some basic electronics as well.
My initial research on CNC pointed to the Mach3 CNC machine controller, which runs on Windows. Further research led me to LinuxCNC, which I found to be a more attractive option, especially since it can run on a Raspberry Pi computer. It became apparent that we need a real-time kernel.
β΅ My initial source of information is a 6-year-old YouTube series, LinuxCNC for the Hobbyist, by Mr. Joe Hildreth. The 17th video, Compiling a Realtime Kernel for LinuxCNC, discusses building a real-time kernel. I found the accompanying written tutorial, Compiling a Realtime Linux kernel with the preemp-rt kernel patch, much easier to follow.
βΆ My second source of information is a 2-year-old LinuxCNC forum post titled Installing LinuxCNC 2.9 on Raspberry Pi 4B with Preempt-RT kernel.
β· I will not go into the details of my failed attempts to build a real-time kernel. However, between the instructions, I had about 6 tries over the span of 12 days π, and despite successfully building and installing, the kernel only showed PREEMPT
, not PREEMPT_RT
.
On my last failed attempt, I went ahead and installed LinuxCNC anyway. A variation of it was installed successfully, and I was able to run it via Remote Desktop Connection as shown below:
βΈ This nearly 3-year-old Stack Overflow post, Raspberry pi4: kernel 64bit with RT extension, addresses the very same problem I had, and the author managed to solve it. This post eventually led me to the previously mentioned Raspberry Pi official page, The Linux kernel, and this successful build and installation.
Compiling the Linux kernel is not my cup of tea. However, I wouldn't say my failed attempts were a waste of time. I have learned many things during these exercises, and some of the steps are similar to the final successful attempt.
βΉ This has been a new and interesting experience for me. I have learned quite a few things during this process. I am not sure if I can achieve my goal, as I have done some research into hardware, and there are many things I have no knowledge of. But I keep my fingers crossed...
Thank you for reading. I hope you find the information in this post useful. Stay safe, as always.
βΏβΏβΏ
Feature image source:
Top comments (0)