Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save dataslayermedia/714ec5a9601249d9ee754919dea49c7e to your computer and use it in GitHub Desktop.
Save dataslayermedia/714ec5a9601249d9ee754919dea49c7e to your computer and use it in GitHub Desktop.
Install Coral AI PCIe Edge TPU on Raspberry Pi 5
#!/bin/bash
cd /
sudo apt update
echo "deb https://packages.cloud.google.com/apt coral-edgetpu-stable main" | sudo tee /etc/apt/sources.list.d/coral-edgetpu.list
curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
sudo apt-get update
sudo apt-get install libedgetpu1-std
sudo apt install -y devscripts debhelper
sudo apt install dkms
sudo apt-get install dh-dkms
# Clone the Gasket driver repository
sudo git clone https://github.com/google/gasket-driver.git
# Change directory to the cloned repository
cd gasket-driver
# Build the Gasket driver package
sudo debuild -us -uc -tc -b
# Go back to the parent directory
cd ..
# Install the built Gasket driver package
sudo dpkg -i gasket-dkms_1.0-18_all.deb
sudo sh -c "echo 'SUBSYSTEM==\"apex\", MODE=\"0660\", GROUP=\"apex\"' >> /etc/udev/rules.d/65-apex.rules"
sudo groupadd apex
sudo adduser $USER apex
# Update the boot configuration for Raspberry Pi
echo "kernel=kernel8.img" | sudo tee -a /boot/firmware/config.txt
# Back up the Device Tree Blob (DTB)
sudo cp /boot/firmware/bcm2712-rpi-5-b.dtb /boot/firmware/bcm2712-rpi-5-b.dtb.bak
# Decompile the DTB into a DTS file
sudo dtc -I dtb -O dts /boot/firmware/bcm2712-rpi-5-b.dtb -o ~/test.dts
# Modify the Device Tree Source (DTS)
sudo sed -i '/pcie@110000 {/,/};/{/msi-parent = <[^>]*>;/{s/msi-parent = <[^>]*>;/msi-parent = <0x67>;/}}' ~/test.dts
# Recompile the DTS back into a DTB
sudo dtc -I dts -O dtb ~/test.dts -o ~/test.dtb
# Replace the old DTB with the new one
sudo mv ~/test.dtb /boot/firmware/bcm2712-rpi-5-b.dtb
sudo reboot now
@feranick
Copy link

feranick commented May 8, 2024

You need the gasket-dkms, not sure you have it installed. You can compile it following this info:

https://github.com/google/gasket-driver

or use prebuilt debs.

https://github.com/feranick/gasket-driver/releases/download/1.0-18.2/gasket-dkms_1.0-18.2_all.deb

@EnziinSystem
Copy link

EnziinSystem commented May 9, 2024

It needs to be at 6.6.30 or higher

The config dtoverlay=pineboards-hat-ai doesn't work.

Here are the steps:

$ rpi-eeprom-update -a
$ sudo rpi-update

$ uname -a
Linux smarthome 6.6.30-v8+ #1761 SMP PREEMPT Thu May  2 16:54:52 BST 2024 aarch64 GNU/Linux

Configure

sudo nano /boot/firmware/config.txt

Add lines

[all]
# Enable the PCIe External connector.
dtparam=pciex1
dtparam=pciex1_gen=3
kernel=kernel8.img

# Enable Pineboard
dtoverlay=pineboards-hat-ai

Turn off PCI ASPM

sudo nano /boot/firmware/cmdline.txt

Add **pcie_aspm=off** before **rootwait**

sudo reboot

Install the PCIe driver and Edge TPU runtime

sudo apt update

echo "deb https://packages.cloud.google.com/apt coral-edgetpu-stable main" | sudo tee /etc/apt/sources.list.d/coral-edgetpu.list

curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -

sudo apt-get update

sudo apt-get install cmake

sudo apt-get install -y libedgetpu1-std

sudo apt install -y devscripts debhelper

sudo apt install -y dkms

sudo apt-get install -y dh-dkms

# Clone the Gasket driver repository

sudo git clone https://github.com/google/gasket-driver.git

cd gasket-driver

sudo debuild -us -uc -tc -b

# Go back to the parent directory
cd ..

# Install the built Gasket driver package

sudo dpkg -i gasket-dkms_1.0-18_all.deb

