Building SnapOS Image for Raspberry Pi Zero W with buildroot in WSL2#

hifi


TL;DR This is a description of the process to create sdcard.img for the Raspberry Pi Zero W with HiFiBerry DAC Hat in Windows Subsystem for Linux (WSL2).


Motivation For small things, I like the Raspberry Pi Zero WH because it only consumes 0.7W. But, in order to reduce workload, specific buildroot images must be created, with only the tools needed.

I came a long way trying to create an sdcard.img for SnapOS for the Raspberry Pi Zero W(H).

However, the whole process is more complex, so I wrote down the steps.

Skip the parts that are not relevant to you (e.g. setup of WSL).

Check the list of items that I used at the end of this article.


Prepare WSL2#

It is entirely possible to do all of this in Docker. But, setup of WSL2 is necessary anyway, so lets simply create a separate WSL2 distro to run buildroot.

Note: This is really starting from the roots. Skip this is you already have WSL2 or Docker.

  1. Install LxRunOffline with Choco

To install LxRunOffline, I prefer Chocolatey package manager.

In a cmd shell with administrator privileges, run:

choco install lxrunoffline
  1. Enable WSL2 Support in Windows

To enable WSL2 support in Windows 10, download and install wsl_update_x64.msi.

Afterwards, in the cmd from above, run:

dism.exe /online /enable-feature ^
    /featurename:VirtualMachinePlatform /all /norestart

You may need to restart for these changes to apply.

  1. Download Ubuntu Linux Image

Get the latest Ubuntu Image from Canonical.

Here, I use the Ubuntu Focal Fossa image.

Store it somewhere, e.g.:

C:\temp\ubuntu-focal-core-cloudimg-amd64-root.tar.gz

  1. Install Ubuntu with LxRunOffline

Open a cmd window with admin privileges.

To list existing WSL distros:

wsl --list --verbose

To install Ubuntu image as a new WSL:

LxRunOffline i -n UF_2 ^
    -d c:\WSL\UFull_2 ^
    -f "c:\temp\ubuntu-focal-core-cloudimg-amd64-root.tar.gz" -s

Afterwards, you may need to upgrade to WSL2:

wsl --set-version UF_2 2

  1. Install WSLtty (Optional)

This is optional, but I found accessing and working in WSL easier with wsltty.

choco install wsltty
  1. Prepare WSL2 Ubuntu

Open a Terminal to WSL2 UF_2.

Since we may use this distro more often for building Raspberry Pi Images, we can also follow some best practices for Linux environment setup.

We do not want to work with root. Create a new user:

adduser alex

Since you are working in WSL in Windows, use a simple, easy to remember password.

Add the user to sudoers:

usermod -aG sudo alex

Change default user on logon for WSL2 UF_2:

Then use the given uid to update the default user. This must be done in cmd again.

lxrunoffline su -n UF_2 -v 1000

If you do not want to prepend your Windows Line Paths with /mnt/, it is possible to fix the default path with a wsl.conf.

Create the file (WSL Terminal):

sudo nano /etc/wsl.conf

Add

[automount]
root = /
options = "metadata"

Install build dependencies#

SnapOS and buildroot require some dependencies.

sudo apt-get install build-essential
sudo apt-get install libasound2-dev libpulse-dev \
    libvorbisidec-dev libvorbis-dev libopus-dev \
    libflac-dev libsoxr-dev alsa-utils \
    libavahi-client-dev avahi-daemon libexpat1-dev -y
sudo apt-get install bc cpio -y
sudo apt-get install libncurses5-dev libncursesw5-dev -y
sudo apt-get install wget unzip rsync -y

Prepare buildroot config#

Now it is time to prepare buildroot in WSL2.

mkdir ~/snapos
cd ~/snapos

Clone buildroot and SnapOS. Versions are important here and will affect compatibility.

The process below is described for buildroot version 2021.02.1 and SnapOS Repository up to commit 02420ed. You may use different versions, but expect a different road.

BUILDROOT_VERSION=2021.02.1
git clone \
    --branch $BUILDROOT_VERSION \
    --depth=1 git://git.buildroot.net/buildroot
git clone https://github.com/badaix/snapos
cd snapos && git checkout 02420ed
cd ../buildroot

Some notes on this process can be found in Issue #143 1 in the snapcast repository. But it was confusing. And I could not get the official SnapOS doc instructions 2, for some reason, to work for me. Either the wifi was missing, or the build had errors. Perhaps because I have a Raspberry Pi Zero W, not the Pi Zero.

