DEV Community

Cover image for Raspberry Pi 4B: Natively Build a 64 Bit Fully Preemptible Kernel (Real-Time) with Desktop
Be Hai Nguyen
Be Hai Nguyen

Posted on

Raspberry Pi 4B: Natively Build a 64 Bit Fully Preemptible Kernel (Real-Time) with Desktop


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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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:

125-01.png

125-02.png

The NEXT button lets us configure the new OS. Please see the illustration below:

125-03.png

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
Enter fullscreen mode Exit fullscreen mode


We can query the kernel information with:

$ uname -a
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

πŸ‘‰ 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
Enter fullscreen mode Exit fullscreen mode

And run the command:

$ git clone --depth=1 https://github.com/raspberrypi/linux
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode


β“Έ Patch the real-time kernel. Please refer to this official section.

● Determine the current kernel version:

$ uname -r
Enter fullscreen mode Exit fullscreen mode

The output will be something like:

6.6.51+rpt-rpi-v8
Enter fullscreen mode Exit fullscreen mode

● Determine the kernel source version. Change to the kernel source directory:

$ cd linux
Enter fullscreen mode Exit fullscreen mode

Run the following command to get the kernel source version:

$ head Makefile -n 4
Enter fullscreen mode Exit fullscreen mode

The output will be something like:

# SPDX-License-Identifier: GPL-2.0
# SPDX-License-Identifier: GPL-2.0
VERSION = 6
PATCHLEVEL = 6
SUBLEVEL = 59
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode


β“Ή 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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

The last output lines of the second command are:

...
#
# configuration written to .config
#
Enter fullscreen mode Exit fullscreen mode

● 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
...
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

And update it to:

CONFIG_LOCALVERSION="-v8-behai-rt-build"
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

If everything goes well, and it should, you will get the UI shown below:

125-04.png

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:

125-05.png

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:

125-06.png

In the pop-up dialog, select ( ) Fully Preemptible Kernel (Real-Time) as per the screenshot below:

125-07.png

The main screen should show Preemption Model (Fully Preemptible Kernel (Real-Time)) ---> as per the following screenshot:

125-08.png


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:

125-09.png

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
...
Enter fullscreen mode Exit fullscreen mode


β“Ό 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
Enter fullscreen mode Exit fullscreen mode

● 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
Enter fullscreen mode Exit fullscreen mode

We use the number of cores in the build command:

$ make -j4 Image.gz modules dtbs
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

● 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/
Enter fullscreen mode Exit fullscreen mode


β“Ύ Finally, reboot to ensure that the OS works πŸ˜‚ and the kernel is indeed a Fully Preemptible Kernel (Real-Time) kernel.

To reboot:

$ sudo reboot
Enter fullscreen mode Exit fullscreen mode

Ping should respond successfully:

$ ping picnc.local
Enter fullscreen mode Exit fullscreen mode

SSH should work:

$ ssh behai@picnc.local
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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:

002-pi-os-full-64-bit-debian-bookworm.png

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:

125-10.png


β“Έ 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)