Selecting previously unselected package gasket-dkms.
(Reading database ... 175909 files and directories currently installed.)
Preparing to unpack gasket-dkms_1.0-18_all.deb ...
Unpacking gasket-dkms (1.0-18) ...
Setting up gasket-dkms (1.0-18) ...
Loading new gasket-1.0 DKMS files...
Deprecated feature: REMAKE_INITRD (/usr/src/gasket-1.0/dkms.conf)
Building for 6.6.30-v8+
Module build for kernel 6.6.30-v8+ was skipped since the
kernel headers for this kernel do not seem to be installed.

Note: Module build for kernel 6.6.30-v8+ was skipped since the kernel headers for this kernel do not seem to be installed

Set udev rule

sudo sh -c "echo 'SUBSYSTEM==\"apex\", MODE=\"0660\", GROUP=\"apex\"' >> /etc/udev/rules.d/65-apex.rules"

sudo groupadd apex

sudo adduser $USER apex

sudo reboot now

Result

$ lspci
0000:00:00.0 PCI bridge: Broadcom Inc. and subsidiaries Device 2712 (rev 21)
0000:01:00.0 PCI bridge: ASMedia Technology Inc. ASM1182e 2-Port PCIe x1 Gen2 Packet Switch
0000:02:03.0 PCI bridge: ASMedia Technology Inc. ASM1182e 2-Port PCIe x1 Gen2 Packet Switch
0000:02:07.0 PCI bridge: ASMedia Technology Inc. ASM1182e 2-Port PCIe x1 Gen2 Packet Switch
0000:03:00.0 System peripheral: Global Unichip Corp. Coral Edge TPU
0000:04:00.0 Non-Volatile memory controller: Phison Electronics Corporation E8 PCIe3 NVMe Controller (rev 01)
0001:00:00.0 PCI bridge: Broadcom Inc. and subsidiaries Device 2712 (rev 21)
0001:01:00.0 Ethernet controller: Device 1de4:0001

List TPU

$ lspci -nn | grep 089a
0000:03:00.0 System peripheral [0880]: Global Unichip Corp. Coral Edge TPU [1ac1:089a]

$ ls /dev/apex_0
ls: cannot access '/dev/apex_0': No such file or directory

$ sudo modprobe gasket
modprobe: FATAL: Module gasket not found in directory /lib/modules/6.6.30-v8+

$ sudo modprobe apex
modprobe: FATAL: Module apex not found in directory /lib/modules/6.6.30-v8+

Note: I did not make changes to MSI-parent and did not recompile the DTB

@askpatrickw
Copy link

@EnziinSystem I concur and I followed those exact steps.
I have also tried installing the releases of gasket from Freneck's repo both of which do not seem to be aligned with the 6.6.30 headers.

@mikegapinski
Copy link

@askpatrickw @EnziinSystem I'll get the tutorial for all AI boards uploaded to our docs website today

@EnziinSystem
Copy link

@askpatrickw @EnziinSystem I'll get the tutorial for all AI boards uploaded to our docs website today

When you're done, please give us the link here.

Thanks.

@mikegapinski
Copy link

@EnziinSystem https://pineboards.io/blogs/tutorials/how-to-configure-the-google-coral-edge-tpu-on-the-raspberry-pi-5

