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

First, you should get your kernel’s working directory ready.
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

Was this post helpful?

Leave a Reply

Your email address will not be published.