Skip to content

Compute ‐ Raspberry Pi

William Talbot edited this page Sep 18, 2024 · 40 revisions

Setup Overview

We are using the Raspberry Pi Compute Module 4. We run RasbianOS 64bit light with Debian 11 Bullseye with Kernel 6.1.21-v8+ This allows for native PTP support and we run ROS1 inside a Ubuntu Focal container. Kernel modules are added outside the container directly to the native OS and the buffer files mapped inside the container. The GPIOs are mainly controlled using the pigpio library http://abyz.me.uk/rpi/pigpio/.

Lessons Learned

  • PTP is not straight forward to get running with any Ubuntu Image available
  • Therefore using Raspberry Pi OS Lite 64 bit
  • Problem here latest version is on Debian Version 12 which does not work with ROS1 Buster - therefore we use the docker container
  • On the latest Debian 12 the GPIO API changed which made it tricky to use the existing Debian Kernal Modules - therefore we use Debian 11.

Kernel Module

Kernel modules are quite straight forward to install - we created in all drivers that need kernel modules the corresponding C-Files which require to be built and can then be added to the kernel using insmode. For more details refer to the individual kernel driver modules.

We currently need kernel modules for:

  • STIM320
  • AP20
  • ADIS16475

Step 1: Flashing the PI with Debian Bookworm

We followed the following: https://www.jeffgeerling.com/blog/2020/how-flash-raspberry-pi-os-compute-module-4-emmc-usbboot

  • Use the development board
  • Connect directly to EMMC via USB Micro cable
sudo apt install libusb-1.0-0-dev
cd git
git clone --depth=1 https://github.com/raspberrypi/usbboot
cd usbboot
make
  • Set jumper to disable eMMC boot
  • Verify good USB micro USB cable which allows for data transmission
  • Power cycle the dev board
sudo ./rpiboot

Install the RPI Imager:

sudo snap install rpi-imager

image

We created a copy of the image here: https://drive.google.com/drive/folders/1Jrnnmyx1K0XbNu_suW2S03UzyD-9fVt2?usp=drive_link

Raspberry Pi OS Lite 64 bit

rsl@pi:~ $ cat /etc/os-release 
PRETTY_NAME="Debian GNU/Linux 11 (Bullseye)"
NAME="Debian GNU/Linux"
VERSION_ID="11"
VERSION="11 (bullseye)"
VERSION_CODENAME=bullseye

Step 2: Setup Networking

First lets obtain a static IP address without using netplan such that we can download netplan.

Copy to sudo vi /etc/network/interfaces