This covers the DMKS drives as well as updating the kernel with rpi-update and installing the headers with rpi-source (since 6.6.30 is not live via apt yet.

@andrewtemy
Copy link

sudo wget https://raw.githubusercontent.com/jgartrel/rpi-
--2024-05-09 12:24:03-- https://raw.githubusercontent.com/jgartrel/rpi-
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.108.133
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.108.133|:443... connected.
HTTP request sent, awaiting response... 400 Bad Request
2024-05-09 12:24:03 ERROR 400: Bad Request.

@mikegapinski
Copy link

Check the URL:

mgapinski@coraltest:~ $ sudo wget https://raw.githubusercontent.com/jgartrel/rpi-source/master/rpi-source -O /usr/bin/rpi-source
--2024-05-09 11:52:17-- https://raw.githubusercontent.com/jgartrel/rpi-source/master/rpi-source
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.111.133, 185.199.110.133, 185.199.109.133, ...
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.111.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 16757 (16K) [text/plain]
Saving to: ‘/usr/bin/rpi-source’

/usr/bin/rpi-source 100%[=============================================================================================================================================>] 16.36K --.-KB/s in 0.004s

2024-05-09 11:52:17 (4.46 MB/s) - ‘/usr/bin/rpi-source’ saved [16757/16757]

mgapinski@coraltest:~ $ sudo chmod +x /usr/bin/rpi-source
mgapinski@coraltest:~ $ rpi-source --tag-update

*** SoC: BCM2712

*** Arch: 64-bit

*** Page Size: 4096

*** Set update tag: c1c78350ad097dff3289b07587120b84c3329878
mgapinski@coraltest:~ $ rpi-source --default-config

*** SoC: BCM2712

*** Arch: 64-bit

*** Page Size: 4096

*** rpi-update: https://github.com/Hexxeh/rpi-firmware

*** Firmware revision: 6bb99655a963e73937b981bbdf530da1a98e2b51

*** Linux source commit: ee713e438df8e09e01e4f7598382d3703db5d4c4

@andrewtemy
Copy link

andrewtemy commented May 9, 2024

thank you so much @mikegapinski ! finally, it works for me

sudo lspci -v
0000:01:00.0 System peripheral: Global Unichip Corp. Coral Edge TPU (prog-if ff)
Subsystem: Global Unichip Corp. Coral Edge TPU
Flags: bus master, fast devsel, latency 0, IRQ 39
Memory at 1800100000 (64-bit, prefetchable) [size=16K]
Memory at 1800000000 (64-bit, prefetchable) [size=1M]
Capabilities: [80] Express Endpoint, MSI 00
Capabilities: [d0] MSI-X: Enable+ Count=128 Masked-
Capabilities: [e0] MSI: Enable- Count=1/32 Maskable- 64bit+
Capabilities: [f8] Power Management version 3
Capabilities: [100] Vendor Specific Information: ID=1556 Rev=1 Len=008 <?>
Capabilities: [108] Latency Tolerance Reporting
Capabilities: [110] L1 PM Substates
Capabilities: [200] Advanced Error Reporting
Kernel driver in use: apex
Kernel modules: apex

ls /dev/apex_*
/dev/apex_0

@askpatrickw
Copy link

askpatrickw commented May 10, 2024

@mikegapinski, I'd post a comment on your post, but no way to do that.

The kernel update steps result in the following errors, for me anyway.

My Pi

cat /proc/cpuinfo | grep -i model
Model		: Raspberry Pi 5 Model B Rev 1.0

Make Fails

make libncurses5-dev
make: *** No rule to make target 'libncurses5-dev'.  Stop.

rpi-source fails

rpi-source --tag-update
ERROR:
Unexpected processor 4 (use --processor argument)

I opened a bug on this last one as the docs are not helpful.
RPi-Distro/rpi-source#32

@mikegapinski
Copy link

That is why I linked a fork of RPI-Distro in my tutorial sudo wget https://raw.githubusercontent.com/jgartrel/rpi-source/master/rpi-source -O /usr/bin/rpi-source

The command rpi-source --tag-update blocks it from being overwritten with the official one

@askpatrickw
Copy link

@mikegapinski ... yes. I did use all the commands in your tutorial.
I was just being brief in my notes. Here you can see the full commands don't work.

$ sudo apt install git bc bison flex libssl-dev make libncurses5-dev
sudo wget https://raw.githubusercontent.com/jgartrel/rpi-source/master/rpi-source -O /usr/bin/rpi-source
sudo chmod +x /usr/bin/rpi-source
rpi-source --tag-update

Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
git is already the newest version (1:2.39.2-1.1).
bc is already the newest version (1.07.1-3).
bison is already the newest version (2:3.8.2+dfsg-1+b1).
flex is already the newest version (2.6.4-8.2).
libssl-dev is already the newest version (3.0.11-1~deb12u2+rpt1).
make is already the newest version (4.3-4.1).
libncurses5-dev is already the newest version (6.4-4).
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
--2024-05-11 11:13:23--  https://raw.githubusercontent.com/jgartrel/rpi-source/master/rpi-source
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.108.133, 185.199.109.133, 185.199.110.133, ...
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.108.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 16757 (16K) [text/plain]
Saving to: ‘/usr/bin/rpi-source’

/usr/bin/rpi-source                         100%[========================================================================================>]  16.36K  --.-KB/s    in 0.1s

2024-05-11 11:13:24 (118 KB/s) - ‘/usr/bin/rpi-source’ saved [16757/16757]

ERROR:
Unexpected processor 4 (use --processor argument)

Help: https://github.com/RPi-Distro/rpi-source/blob/master/README.md

@sadontsev
Copy link

sadontsev commented May 17, 2024

@mikegapinski Hi Mike,
Thank you very much for your guide.

I was hoping you can help me to sort out why after all of the steps I don't see the TPU available as apex?

➜  ~ ls /dev/apex_*
zsh: no matches found: /dev/apex_*

I've got the dual-core M.2 A+E TPU and RPI5 with A+E PCIE head, Mcuzone.

Following your steps, I've upgraded to 6.6.30-v8+ #1763 SMP PREEMPT Mon May 13 17:50:31 BST 2024 aarch64

Trying different things around I suspect that maybe my release of the kernel is problematic, not supported by the driver?.
➜ ~ sudo apt install dkms build-essential

Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
dkms is already the newest version (3.0.10-8+deb12u1).
build-essential is already the newest version (12.9).
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.

➜ ~ git clone https://github.com/google/gasket-driver

cd gasket-driver
fatal: destination path 'gasket-driver' already exists and is not an empty directory.

➜ gasket-driver git:(main) sudo dkms add .

sudo dkms build gasket/1.0
sudo dkms install gasket/1.0
Error! Arguments <module> and <module-version> are not specified.
Usage: add <module>/<module-version> or
       add -m <module>/<module-version> or
       add -m <module> -v <module-version>
Sign command: /lib/modules/6.6.30-v8+/build/scripts/sign-file
Binary /lib/modules/6.6.30-v8+/build/scripts/sign-file not found, modules won't be signed
Deprecated feature: REMAKE_INITRD (/var/lib/dkms/gasket/1.0/source/dkms.conf)
Error! Your kernel headers for kernel 6.6.30-v8+ cannot be found at /lib/modules/6.6.30-v8+/build or /lib/modules/6.6.30-v8+/source.
Please install the linux-headers-6.6.30-v8+ package or use the --kernelsourcedir option to tell DKMS where it's located.
Sign command: /lib/modules/6.6.30-v8+/build/scripts/sign-file
Binary /lib/modules/6.6.30-v8+/build/scripts/sign-file not found, modules won't be signed
Deprecated feature: REMAKE_INITRD (/var/lib/dkms/gasket/1.0/source/dkms.conf)
Error! Your kernel headers for kernel 6.6.30-v8+ cannot be found at /lib/modules/6.6.30-v8+/build or /lib/modules/6.6.30-v8+/source.
Please install the linux-headers-6.6.30-v8+ package or use the --kernelsourcedir option to tell DKMS where it's located.

I ran the kernel headers installation ahead of this attempt.
Just like I previously downloaded and installed drivers from Google with no visible errors.
Surely tried rebooting multiple times.

Overall, the TPU is recognisable (maybe at least 1 core, I'm not sure. But it's less important at the moment):
➜ ~ lspci -nn | grep 089a 0000:01:00.0 System peripheral [0880]: Global Unichip Corp. Coral Edge TPU [1ac1:089a]

Many thanks.

@mikegapinski
Copy link

mikegapinski commented May 17, 2024 via email

@sadontsev
Copy link

@mikegapinski you're the best.
It did indeed help. The driver is working now.

So now I'm wondering what exactly am I missing to see both cores (as I remember they're supposed to be displayed separately).
I'll try to look into it myself, however if you're got some ideas, you're welcome :)

