Raspberry Pi and Zephyr

The Zephyr Getting Started Guide is great at helping you get started on Windows, Mac or Linux.

At Accelerando, we like to use the Raspberry Pi (an inexpensive single-board computer, running Linux, using an ARM CPU) as a Zephyr development platform, although this is not officially supported by the Zephyr instructions.

Why develop on Pi?

When one has a nice grunty workstation which compiles your Zephyr OS and application in just a few seconds, why would one want to do that on a less powerful system instead?

Firstly, most of the chips we work with are programmed over USB. When developing on a notebook, cable ports can be limited, and one may wish not to be tethered to a complex arrangement of devices.

Also, unfortunately, some of the USB-serial-port chips you’ll encounter on development boards have somewhat cantankerous device-drivers for Mac and Windows, which are known to occasionally get confused and require a (frustrating) reboot, though they do seem to work more reliably under Linux.

By using a separate “helper system” to handle the cabled connections to development boards, this means that that one can set up a test rig wherever it needs to be, for example outside under the open sky where there is GPS and Radio Line-of-sight, or out on a factory floor attached to some noisy machinery, or up on a roof, or floating in a lake, while the engineer is able to work from somewhere more convenient.

Secondly, we’re committed at Accelerando to bringing embedded development out of the 1980s by using source control, build pipelines, test suites and all the things that grown up programmers use. Small inexpensive Linux systems like the Raspberry Pi and its squadron of successor-imitators are like the Lego bricks of embedded development automation; they allow us to ensure that we have a reliable and repeatable deployment process.

Setting up your Pi

So how, if it isn’t officially supported, can we get Zephyr onto a Raspberry Pi?

Firstly, we haven’t tried this for every chip that Zephyr supports; we mostly work with ARM processors and the ESP32, and thus the following all applies to them.

Although Zephyr doesn’t provide a convenient package, the GCC port for ARM is provided as a binary by its project team, and the same is true for the ESP compilers. Python runs well pretty much anywhere, fortunately.

The one gotcha is that if you are going to do this the way we did, you should go out and get a Raspberry Pi Model 4 or newer, with at least 4GB of RAM.

You can run on a 1M system such as the Raspberry Pi Model 3B, but in particular the pyocd tool may be difficult to compile due to the amount of memory used during the compilation process (you can work around this by using openocd to do the same tasks that would normaly require pyocd).

Zephyr install on Pi

To summarise:

  • Install Ubuntu, not Raspberry OS (Raspbian/Raspberry OS is missing some of the cross-compiler packages, so you’d need to compile those from source if you choose Raspbian as your starting point)
  • Get a SBC with 4G of Ram (because rustc)
  • Consider useing our SaltStack rules to one-step install everything (see below)

Step-by-step:

sudo apt-get install git cmake ninja-build gperf ccache dfu-util device-tree-compiler wget python3-dev python3-pip python3-setuptools python3-tk python3-wheel xz-utils file make gcc gcc-multilib-arm-linux-gnueabihf g++-multilib-arm-linux-gnueabihf libsdl2-dev

sudo pip3 install west imgtool

sudo mkdir -p /usr/local/gnuarmemb

curl https://developer.arm.com/-/media/Files/downloads/gnu-rm/9-2020q2/gcc-arm-none-eabi-9-2020-q2-update-aarch64-linux.tar.bz2 | sudo tar --strip-components=1 --directory=/usr/local/gnuarmemb -jxf -

echo 'export ZEPHYR_TOOLCHAIN_VARIANT=gnuarmemb' | sudo tee -a /etc/profile.d/zephyr.sh
echo 'export GNUARMEMB_TOOLCHAIN_PATH=/usr/local/gnuarmemb/' | sudo tee -a /etc/profile.d/zephyr.sh
echo 'export PATH=${HOME}/.local/bin:${PATH}' | sudo tee -a /etc/profile.d/zephyr.sh

west init ~/zephyrproject
cd ~/zephyrproject
west update
west zephyr-export

pip3 install --user -r zephyr/scripts/requirements.txt

Automating installation with SaltStack

If you want to automate this process, then you can find automation rules in our “Kevin” project, which we use to automate many kinds of development on Raspberry Pi machines: github.com/unixbigot/kevin#quick-start.

Once you’ve installed salt-minion, setting up zephyr using Kevin is essentially a single command:

sudo salt-call --local state.apply dev.zephyr

Installing PyOCD on Raspberry Pi

PyOCD is an open-source Python program for installing your programs into the flash memory of ARM microcontrollers, and, for many ARM-derivative chips supported by Zephyr, pyocd the default installation tool invoked when you type west flash.

It is slightly tricky to install pyocd on computers with only (!) one Gigabyte of memory.

The source of difficulty appears to be that PyOCD depends on a Python library that is implemented in the Rust programming language, and the compilation of that component consumes enough memory that it grinds a 1GB machine to a complete standstill. I’m sure you could work around this, but I am neither a Rust nor a Python guru, and so I addressed the issue by just acquiring more RAM.

sudo apt-get install python3 cargo openocd libusb-dev
pip3 install pyocd

Installing OpenOCD on Raspberry Pi

Zephyr supports a number of ways of installing firmware onto your target board, Jlink and PyOCD are most common methods defined for ARM-based microcontrollers. Installing these tools on Raspberry Pi can be tricky, so we can use OpenOCD instead.

OpenOCD is packaged for Raspbian and Ubuntu, so you may choose to simply invoke apt-get install openocd. However, if you want to customise which programming devices are supported by OpenOCD (eg. to use your Raspberry Pi’s GPIO pins as a zero cost programming cable), you can compile OpenOCD from source-code relatively easily:

sudo apt-get install git autoconf libtool make pkg-config libusb-1.0-0 libusb-1.0-0-dev
sudo mkdir -m 775 /opt
sudo chgrp adm /opt
git clone http://openocd.zylin.com/openocd /opt/openocd
cd /opt/openocd
./bootstrap
./configure --enable-sysfsgpio --enable-bcm2835gpio
make
sudo make install

If you’re using Saltstack and Kevin, again the shortcut to do this is:

salt-call --local state.apply dev.openocd