source /etc/network/interfaces.d/*

auto lo

auto eth0
iface eth0 inet static
    address 192.168.2.58
    netmask 255.255.255.0
    gateway 192.168.2.51
    dns-nameservers 8.8.8.8

Restart the networking:

sudo systemctl restart networking

Setup SSH_keys by copying over from other PC

ssh [email protected] -o PubkeyAuthentication=no -o PreferredAuthentications=password
scp -r -o PubkeyAuthentication=no -o PreferredAuthentications=password /home/rsl/.ssh/* [email protected]:/home/rsl/.ssh
killall ssh-agent; eval "$(ssh-agent)"
ssh-add /home/rsl/.ssh/id_rsa
killall ssh-agent; eval "$(ssh-agent)"

Given that the internet is now working on the PI one can install netplan

sudo apt install netplan.io -y
# and then continue follow the pi installation script within the grandtour repo

Step 3: PTP Setup

Follow tutorial here: https://github.com/jclark/rpi-cm4-ptp-guide/blob/main/os.md

Make the changes to the sudo raspi-config

enable serial port (under Interface/Serial Port); Answer *No to login shell accessible over serial

  • Yes to enable serial port hardware

Then append to /boot/firmware/config.txt

# Enable GPIO pin 18 for PPS (not always necessary, but useful for testing)
dtoverlay=pps-gpio,gpiopin=18
# realtime clock
dtoverlay=i2c-rtc,pcf85063a,i2c_csi_dsi
# fan
dtoverlay=i2c-fan,emc2301,i2c_csi_dsi
# Make /dev/ttyAMA0 be connected to GPIO header pins 8 and 10
# This always disables Bluetooth
dtoverlay=disable-bt

Restart some things

sudo systemctl disable hciuart
sudo dpkg-reconfigure tzdata

Check if this looks good

ethtool -T eth0
sudo hwclock --show

Step 4: Kernel Configuration & Installation

In order to run the ADIS16475-2 IMU, kernel must be configured and relevant modules installed. Whil it may be possible to install dynamic kernel modules (dkms) and configure the kernel without building from source, this has not been tested.

a. Download and Prepare Kernel

Following the official documentation:

git clone --depth=1 --branch rpi-6.1.y https://github.com/raspberrypi/linux

Install dependencies:

sudo apt install bc bison flex libssl-dev make

Prepare the default configuration:

cd linux
KERNEL=kernel8
make bcm2711_defconfig

Adjust the CONFIG_LOCALVERSION in .config (or can be changed graphically with menuconfig), e.g.

CONFIG_LOCALVERSION="-v8l-CUSTOM"

b. Enable Industrial I/O (IIO) for the ADIS16475 IMU

make menuconfig

In Device Drivers -> Industrial I/O support make sure that Enable buffer support within IIO, Industrial I/O HW buffering, Industrial I/O buffering based on kfifo and Enable triggered sampling support are enabled.

In Inertial measurement units, enable the adis16475.

Create the following overlay file arch arm64/boot/dts/overlays/adis16475.dts:

// SPDX-License-Identifier: GPL-2.0
/dts-v1/;
/plugin/;
 
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/gpio/gpio.h>
 
/ {
    compatible = "brcm,bcm2835";
 
    fragment@0 {
        target = <&spi0>;
        __overlay__ {
            status = "okay";
            dmas = <&dma 6>, <&dma 7>; // BCM2711 ARM Peripherals PDF page 61-62
            dmas-names = "tx", "rx";
        };
    };
 
    fragment@1 {
        target = <&spidev0>;
        __overlay__ {
            status = "disabled";
        };
    };
 
    fragment@2 {
        target = <&spidev1>;
        __overlay__ {
            status = "disabled";
        };
    };
 
     fragment@3 {
        target = <&gpio>;
        __overlay__ {
            adis16475_pins: adis16475_pins {
                brcm,pins = <17 23>; // interrupt and reset
                brcm,function = <0 1>; // in out
            };
        };
    };
 
    fragment@4 {
        target-path = "/";
        __overlay__ {
            clocks {
                adis16475_ref_clk: clock@0 {
                         #clock-cells = <0>;
                         compatible = "fixed-clock";
                };
            };
        };
    };
 
    fragment@5 {
        target = <&spi0>;
        __overlay__ {
            /* needed to avoid dtc warning */
            #address-cells = <1>;
            #size-cells = <0>;
 
            adis16475: adis16475@0 {
                reg = <0>;
                pinctrl-names = "default";
                pinctrl-0 = <&adis16475_pins>;
                spi-cpha;
                spi-cpol;
                reset-gpios = <&gpio 23 GPIO_ACTIVE_LOW>;
                spi-max-frequency = <200000>; // (200 kHz) max 2000000 (2MHz)
                interrupts = <17 IRQ_TYPE_EDGE_RISING>;
                interrupt-parent = <&gpio>;
            };
        };
    };
 
    __overrides__ {
        /*
         * This gives an option to use the gpio25 as the data ready pin. This
         * must be used for the adis16465/7 families as these devices use the
         * 14 pin connector where DR is using gpio25. Note that this should
         * not be used for the other devices as the gpio25 is both connected to
         * the sync selector and to the sync pin (because the sync and DR pins
         * are swapped in the 16 pin connector).
         */
        drdy_gpio25 = <&adis16475_pins>,"brcm,pins:0=25",
                <&adis16475>,"interrupts:0=25";
        device = <&adis16475>,"compatible";
        sync_mode = <&adis16475>,"adi,sync-mode:0"; /* Note: 0 = output_sync, 1 = direct_sync, 2 = scaled_sync, 3 = pulse_sync */
        ext_sync_freq = <&adis16475_ref_clk>, "clock-frequency:0",
                <&adis16475>,"clocks:0=",<&adis16475_ref_clk>;
    };
};

Note that the DMA buffer is enabled for the SPI bus.