Therefore, we are starting from raspberrypi0w_defconfig, provided through the official buildroot setup.

To list available confs:

make list-defconfigs

Note that some configs for rpi2 to 4 are also available in the SnapOS repository.3

make BR2_EXTERNAL=~/snapos/snapos/buildroot-external/ raspberrypi0w_defconfig

This will link the snapos configuration as external add-on to the raspberrypi0w_defconfig and create a template .config file that can be modified further.

Prepare the build#

make menuconfig

menuconfig

A menu will open with a GUI to modify the build .config. Select options with Y, navigate with and save changes with ENTER.

Enable the pre-selected Snapclient package under External options in make menuconfig

snapos

For the following config part, I found the best instructions in a blog post from Amrith Namboodiri.4

  1. Build options, select Enable compiler cache.
  2. Toolchain, select Enable WCHAR support.
  3. System configuration
    • chose a System hostname and Root password (this is later needed to login),
    • enable Install timezone info
  4. Target packages > Hardware Handling > Firmware
    • to enable wifi, select rpi-wifi-firmware
  5. Target packages, submenu Network applications. Select:
    • wpa_supplicant
    • wpa_supplicant - Enable 80211 support
    • dropbear
    • openssh
  6. Target packages, submenu Text editors and viewers.
    • Select nano
  7. Target packages, submenu Audio and video applications.
    • select alsa-utils for testing the HifiBerry DAC
    • in alsa-utils, make sure aplay and speaker-test are selected

Most of this beyond 2. is optional, depending on your Raspberry Pi Setup. For some background information on these customizations, I found this blog post5 good.

If you want, you can update the default raspberrypi0w_defconfig with your customizations. Make sure to create a backup of raspberrypi0w_defconfig.

make savedefconfig

Enable wifi#

There are some additional configurations necessary to make wifi connect automatically on boot.

In the buildroot folder, cd into board/raspberrypi/. The configurations here will be applied for all buildroot raspi builds.

nano interfaces 

Paste the following 4

auto lo
iface lo inet loopback

auto eth0
iface eth0 inet dhcp
    pre-up /etc/network/nfs_check
    wait-delay 15

auto wlan0
iface wlan0 inet dhcp
    pre-up wpa_supplicant -D nl80211 -i wlan0 -c /etc/wpa_supplicant.conf -B
    post-down killall -q wpa_supplicant
    wait-delay 15

iface default inet dhcp

Create wpa_supplicant.conf with:

ctrl_interface=/var/run/wpa_supplicant
ap_scan=1

network={
    ssid="<Your SSID>"
    psk="<Your Key>"
}

I found no need to select country or key_mgmt, which are often recommended.

Edit the post-build.sh (e.g. nano post-build.sh) and paste the following lines at the end of the file:

cp package/busybox/S10mdev ${TARGET_DIR}/etc/init.d/S10mdev
chmod 755 ${TARGET_DIR}/etc/init.d/S10mdev
cp package/busybox/mdev.conf ${TARGET_DIR}/etc/mdev.conf

cp board/raspberrypi/interfaces ${TARGET_DIR}/etc/network/interfaces
cp board/raspberrypi/wpa_supplicant.conf ${TARGET_DIR}/etc/wpa_supplicant.conf

Modify config.txt#

You can do this step before or after flashing the image. I applied it before, so that the configuration is automatically applied upon build.

A file called config.txt is present on the boot partition of the SD card that defines startup options. In my case, I needed to add a line to activate the HiFi Berry DAC overlay.

Before build, this file can be found at

buildroot/package/rpi-firmware/config.txt

Add these lines at the end of the file.

# fixes rpi (3B, 3B+, 3A+, 4B and Zero W) ttyAMA0 serial console
dtoverlay=miniuart-bt
# add hifiberry-dac overlay
dtoverlay=hifiberry-dac

The first line is automatically added by the script in

buildroot/board/raspberrypi/post-image.sh

.. but not, if package/rpi-firmware/config.txt already includes a line with dtoverlay.

The second line comes from the official Setup instructions for the HiFi Berry DAC.6

Build#

Now it is time to test the build:

make all

If you see a warning, where buildroot complains about paths in PATH containing space characters, temporarily truncate your path to remove any entries coming from the Windows side in WSL2. E.g.:

# show path
echo $PATH
# temporarily override in current session
export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

When make runs, it will take some time. If no errors occur, we can proceed to flashing the image.

The image will appear in the output folder.

~/snapos/buildroot/output/images/sdcard.img

Note

You can modify the config with make menuconfig and then rebuild the image with make all. These consecutive builds will run faster. However, if you change the toolchain (e.g. add nano to the .config, after make all), it is advised to do a clean rebuild with make clean && make all.

Flash image to sdcard#

As of April 2021, sdcards cannot be mounted directly in WSL2, only if you are following the Insider program.

Therefore, copy the image to the Windows side:

cp output/images/sdcard.img /c/temp/

And burn it with your favorite flashing tool. I like Etcher. Install in CMD with:

choco install etcher

Startup Raspberry Pi Zero W#

If everything goes well, you can watch the startup through the HDMI port and are greeted with the Berry logo.

startup

The startup of this image is an astonishing 20 Seconds.

If it goes perfect, you will see the Raspi to logon to your router through wifi.

fritz-logon

Select the IP and connect to it with:

ssh root@192.168.178.108

Hit enter twice until you are asked for the root password, enter what was set in menuconfig.

Test RPi#

If you are using the Davicom DM96xx USB 10/100 Ethernet Adapter, the Raspberry Pi Zero W should also become available through your Ethernet. You can verify this by looking at the startup log with dmesg.

> [   14.461959] dm9601 1-1:1.0 eth0: register 'dm9601' at usb-20980000.usb-1, Davicom DM96xx USB 10/100 Ethernet, 00:e0:4c:23:44:58
> [   14.483967] usbcore: registered new interface driver dm9601
> [   14.971505] NET: Registered protocol family 10
> [   14.983440] Segment Routing with IPv6
> [   15.119323] dm9601 1-1:1.0 eth0: link up, 100Mbps, full-duplex, lpa 0xFFFF
> [   15.487575] IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
> [   15.672407] brcmfmac: brcmf_cfg80211_set_power_mgmt: power save enabled
> [   17.101813] IPv6: ADDRCONF(NETDEV_CHANGE): wlan0: link becomes ready

For the HiFi Berry DAC Hat, check audio with aplay -l, according to the docs.6

> card 0: sndrpihifiberry [snd_rpi_hifiberry_dac], device 0: HifiBerry DAC HiFi pcm5102a-hifi-0 [HifiBerry DAC HiFi pcm5102a-hifi-0]
>   Subdevices: 1/1
>   Subdevice #0: subdevice #0

You can test sound output with the speaker-test utility.

speaker-test -t wav -c 2

> Time per period = 10.035245
> 0 - Front Left
> 1 - Front Right

Finally, for testing snapclient, we need to set up a snapserver host first. Afterwards, test with (e.g):

snapclient --host 192.168.100.10 --port 1704

On the snapserver, the following logs will appear on successful check-in:

snapserver_1  | 2021-06-19 05-06-34.724 [Notice] (StreamServer) StreamServer::NewConnection: 
                192.168.60.17
snapserver_1  | 2021-06-19 05-06-34.739 [Info] (Server) Hello from b8:21:eb:de:1a:d0, 
                host: SnapOS, v0.20.0, ClientName: Snapclient, OS: Buildroot 2021.02.1, 
                Arch: armv6l, Protocol version: 2

If you want to permanently and automatically connect the snapclient to the snapserver:

nano /etc/default/snapclient

and add:

START_SNAPCLIENT=true
SNAPCLIENT_OPTS="--host 192.168.100.10 --port 1704"

Afterwards, restart the snapclient daemon:

/etc/init.d/S99snapclient restart

To shut down the Raspberry Pi Zero gracefully, use:

poweroff

Conclusion#

hifi-house

From here on, there are many ways to proceed. Modify the image with menuconfig, to add other packages or tools. Or, to upgrade your image.

Hardware#

This is the list of Hardware I used:

€64.29

Better sound quality? HiFiBerry DAC2 HD


I found the audio quality ok for some speakers (e.g. JBL Boombox Xtreme). For my old stereo system, I purchased another Pi Zero WH, but combined it with the HiFiBerry DAC2 HD7. This comes at a hefty €89.00, but the sound quality is stunning.

Also, the HiFiBerry DAC2 HD will not fit in the HB-ZCA-DAC Housing for HiFiBerry DAC. I used the HighPi Case for HiFiBerry DAC+ RCA8. This worked with a pair of 90° USB angle adapters9, to prevent bending of cables.

Finally, in order to load the correct drivers for the DAC2 HD, edit config.txt and use dtoverlay=hifiberry-dacplushd. No need to rebuild snapos.img.