@mikegapinski
Copy link

@sadontsev you need the HAT Ai Dual if you want to see two accelerators. This board has a PCIe switch for the Dual Edge TPU

@sadontsev
Copy link

@mikegapinski yeah, thanks. I was promised by the seller that mine would support it. But maybe it was a trick.

Here's some info

@mikegapinski
Copy link

@mikegapinski yeah, thanks. I was promised by the seller that mine would support it. But maybe it was a trick.

Here's some info

In theory it does support it, but not fully. The Dual Edge variant needs a dedicated board

@sadontsev
Copy link

sadontsev commented May 18, 2024

@mikegapinski yeah, you're right.

Upd, maybe I found what's wrong:
$ dmesg
...
[ 5496.544355] apex 0000:01:00.0: RAM did not enable within timeout (12000 ms)
[ 5496.544364] apex 0000:01:00.0: Error in device open cb: -110
...

Which may related to the connection issue. See comment section here
Yet, it was too early to celebrate. For whatever reason, the TPU cannot be identified yet either by Frigate or simple Python script (bare metal w/ pyenv or via Docker).
I even tried a clean OS installation on a spare card but didn't help.
I appreciate if someone can suggest the next steps here:

Frigate:
Relevant pieces of the config:
--device /dev/apex_0:/dev/apex_0 \

