RPi Kernel
Details on building a realtime kernel for the Rpi.
linuxcnc seems to recommend the Rpi4 as a minimum
Downloading Sources
- https://github.com/raspberrypi/linux
- https://www.raspberrypi.com/documentation/computers/linux_kernel.html
Install some dependencies
sudo apt install git bc bison flex libssl-dev make gcc raspberrypi-kernel-headers libc6-dev
sudo apt install patch xz-utils libncurses-dev
To download the sources without the full git repository (as this can take a long time)
# Using kernel 6.3 as an example here
cd /usr/src
# For the latest master
wget https://github.com/raspberrypi/linux/archive/refs/heads/rpi-6.3.y.tar.gz
# For a specific version based on the commit hash (what I'm current;y using)
wget https://github.com/raspberrypi/linux/archive/2d0a7ff52ebfe7bc1c08fd7e444b9ce3d34385bf.tar.gz -O rpi-6.3.y.tar.gz
# Extract the files
tar -xvf rpi-6.3.y.tar.gz
mv linux-rpi-6.3.y linux-6.3.2-rt
Patch Sources
To determine which version the sources are using
head linux-6.3.2-rt/Makefile -n 4
# Given I've specified the git hash above for a specific version, this should be 6.3.2
Download and apply the patch file for the relevant kernel version.
cd /usr/src/
wget https://mirrors.edge.kernel.org/pub/linux/kernel/projects/rt/6.3/patch-6.3.3-rt15.patch.xz
cd linux-6.3.2-rt
xzcat ../patch-6.3.3-rt15.patch.xz | patch -p1
Note for this specific patch, it may complain while trying to apply the last hunk.
This is due to it already being applied in the kernel sources, so just answer the prompt with 'n'
Configure Sources
Next create a default configuration for the RPI4
# 64bit Rpi4 / Rpi3
make bcm2711_defconfig
Next let's make some configuration changes.
make menuconfig
The main ones to change are:
- General -> Preemption Model
switch this toFull Real-time
- General Setup -> Local Version
add something to the end of
CONFIG_LOCALVERSION
to make it unique.
Such as-rt-linuxcnc1
Build / Install kernel
Next we're going to build the kernel sources.
Something to remember at this point is if you've already added isolcpus=2,3
to the /boot/cmdline.txt file.
Then it's going to take twice as long to compile due to two of the core's being unavailable for general use.
# Build the kernel - 64bit
make -j4 Image.gz modules dtbs
Next we're going to install the kernel modules
# This typically copies the modules across to a directory such as /lib/modules/6.3.2-rt13-v8-rt-linuxcnc1
make modules_install
Finally, we're going to install the kernel image and other boot related files.
The best way to do this is to use a separate directory so that we don't overwrite the default kernel.
We can then just switch back and forth between the default and the realtime kernel using a single config line under /boot/config.txt
In this example we're using the directory /boot/rt-6.3/
# Install the kernel image and boot files - 64bit
mkdir -p /boot/rt-6.3/overlays/
cp arch/arm64/boot/dts/broadcom/*.dtb /boot/rt-6.3/
cp arch/arm64/boot/dts/overlays/*.dtb* /boot/rt-6.3/overlays/
cp arch/arm64/boot/dts/overlays/README /boot/rt-6.3/overlays/
cp arch/arm64/boot/Image.gz /boot/rt-6.3/kernel8.img
Boot Config
Next edit the /boot/config.txt
file.
# Add this to the top of the file
os_prefix=/rt-6.3/
This should select the realtime kernel we're ve just installed into the /boot/rt-6.3
directory on the next reboot.
If you need to switch back to the default kernel, just comment out the line and reboot.
To reboot the machine /sbin/reboot
After a reboot, we can check the kernel version with uname -a
to make sure it has RT in it's name
32bit / 64bit kernel
For the RPI4 we have kernel8.img
for 64 bit and kernel7l.img
for 32bit.
It's determined which one to use within config.txt via the arm_64bit
setting.
This currently defaults to 1 now for 64bit, unless specifically set to 0 for 32bit.
arm_64bit=1
Reading The Live Kernel Configuration
If you want to read the config from the running kernel
(what was used to compile the kernel)
modprobe configs
zcat /proc/config.gz > ./output