How to use Nrfutil for BLE DFU on Raspberry Pi

Morning Everyone,

We use raspberry pis as part of our test equipment. The final stage of our CI/CD pipeline downloads the build dfu packages to a Pi and then does an OTA update onto our hardware.

However, out of the box, nrfutil cannot do a bluetooth DFU update. This is because the pc-ble-driver library that interfaces with the bluetooth dongle does not work on arm64 architectures. Here is what i did to get it working. I thought it would be useful to some of you!

Please treat these intructions with a pinch of salt, they worked for me, but they may need some adjustment to work for you! (they may also work for new Mac machines with the arm64 architecture too)

#! /bin/bash

# script to rebuild pc-ble-drivers package for raspberry pi
# based on this: https://devzone.nordicsemi.com/f/nordic-q-a/47329/connection-3b-armv8-and-nrf-52840-dongle/188449#188449
# and this: https://github.com/NordicSemiconductor/pc-ble-driver-py/issues/202#issuecomment-1043871397

sudo apt-get update
sudo apt-get -y install build-essential git autoconf libudev-dev ninja-build libboost-dev cmake libspdlog-dev software-properties-common zlib1g-dev libncurses5-dev libgdbm-dev libnss3-dev libssl-dev libsqlite3-dev libreadline-dev libffi-dev curl libbz2-dev

# Download, build and install Python 3.8 as nrfutil doesn't work with the default version of python installed with Raspbian (Currently 3.9)
# https://krystof.io/installing-alternative-python-versions-on-raspberry-pi/
# https://linuxize.com/post/how-to-install-python-3-8-on-debian-10/
# https://www.linuxcapable.com/how-to-install-python-3-8-on-debian-11-bullseye/

# Please, please, please Nordic, update nrfutil so it will work with the current releases of Python. (sobs on floor)
# Or open source it so the community can fix it!

sudo apt-get remove --purge python3
wget https://www.python.org/ftp/python/3.8.13/Python-3.8.13.tar.xz
tar -xvf Python-3.8.13.tar.xz
cd Python-3.8.13
./configure --enable-optimizations
make -j 6
sudo make install 

# note that this installs in your user directory, doing it somewhere else would probably be a good idea.

# make the keyword python point to python 3.8
sudo update-alternatives --install /usr/bin/python python '/home/pi/Python-3.8.13/python' 1

# install pip
wget https://bootstrap.pypa.io/get-pip.py
python get-pip.py

# remove unused files to save space
cd ..
rm Python-3.8.13.tar.xz

# install dependencies for pc-ble-driver build
cd ~
git clone https://github.com/catchorg/Catch2.git
cd Catch2
cmake -Bbuild -H. -DBUILD_TESTING=OFF
sudo cmake --build build/ --target install 

cd ~
wget https://sourceforge.net/projects/asio/files/asio/1.12.2%20%28Stable%29/asio-1.12.2.tar.gz
tar xvf asio-1.12.2.tar.gz
cd asio-1.12.2
autoreconf -i
./configure
make
sudo make install

# note - in CMakeLists.txt you must comment out the TEST_BIG_ENDIAN test, it keeps not working for some reason

cd ~
git clone https://github.com/NordicSemiconductor/pc-ble-driver
cd pc-ble-driver
mkdir build
cd build
cmake -G Ninja .. -DDISABLE_TESTS=1 -DDISABLE_EXAMPLES=1 -DARCH=arm64 -DNRF_BLE_DRIVER_VERSION=4.1.4 -DCONNECTIVITY_VERSION=4.1.4

# at this point, find the build.ninja file, open it and do this find and replace:
# find: -m64
# replace: -march=armv8-a+crc

# The reason for this is that for some reason when you call the cmake with the arm64 keyword as above, it adds the incorrect compiler option for the architecture of the pi
# I'm sure there's a better way of doing this, but after a full week of fighting with this, i couldn't be bothered to find out.

cmake --build .
mkdir dist
cmake --install . --prefix dist

# build the python library for this

# swig is a c/c++ to higher level language interface required for pc-ble-driver-py
sudo apt install swig 
git clone https://github.com/NordicSemiconductor/pc-ble-driver-py.git --branch release/0.16.2
cd pc-ble-driver-py
pip3 install --upgrade pip scikit-build
pip3 install -r requirements-dev.txt

export CMAKE_PREFIX_PATH=$(pwd)/../pc-ble-driver/build/dist
python setup.py bdist_wheel --build-type Release

pip install /home/pi/pc-ble-driver-py/dist/pc_ble_driver_py-0.16.3-cp38-cp38-linux_aarch64.whl
pip install nrfutil==6.1.3 # if you need this one as well, as pc-ble-driver-py is already satisfied, everything is good

# google have done something to the protobuf library that nrfutil uses, which stops nrfutil from working (facepalm) so you need to downgrade protobuf to allow nrfutil to work

# protobuf 4.20.1 
pip uninstall protobuf
pip install protobuf==3.20.1

Fingers Crossed, you will now be able to use nrfutil to do a ble dfu from your pi! Good Luck!

Related