Building Custom Kernel for Raspberry Pi + Navio2 (Ardupilot on Linux)

Instructions for patching a custom Linux kernel for a Raspberry Pi (3/4) + Navio2 system running Ardupilot.

To make your custom kernel work with Navio2 for running Ardupilot, some overlays and a kernel module must be included. This article is a note of what I did to create my own kernel that’s workable with Navio2 for Ardupilot.

Assumptions

• You are to cross-compile the custom kernel on a Ubuntu desktop (I personally run my Ubuntu in a VM) and flash it onto a SD card for booting on a Raspberry Pi 3/4 board.
• You have ARM Cross-Compiler Tool Chain and Build Dependencies installed properly with ~/tools/ as the tool’s root directory.
You can get the compiler as instructed here or using the commands below:
git clone https://github.com/raspberrypi/tools ~/tools
sudo apt update
sudo apt install git bison flex libssl-dev

• You have a working SD card that is flashed with the Raspbian’s image that matches your kernel version.

[Step 0] Preparation

As an example here, I’m cloning a branch from my GitHub repository:

cd ~
git clone --depth=1 https://github.com/cchen140/linux-rt-rpi.git
cd linux-rt-rpi
git checkout -b rpi-4.19.y-rt origin/rpi-4.19.y-rt  # check out the desired remote branch
git checkout -b rpi-4.19.y-rt-navio2  # switch to a new branch name
git push -u origin rpi-4.19.y-rt-navio2  # push the new branch to remote


[Step 1] Patch for Navio 2

Make sure you have checked out the branch you’d like to work on. Then, we must patch our custom kernel to include Navio 2’s code.
I have created a patch navio2-4.19.83.patch that is available here.
To download and apply the patch, go to the root directory of your kernel code and run:

wget https://gist.github.com/cchen140/07159b29a21be929b545ad6c268ef3cc/raw/navio2-4.19.83.patch
git apply --stat navio2-4.19.83.patch
git apply --check navio2-4.19.83.patch
git am -3 < navio2-4.19.83.patch

You should resolve any patching error before you move on.

Creating the Navio2 Patch

The patch navio2-4.19.83.patch was created based on the branch rpi-4.19.83-navio by using the following commands:

cd ~
git clone --depth=1 https://github.com/cchen140/linux-rt-rpi.git
cd linux-rt-rpi
git checkout rpi-4.19.83-navio
git format-patch -8 HEAD --stdout > navio2-4.19.83.patch


[Step 2] Patch for RCIO Kernel Module

Navio 2 also depends on the RCIO kernel module which is maintained in a separate repository (source and forked).
As a result, applying the patch we made in last step is insufficient to make our kernel work with Navio2. There are two ways to tackle this problem (we will take the 1st approach):

1. Integrate the RCIO kernel module source code into our kernel code base.
2. Without the integration, we’ll have to compile and install the module separately (see this post for detailed steps if you’d like to take this approach).

To integrate the RCIO kernel module into your kernel, use the patch (coming from a commit I made) as follows:

wget -O rcio.patch https://github.com/cchen140/linux-rt-rpi/commit/253861034e6ad170ccb4c84129c56d7945a613af.patch
git apply --stat rcio.patch
git apply --check rcio.patch
git am < rcio.patch

Again, you should resolve any patching error before you move on.

[Step 3] Cross-Compile

At this point, all the changes for Navio2 have been integrated into your kernel.
To configure your kernel, you will need to use arch/arm/configs/bcm2709_navio2_defconfig for Raspberry Pi 3 and arch/arm/configs/bcm2711_navio2_defconfig for Raspberry Pi 4.

After that, use the following commands to compile your kernel (and please remember to check your tool’s path — here I’m assuming it is located under ~/tools/):

RPI-3RPI-4
echo PATH=\$PATH:~/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin >> ~/.bashrc source ~/.bashrc KERNEL=kernel7 make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- bcm2709_navio2_defconfig make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage modules dtbs -j 2  echo PATH=\$PATH:~/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin >> ~/.bashrc
source ~/.bashrc

KERNEL=kernel7l

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- bcm2711_navio2_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage modules dtbs -j 2


[Step 4] Update Raspberry Pi SD Card

Before you proceed, let’s create two folders for mounting the SD card’s two partitions (creating folders only has to be done once).

mkdir mnt
mkdir mnt/fat32
mkdir mnt/ext4


Then, insert your SD card and run the following commands to flash your new kernel onto your SD card (assuming your you have your SD card on sdb1 and sdb2):

sudo mount /dev/sdb1 mnt/fat32
sudo mount /dev/sdb2 mnt/ext4

sudo cp mnt/fat32/$KERNEL.img mnt/fat32/$KERNEL-backup.img
sudo cp arch/arm/boot/zImage mnt/fat32/$KERNEL.img sudo cp arch/arm/boot/dts/*.dtb mnt/fat32/ sudo cp arch/arm/boot/dts/overlays/*.dtb* mnt/fat32/overlays/ sudo cp arch/arm/boot/dts/overlays/README mnt/fat32/overlays/ sudo make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- INSTALL_MOD_PATH=mnt/ext4 modules_install sudo umount mnt/fat32 sudo umount mnt/ext4  After all these steps, you should be able to put your SD card back to your Raspberry Pi board and boot up. [Step 5] Revise Boot Configurations for Device Tree Overlays To allow a correct communication between Raspberry Pi and Navio2, add the DT overlay configurations at the end of the boot configuration file /boot/config.txt as follows: dtparam=spi=on dtoverlay=spi0-4cs dtoverlay=spi1-1cs,cs0_pin=16,cs0_spidev=disabled dtoverlay=rcio dtoverlay=navio-rgb dtparam=i2c1=on dtparam=i2c1_baudrate=1000000  [Step 6] Load RCIO Kernel Module At this point when Linux is booted up, the RCIO kernel module is loaded yet. To manually load the RCIO module, use the following commands: sudo modprobe rcio_spi sudo modprobe rcio_core  To verify if the RCIO kernel module has been correctly loaded, you can use lsmod or dmesg. An example is given as follows: lsmod | grep rcio  You should see a similar output like shown below if RCIO is running correctly. rcio_spi 16384 0 rcio_core 36864 1 rcio_spi  To make Linux load the RCIO module automatically on boot, add the module names in the file /etc/modules, as exemplified as follows: rcio_spi rcio_core  [Step 7] Install Ardupilot Please refer to this post for detailed steps for installing and running Ardupilot. I conclude the commands here: # To get source code git clone https://github.com/ArduPilot/ardupilot cd ardupilot git checkout Copter-3.6.11 git submodule update --init --recursive # To compile alias waf="$PWD/modules/waf/waf-light"
waf configure --board=navio2
waf copter

# To launch
sudo build/navio2/bin/arducopter -A udp:192.168.1.9:14550


References

• https://community.emlid.com/t/rcio-boot-loop/13458