We noticed that the ADIS16475 became unresponsive when attempting to run the spi bus at the maximum rate for the device (2MHz) and at some lower frequencies (1MHz and 500KHz) and hence 200kHz and 100kHz were both reasonable tested frequencies. However note that at 100kHz there were some issues with IMU-side sampling frequencies above 200Hz. Also note that at 200kHz bus frequency, attempting to stream at 1000Hz resulted in IMU frequencies of only 500Hz in our tests.

This uses pins specific to the grand_tour breakout board. To work with the Compute Module 4 I/O board 3 lines must be changed. The interrupt pin 17 should be replaced with 22, and the reset pin 23 should be replaced with 27 (this is flexible). For a default raspberry PI setup, pins 4 and 12 are often used for the interrupt and reset.

Next, modify arch/arm64/boot/dts/overlays/Makefile with the following line (anywhere before the end) so that the overlay is compiled:

    adis16475.dtbo \

Modify the following lines of /boot/config.txt (from Bookworm (12) onwards, this is /boot/firmware/config.txt):

# ADIS16475 IMU
[all]
dtoverlay=adis16475
dtparam=device="adi,adis16475-2"

One may also need to enable SPI by uncommenting:

dtparam=spi=on

c. Build & Install the Kernel

make -j6 Image.gz modules dtbs
sudo make -j6 modules_install

To make a backup of the current kernel (noting again that /boot/firmware/ is used from Bookworm (12) onwards):

sudo cp /boot/$KERNEL.img /boot/$KERNEL-backup.img

Install:

sudo cp arch/arm64/boot/Image.gz /boot/$KERNEL.img
sudo cp arch/arm64/boot/dts/broadcom/*.dtb /boot/
sudo cp arch/arm64/boot/dts/overlays/*.dtb* /boot/overlays/
sudo cp arch/arm64/boot/dts/overlays/README /boot/overlays/

Reboot to run the new kernel:

sudo reboot

Check the new kernel is loaded with:

uname -a

d. ADIS16475 Permissions

The ADIS16475 and its trigger exist at /sys/bus/iio/devices/. In order to run drivers without requiring administrator priviledges, modify the udev rules:

sudo mkdir -p /usr/local/lib/udev/rules.d
sudo echo "KERNEL==\"iio:device[0-9]*\", SUBSYSTEM==\"iio\", GROUP=\"iio\", MODE=\"0660\", PROGRAM=\"/bin/sh -c 'chgrp -R iio /sys%p; chmod -R g=u /sys%p'\"" > /usr/local/lib/udev/rules.d/98-iio.rules
sudo groupadd iio
sudo usermod -aG iio $USER
sudo udevadm control --reload-rules
sudo udevadm trigger

While this gives priveledges for what the kernel driver exposes in /sys/bus/iio/devices/, this doesn't give permissions to read and write to registers arbitrarily (e.g. for sending software resets). It is not yet known how to do this.

Step 5: Setting up the rest:

From this point one can follow grand_tour_box/box_configuration/pi/pi_configure.sh This includes setting up system services for:PTP, PIGPIO, Docker, creating a ROS docker image, Fan Control, Boxi, Modifying the bashrc. Warning: The docker container is currently sketchy given that it requires you to just fetch the latest docker image from github then add some installations and docker commit it. We should add a clean Dockerfile to this.

PCB

grand_tour_pi_breakout_board.pdf

(Always output trigger - feedback pin)

FAN_PWM_25kHz

  • PWM0_0 -> GPIO18
  • GPIO16 (feedback for PWM speed) ->

CAM_PWM_30Hz

  • PWM0_1 -> GPIO19
  • GPIO26

ADIS_CLK_1.6kHz

  • GPCLK0 -> GPIO4
  • GPIO27
    • (SPI)

SAFRAN_CLK_2kHz

  • GPCLK1 -> GPIO5
  • GPIO22
  • (+RS422)

HONEY_CLK_1.2kHz

  • GPCLK2 -> GPIO6
  • GPIO25
  • (+RS422)

NTC (I2C):

  • SCL - I2C1_SCL -> GPIO3
  • SDA - I2C1_SDA -> GPIO2

pi_breakout_old

pi_breakout_new

LED Driver tca6408a.pdf

Button/LED

Links

Clone this wiki locally