Building SnapOS Image for Raspberry Pi Zero W with buildroot in WSL2
Published: 2021-04-10, Revised: 2024-02-13
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).
- First try was in WSL1. Conclusion: Building Linux images with the MS modified Linux Kernel in WSL1 is not a good idea.
- Docker to the rescue: This was not a good idea, too. Of course, Docker when run from WSL1 shares the exact same Linux Kernel.
- WSL2: In retrospect, it was not surprising that buildroot worked here, since WSL2 is native Linux.
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.
- Install LxRunOffline with Choco
To install LxRunOffline, I prefer Chocolatey package manager.
In a cmd shell with administrator privileges, run:
choco install lxrunoffline
- 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.
- 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
- 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
- Install WSLtty (Optional)
This is optional, but I found accessing and working in WSL easier with wsltty.
choco install wsltty
- 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:
- get the id for user alex
su alex id > uid=1000(alex) gid=1000(alex) groups=1000(alex),27(sudo)
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
Link SnapOS external config#
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
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
For the following config part, I found the best instructions in a blog post from Amrith Namboodiri.4
Build options
, selectEnable compiler cache
.Toolchain
, selectEnable WCHAR support
.System configuration
- chose a
System hostname
andRoot password
(this is later needed to login), - enable
Install timezone info
- chose a
Target packages
>Hardware Handling
>Firmware
- to enable wifi, select
rpi-wifi-firmware
- to enable wifi, select
Target packages
, submenuNetwork applications
. Select:- wpa_supplicant
- wpa_supplicant - Enable 80211 support
- dropbear
- openssh
Target packages
, submenuText editors and viewers
.- Select
nano
- Select
Target packages
, submenuAudio and video applications
.- select
alsa-utils
for testing the HifiBerry DAC - in
alsa-utils
, make sureaplay
andspeaker-test
are selected
- select
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.
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.
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#
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:
- 1 RPIZ-WH Raspberry Pi Zero WH - 15.19
- 1 SanDisk Ultra microSDHC A1 98MB/s Class 10 SDCard + Adapter 16GB - 4.90
- 1 125041 Mini HDMI Adapter - 2.90
- 1 HB-ZCA-DAC Housing for HiFiBerry DAC + Zero and Raspberry Pi - 11.90
- 1 HB-DACP-ZERO HiFiBerry DAC + Zero with RCA Output 14,90
- 1 8012053 Micro USB Power Supply for Raspberry Pi 5V / 2,5A - 4.90
- 1 40102-1MHQ Home Cinema Stereo Audiocable 2x Cinch – 1,0m - 6.30
- 1 125197 Micro USB 2.0 Fast Ethernet Network Adapter - 3.30
€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
.
-
The SnapOS Github Repo ↩
-
Amrith Namboodiri How to build Raspberry pi zero w BUILDROOT image ↩↩
-
General introduction to customizations of buildroot for Raspberry Pi ↩
-
HiFiBerry DAC2 HD hifiberry.com ↩
-
HighPi Case for HiFiBerry DAC+ RCA berrybase.de ↩