detectors:
  coral1:
    type: edgetpu
    device: pci:0

Error:

2024-05-18 13:47:27.411259143    File "/usr/lib/python3/dist-packages/tflite_runtime/interpreter.py", line 160, in load_delegate
2024-05-18 13:47:27.411261273      delegate = Delegate(library, options)
2024-05-18 13:47:27.411262995    File "/usr/lib/python3/dist-packages/tflite_runtime/interpreter.py", line 119, in __init__
2024-05-18 13:47:27.411264198      raise ValueError(capture.message)
2024-05-18 13:47:27.411265106  ValueError
2024-05-18 13:47:27.411306013  
2024-05-18 13:47:27.411308217  During handling of the above exception, another exception occurred:
2024-05-18 13:47:27.411309050  
2024-05-18 13:47:27.411310198  Traceback (most recent call last):
2024-05-18 13:47:27.411312272  [2024-05-18 13:47:15] frigate.comms.mqtt             ERROR   : Unable to publish to eyeofsauron/motion: client is not connected
2024-05-18 13:47:27.411313883    File "/usr/lib/python3.9/multiprocessing/process.py", line 315, in _bootstrap
2024-05-18 13:47:27.411314828      self.run()
2024-05-18 13:47:27.411316643    File "/usr/lib/python3.9/multiprocessing/process.py", line 108, in run
2024-05-18 13:47:27.411318772      self._target(*self._args, **self._kwargs)
2024-05-18 13:47:27.411320291    File "/opt/frigate/frigate/object_detection.py", line 102, in run_detector
2024-05-18 13:47:27.411321920      object_detector = LocalObjectDetector(detector_config=detector_config)
2024-05-18 13:47:27.411323939    File "/opt/frigate/frigate/object_detection.py", line 53, in __init__
2024-05-18 13:47:27.411350791      self.detect_api = create_detector(detector_config)
2024-05-18 13:47:27.411352828    File "/opt/frigate/frigate/detectors/__init__.py", line 18, in create_detector
2024-05-18 13:47:27.411366994      return api(detector_config)
2024-05-18 13:47:27.411375383    File "/opt/frigate/frigate/detectors/plugins/edgetpu_tfl.py", line 41, in __init__
2024-05-18 13:47:27.411377031      edge_tpu_delegate = load_delegate("libedgetpu.so.1.0", device_config)
2024-05-18 13:47:27.411378772    File "/usr/lib/python3/dist-packages/tflite_runtime/interpreter.py", line 162, in load_delegate
2024-05-18 13:47:27.411380198      raise ValueError('Failed to load delegate from {}\n{}'.format(
2024-05-18 13:47:27.411381568  ValueError: Failed to load delegate from libedgetpu.so.1.0

Python:

from tflite_runtime.interpreter import Interpreter, load_delegate

try:
    delegate = load_delegate('libedgetpu.so.1')
    print("Edge TPU delegate loaded successfully")

    interpreter = Interpreter(
        model_path='mobilenet_ssd_v2_coco_quant_postprocess_edgetpu.tflite',
        experimental_delegates=[delegate]
    )
    interpreter.allocate_tensors()
    print("Model loaded and tensors allocated")
except ValueError as e:
    print(f"Failed to load Edge TPU delegate: {e}")
    import traceback
    traceback.print_exc()
Traceback (most recent call last):
  File "test_tflite_edgetpu.py", line 4, in <module>
    delegate = load_delegate('libedgetpu.so.1')
  File "/home/max/.pyenv/versions/tpu-env-3.8/lib/python3.8/site-packages/tflite_runtime/interpreter.py", line 168, in load_delegate
    raise ValueError('Failed to load delegate from {}\n{}'.format(
ValueError: Failed to load delegate from libedgetpu.so.1

While the device is here and can be recognised:

(tpu-env-3.8) max@nasnew:~/tpu $ lspci -nn | grep 089a
0000:01:00.0 System peripheral [0880]: Global Unichip Corp. Coral Edge TPU [1ac1:089a]
(tpu-env-3.8) max@nasnew:~/tpu $ ls /dev/apex_*
/dev/apex_0

@mikegapinski
Copy link

This can happen if the board you use does not have proper routing and a high quality FPC cable: raspberrypi/linux#6126

That is why the kernel overlay is not for coral itself, it does not work on all PCIe hats.

You can check for dmesg errors, but I think this is the problem

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment