This tutorial is based on Ubuntu 20.04 and Xenomai 3.2.1. ### For Compiling and Installing on x86_64: 1. **[Prerequisites](#Prerequirements)**: Prepare the environment for compilation. 2. **[Xenomai Kernel](#Xenomai-Kernel)**: Download the Linux kernel and Xenomai source code, and configure the necessary options. 3. **[Compile and Install Kernel with Debian Packages](#Compile-And-Install-Kernel-with-debian-packages)**: Compile the Linux kernel and install it. 4. **[Xenomai Userspace](#Xenomai-Userspace)**: After installing and rebooting with the Xenomai kernel, install the Xenomai userspace library. This section also includes a sample Xenomai program to verify the installation. > ℹ️ Note: If you want to install the kernel directly on the compiling machine, refer to the section on [#Compile-And-Install-Kernel-with-bzImage](#Compile-And-Install-Kernel-with-bzImage). ### For Compiling and Installing on ARM64 (Raspberry Pi 4): 1. **[Prerequisites](#Prerequirements)**: Prepare the environment for compilation. 2. **[Xenomai Kernel for Raspberry Pi 4 (Cross-Compile)](#Xenomai-Kernel-for-Raspberry-Pi-4-Cross-Compile)**: Download the Linux kernel and Xenomai source code, configure the options, and cross-compile the kernel for ARM64 on a x86_64 Linux system. 3. **[Install Kernel on Raspberry Pi](#Install-Kernel-On-Raspberry-Pi)**: After compiling the Linux kernel, transfer the Debian packages to the Raspberry Pi and install them. 4. **[Xenomai Userspace](#Xenomai-Userspace)**: After installing and rebooting with the Xenomai kernel, install the Xenomai userspace library. This section also includes a sample Xenomai program to verify the installation. # Prerequirements Tools for compiling xenomai kernel and xenomai userspace need to be installed first. You can use the commands below to install it. ```shell sudo apt install -y make gcc libncurses5-dev flex bison libssl-dev libelf-dev dwarves zstd autoconf libtool curl dpkg-dev ``` # Xenomai Kernel Download source code of Xenomai and Linux kernel ```shell wget https://source.denx.de/Xenomai/linux-dovetail/-/archive/v5.15.166-dovetail1/linux-dovetail-v5.15.166-dovetail1.zip wget https://source.denx.de/Xenomai/xenomai/-/archive/v3.2.1/xenomai-v3.2.1.tar.bz2 ``` Extract the compressed source code files. ```shell unzip linux-dovetail-v5.15.166-dovetail1.zip tar xvf xenomai-v3.2.1.tar.bz2 export linux=$(pwd)/linux-dovetail-v5.15.166-dovetail1 export xenomai=$(pwd)/xenomai-v3.2.1 ``` We need to run the `prepare-kernel` script for compiling the Linux kernel with Xenomai. ```shell cd xenomai-v3.2.1/scripts ./prepare-kernel.sh --linux=$linux --arch=x86_64 ``` We can configure the Linux kernel now. ```shell cd $linux make menuconfig ``` Setup the options > Options that do not exist or cannot be changed are ignored. ``` * General setup ​ --> Local version - append to kernel release: -xenomai --> Timers subsystem ​ ---> High Resolution Timer Support [*] ​* Pocessor type and features ​ --> Processor family ​ ---> Core 2/newer Xeon (if "cat /proc/cpuinfo | grep family" returns 6, set as Generic otherwise) --> Multi-core scheduler support [] * Xenomai/cobalt ​ --> Sizes and static limits ​ ---> Number of registry slots (512 --> 4096) ​ ---> Size of system heap (Kb) (4096 --> 4096) ​ ---> Size of private heap (Kb) (256 --> 256) ​ ---> Size of shared heap (Kb) (256 --> 256) ​ ---> Maximum number of POSIX timers per process (256 --> 512) ​ --> Drivers ​ ---> RTnet ​ ---> RTnet, TCP/IP socket interface (Enable) ​ ----> Drivers ​ -----> New intel(R) PRO/1000 PCIe(Gigabit) [M] ​ -----> Realtek 8169(Gigabit) [M] ​ -----> Loopback [M] ​ ----> Add-Ons ​ -----> Real-Time Capturing Support [M] * Power management and ACPI options ​ --> CPU Frequency scaling ​ ---> CPU Frequency scaling [] ​ --> ACPI (Advanced Configuration and Power Interface) Support ​ ---> Processor [] ​ --> CPU Idle ​ ---> CPU idle PM support [] * Memory Management Options ​ ---> Transparent Hugepage Support [] ​ ---> Allow for memory compaction [] ​ ---> Contiguous Memory Allocation [] ---> Page Migration [] ​* Device Drivers --> Unisys visorbus driver [] ``` Modify .config for preventing errors. We don't have the keys and we don't need the debug info. ```shell ./scripts/config --disable SYSTEM_TRUSTED_KEYS ./scripts/config --set-str SYSTEM_TRUSTED_KEYS "" ./scripts/config --disable SYSTEM_REVOCATION_KEYS ./scripts/config --set-str SYSTEM_REVOCATION_KEYS "" ./scripts/config --disable CONFIG_DEBUG_INFO_BTF ./scripts/config --set-str CONFIG_DEBUG_INFO_BTF "n" ``` Next, You have two options for compiling the kernel. * [bzImage](#Compile-And-Install-Kernel-with-bzImage) * [Debian Packages](#Compile-And-Install-Kernel-with-debian-packages) ## Compile And Install Kernel (with bzImage) This will compiling and install on the host which is your running system. ```shell make -j$(nproc) bzImage make modules make modules_install ``` ## Compile And Install Kernel (with debian packages) This will compiling for deb packages which you can send it to other or install the deb package on other host. ```shell make -j$(nproc) bindeb-pkg ``` > **Compiling Options** > * **-Zxz** change deb package compression type to xz. > **Notice** > After the compiling, the deb package files will in the parent folder which means on the previous directory `../`. You can use the following commands for installing the Xenomai linux kernel. ```shell sudo apt-get install ./linux-headers-5.10.191-xenomai_5.10.191-xenomai-1_amd64.deb sudo apt-get install ./linux-image-5.10.191-xenomai-dbg_5.10.191-xenomai-1_amd64.deb sudo apt-get install ./linux-image-5.10.191-xenomai_5.10.191-xenomai-1_amd64.deb sudo apt-get install ./linux-libc-dev_5.10.191-xenomai-1_amd64.deb ``` We need to configure the grub for using our new linux kernel. ```shell sudo nano /etc/default/grub ``` The content of `/etc/default/grub` should be look like below. We configure it to use the last selected kernel every boot. ``` GRUB_DEFAULT=saved GRUB_SAVEDEFAULT=true GRUB_TIMEOUT_STYLE=menu GRUB_TIMEOUT=10 GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian` GRUB_CMDLINE_LINUX_DEFAULT="quiet splash" GRUB_CMDLINE_LINUX="" ``` After edited the file `/etc/default/grub`, you need the update the grub configuration. ```shell sudo update-grub sudo reboot now ``` After reboot you should see the grub menu, select `Advanced options for Ubuntu` and select the kernel which we have installed. # Xenomai Kernel for Raspberry Pi 4 (Cross-Compile) Download source code of Xenomai and Linux kernel ```shell wget https://source.denx.de/Xenomai/linux-dovetail/-/archive/v5.15.166-dovetail1/linux-dovetail-v5.15.166-dovetail1.zip wget https://source.denx.de/Xenomai/xenomai/-/archive/v3.2.1/xenomai-v3.2.1.tar.bz2 ``` Extract the compressed source code files. ```shell unzip linux-dovetail-v5.15.166-dovetail1.zip tar xvf xenomai-v3.2.1.tar.bz2 export linux=$(pwd)/linux-dovetail-v5.15.166-dovetail1 export xenomai=$(pwd)/xenomai-v3.2.1 ``` We need to run the `prepare-kernel` script for compiling the Linux kernel with Xenomai. ```shell cd xenomai-v3.2.1/scripts ./prepare-kernel.sh --linux=$linux --arch=arm64 ``` We can configure the Linux kernel now. ```shell cd $linux sudo apt install -y gcc-aarch64-linux-gnu make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- defconfig make menuconfig ``` Setup the options > Options that do not exist or cannot be changed are ignored. ``` * General setup ​ --> Local version - append to kernel release: -xenomai --> Timers subsystem ​ ---> High Resolution Timer Support [*] ​* Pocessor type and features ​ --> Processor family ​ ---> Core 2/newer Xeon (if "cat /proc/cpuinfo | grep family" returns 6, set as Generic otherwise, raspberry pi returns nothing.) --> Multi-core scheduler support [] * Xenomai/cobalt ​ --> Sizes and static limits ​ ---> Number of registry slots (512 --> 4096) ​ ---> Size of system heap (Kb) (4096 --> 4096) ​ ---> Size of private heap (Kb) (256 --> 256) ​ ---> Size of shared heap (Kb) (256 --> 256) ​ ---> Maximum number of POSIX timers per process (256 --> 512) ​ --> Drivers ​ ---> RTnet ​ ---> RTnet, TCP/IP socket interface (Enable) ​ ----> Drivers ​ -----> New intel(R) PRO/1000 PCIe(Gigabit) [M] ​ -----> Realtek 8169(Gigabit) [M] ​ -----> Loopback [M] ​ ----> Add-Ons ​ -----> Real-Time Capturing Support [M] * Power management and ACPI options ​ --> CPU Frequency scaling ​ ---> CPU Frequency scaling [] ​ --> ACPI (Advanced Configuration and Power Interface) Support ​ ---> Processor [] ​ --> CPU Idle ​ ---> CPU idle PM support [] * Memory Management Options ​ ---> Transparent Hugepage Support [] ​ ---> Allow for memory compaction [] ​ ---> Contiguous Memory Allocation [] ---> Page Migration [] ​* Device Drivers --> Unisys visorbus driver [] ``` Modify .config for preventing errors. We don't have the keys and we don't need the debug info. ```shell ./scripts/config --disable SYSTEM_TRUSTED_KEYS ./scripts/config --set-str SYSTEM_TRUSTED_KEYS "" ./scripts/config --disable SYSTEM_REVOCATION_KEYS ./scripts/config --set-str SYSTEM_REVOCATION_KEYS "" ./scripts/config --disable CONFIG_DEBUG_INFO_BTF ./scripts/config --set-str CONFIG_DEBUG_INFO_BTF "n" ``` Compile the linux kernel for deb packages. ``` make ARCH=arm64 KBUILD_DEBARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- CXXFLAGS="-march=armv8-a+crc -mtune=cortex-a72" CFLAGS="-march=armv8-a+crc -mtune=cortex-a72" -j$(nproc) bindeb-pkg ``` Next [Install-Kernel-On-Raspberry-Pi](#Install-Kernel-On-Raspberry-Pi) ## Install Kernel (On Raspberry Pi) Copy your file to raspberry pi and install the packages by the following commands. ``` sudo apt install ./linux-headers-xxxx.deb sudo apt install ./linux-image-xxxx.deb sudo apt install ./linux-image-xxxx-dbg-xxxx.deb sudo apt install ./linux-libc-dev_xxxx.deb ``` Use command `lsblk` to figure out the boot partition. From the results below boot partition is `/boot`. ``` pi@raspberrypi:~ $ lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT mmcblk0 179:0 0 58G 0 disk ├─mmcblk0p1 179:1 0 256M 0 part /boot └─mmcblk0p2 179:2 0 57.7G 0 part / ``` Backup the old linux kernel in `/boot`. ``` mv /boot/kernel8.img /boot/kernel8.img.old ``` Use the compiled linux kernel with xenomai support. ``` mv /boot/vmlinuz-5.10.184-xeno /boot/kernel8.img ``` # Xenomai Userspace > **⚠️ NOTICE** > Steps below should be a root user to execute the commands > **Tips: Command `sudo su -` can get into the root user** Compile Xenomai Userspace and Install it on your system ```shell wget https://source.denx.de/Xenomai/xenomai/-/archive/v3.2.1/xenomai-v3.2.1.tar.bz2 tar xvf xenomai-v3.2.1.tar.bz2 cd xenomai-v3.2.1/ sudo apt install -y make automake libtool m4 autoconf fuse ./scripts/bootstrap ./configure make make install ``` > ℹ️ Use `./configure --enable-smp` on Raspberry Pi instead or it will not work. > ℹ️ Use `./scripts/bootstrap --enable-dlopen-libs` for xenomai with dynamic library support. > **REF:** https://github.com/LinuxCNC/linuxcnc/issues/1645 Configure Xenomai runtime environment for all user environment variable ```shell ! grep -q "/usr/xenomai/bin" /etc/bash.bashrc && echo "export PATH=/usr/xenomai/bin:\$PATH" | sudo tee -a /etc/bash.bashrc echo "/usr/xenomai/lib" | sudo tee -a /etc/ld.so.conf.d/xenomai.conf sudo ldconfig ``` Next we can run a xenomai example code ```shell cd ~/ mkdir xeno_example cd xeno_example ``` Use your favorite editor to copy and paste the code (xeno_example.c) below ```shell nano xeno_example.c ``` **xeno_example.c** ```c #include <stdio.h> #include <signal.h> #include <unistd.h> #include <alchemy/task.h> RT_TASK hello_task; // function to be executed by task void helloWorld(void *arg) { RT_TASK_INFO curtaskinfo; printf("Hello World!\n"); // inquire current task rt_task_inquire(NULL,&curtaskinfo); // print task name printf("Task name : %s \n", curtaskinfo.name); } int main(int argc, char* argv[]) { char str[10]; printf("start task\n"); sprintf(str,"hello"); /* Create task * Arguments: &task, * name, * stack size (0=default), * priority, * mode (FPU, start suspended, ...) */ rt_task_create(&hello_task, str, 0, 50, 0); /* Start task * Arguments: &task, * task function, * function argument */ rt_task_start(&hello_task, &helloWorld, 0); } ``` Use your favorite editor to copy and paste the code (Makefile) below ```shell nano Makefile ``` **Makefile** ```makefile XENO_CONFIG := /usr/xenomai/bin/xeno-config CFLAGS := $(shell $(XENO_CONFIG) --posix --alchemy --cflags) LDFLAGS := $(shell $(XENO_CONFIG) --posix --alchemy --ldflags) CC := gcc EXECUTABLE := xeno_example all: $(EXECUTABLE) %: %.c $(CC) -o $@ $< $(CFLAGS) $(LDFLAGS) clean: rm -f $(EXECUTABLE) ``` Finally we can compile and run this example ! ``` make ./xeno_example ```