Zephyr

Content

  1. Intro to Zephyr
  2. Context for this page
  3. Zephyr application with BLE in a USB dongle
    1. Linux Update
    2. Tools for Zephyr
    3. Using west in a virtual environment
    4. Environment
    5. Board support and SDK
    6. Build & Flash
    7. Test
  4. USB-based BLE Controller
  5. Next Steps

Intro to Zephyr

Zephyr is the new kid in town when it comes to embedded operating systems. It can be compared to FreeRTOS, which I use in my latest book – Microcontrollers with C. Both are small-footprint, real-time OS’es. However, where FreeRTOS is basically an RTOS only, Zephyr is an RTOS with communication stacks, filesystems and security for automotive and medical applications. On top of all this, Zephyr has out-of-the-box support for tons of boards and microcontrollers – across many vendors. It comes with a clever common build system for many samples – that can be reused for custom designs.

If you compare Zephyr to Linux, the major technical difference is that Linux is not an RTOS, but a high-throughput operating system – supporting virtual memory and SMP. See much more in Microcontrollers with C. You can see Zephyr as Linux’es, reliable kid-brother.

Zephyr is developed under an Apache 2.0 license, which is much more flexible than GNU’s GPL license, and it is community-driven.

nRF52840 Dongle
nRF52840 USB-Dongle

Context for this page

While Zephyr supports Windows, Linux and Mac as development hosts, Linux comes most “natural”, and I am using a “real” Linux setup for this page (I do apologize for the long prompt – it is standard and I forgot to change it).

There are many samples with Zephyr – the most basic is “Blinky”, where you blink with an LED on the target board. I wanted to try something else, and went for the Bluetooth Low Energy Beacon. This is a simple application that emits a constant repeating message – easy to recognize in a test – which we will see later. In the page on Bluetooth Audio, I discuss BLE Audio, which is a newer “add-on” to BLE. The beacon in the sample uses the more basic BLE – and only a small subset of this.

If you are a bit familiar with BLE, and especially BLE on a “dongle” like I use here, you might wonder whether the BLE dongle is “just” the BLE controller – with the PC acting as the BLE host, and a Host-Control-Interface between the two – or whether the dongle plays both roles – see figure below.

BLE, Dongle and PC
Two of the ways to have BLE in a dongle – standalone application and BLE controller

Zephyr offers support for both concepts. With the Beacon sample, the target BLE dongle contains both controller and host – all implemented in Zephyr (left side of the figure). Thus the PC basically only delivers power and is used when flashing the device. In the above figure you might substitute “PC” with e.g., “Raspberry Pi”.

In the right side of the figure above you might also substitute “PC” with a small custom CPU/MCU. In that scenario it would not work as a development system. This is a very common scenario. Here you might also have Zephyr in the application/BLE Host device.

You might worry that after flashing the dongle with an application, you have overwritten the part that is responsible for downloading new firmware! However, as with most modern devices, the flash is split in a bootloader and an application area. When doing a normal DFU – Device Firmware Update – you only overwrite the application area. You can read more about this in my book Microcontrollers with C.

At the bottom of this page I build the controller-only solution. That allows for some interesting tests of various tools for command-line use of the BLE-dongle.

Zephyr application with BLE in a USB dongle

The following to a large degree follows https://docs.zephyrproject.org/latest/develop/getting_started/index.html – with a few additions and hints.

Linux update

As usual on Linux, get the updater’s info updated first:
kelk@kelk-ThinkPad-P15-Gen-1:~$ sudo apt update
Get:1 http://security.ubuntu.com/ubuntu jammy-security InRelease [129 kB]
Get:2 http://dk.archive.ubuntu.com/ubuntu jammy InRelease [270 kB]
Hit:3 http://dk.archive.ubuntu.com/ubuntu jammy-updates InRelease
Hit:4 http://dk.archive.ubuntu.com/ubuntu jammy-backports InRelease
Fetched 399 kB in 0s (990 kB/s)
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
178 packages can be upgraded. Run 'apt list --upgradable' to see them.
And then the actual update of already installed binaries:
kelk@kelk-ThinkPad-P15-Gen-1:~$ sudo apt upgrade
... tons of messages

Tools for Zephyr

Now Install the necessary tools for Zephyr:
kelk@kelk-ThinkPad-P15-Gen-1:~$ sudo apt install --no-install-recommends 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 g++-multilib libsdl2-dev libmagic1
..... Usual output
Zephyr uses the Python virtual environment to assure that all the Python-based management uses the right versions. This is a recommended approach in general. Note that “west” is also a Python-based tool – made for Zephyr.
kelk@kelk-ThinkPad-P15-Gen-1:~$ sudo apt install python3-venv
This is my home directory after the above:
kelk@kelk-ThinkPad-P15-Gen-1:~$ ll
total 76
drwxr-x--- 16 kelk kelk 4096 Mar 14 15:07 ./
drwxr-xr-x 3 root root 4096 Mar 14 11:43 ../
-rw-r--r-- 1 kelk kelk 220 Mar 14 11:43 .bash_logout
-rw-r--r-- 1 kelk kelk 3771 Mar 14 11:43 .bashrc
drwx------ 12 kelk kelk 4096 Mar 14 13:20 .cache/
drwxrwxr-x 3 kelk kelk 4096 Mar 14 13:53 .cmake/
drwx------ 12 kelk kelk 4096 Mar 14 14:58 .config/
drwxr-xr-x 2 kelk kelk 4096 Mar 14 11:49 Desktop/
drwxr-xr-x 2 kelk kelk 4096 Mar 14 11:49 Documents/
drwxr-xr-x 2 kelk kelk 4096 Mar 14 13:08 Downloads/
drwxr-xr-x 2 kelk kelk 4096 Mar 14 11:57 .fontconfig/
drwx------ 5 kelk kelk 4096 Mar 14 13:20 .local/
drwxr-xr-x 2 kelk kelk 4096 Mar 14 11:49 Music/
drwxr-xr-x 2 kelk kelk 4096 Mar 14 11:49 Pictures/
-rw-r--r-- 1 kelk kelk 807 Mar 14 11:43 .profile
drwxr-xr-x 2 kelk kelk 4096 Mar 14 11:49 Public/
drwx------ 5 kelk kelk 4096 Mar 14 13:03 snap/
-rw-r--r-- 1 kelk kelk 0 Mar 14 13:18 .sudo_as_admin_successful
drwxr-xr-x 2 kelk kelk 4096 Mar 14 11:49 Templates/
drwxr-xr-x 2 kelk kelk 4096 Mar 14 11:49 Videos/
Fire up the Python virtual environment – please note ” (.venv)” in the prompt  after the activate:
kelk@kelk-ThinkPad-P15-Gen-1:~$ python3 -m venv ~/zephyrproject/.venv
kelk@kelk-ThinkPad-P15-Gen-1:~$ source zephyrproject/.venv/bin/activate

Using west in a virtual environment

Install west – the Zephyr Python-based build management tool:
(.venv) kelk@kelk-ThinkPad-P15-Gen-1:~$ pip install west
Collecting west
Using cached west-1.3.0-py3-none-any.whl (102 kB)
Collecting packaging
Using cached packaging-24.2-py3-none-any.whl (65 kB)
Collecting colorama
Using cached colorama-0.4.6-py2.py3-none-any.whl (25 kB)
Collecting pykwalify
Using cached pykwalify-1.8.0-py2.py3-none-any.whl (24 kB)
Collecting PyYAML>=5.1
Using cached PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (751 kB)
Requirement already satisfied: setuptools in ./zephyrproject/.venv/lib/python3.10/site-packages (from west) (59.6.0)
Collecting ruamel.yaml>=0.16.0
Using cached ruamel.yaml-0.18.10-py3-none-any.whl (117 kB)
Collecting docopt>=0.6.2
Using cached docopt-0.6.2-py2.py3-none-any.whl
Collecting python-dateutil>=2.8.0
Using cached python_dateutil-2.9.0.post0-py2.py3-none-any.whl (229 kB)
Collecting six>=1.5
Using cached six-1.17.0-py2.py3-none-any.whl (11 kB)
Collecting ruamel.yaml.clib>=0.2.7
Using cached ruamel.yaml.clib-0.2.12-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (722 kB)
Installing collected packages: docopt, six, ruamel.yaml.clib, PyYAML, packaging, colorama, ruamel.yaml, python-dateutil, pykwalify, west
Successfully installed PyYAML-6.0.2 colorama-0.4.6 docopt-0.6.2 packaging-24.2 pykwalify-1.8.0 python-dateutil-2.9.0.post0 ruamel.yaml-0.18.10 ruamel.yaml.clib-0.2.12 six-1.17.0 west-1.3.0

Init the Zephyr project:

(.venv) kelk@kelk-ThinkPad-P15-Gen-1:~$ west init zephyrproject
=== Initializing in /home/kelk/zephyrproject
--- Cloning manifest repository from https://github.com/zephyrproject-rtos/zephyr
Cloning into '/home/kelk/zephyrproject/.west/manifest-tmp'...
remote: Enumerating objects: 1224656, done.
remote: Counting objects: 100% (327/327), done.
remote: Compressing objects: 100% (175/175), done.
remote: Total 1224656 (delta 182), reused 164 (delta 151), pack-reused 1224329 (from 3)
Receiving objects: 100% (1224656/1224656), 721.18 MiB | 9.19 MiB/s, done.
Resolving deltas: 100% (907275/907275), done.
Updating files: 100% (42891/42891), done.
--- setting manifest.path to zephyr
=== Initialized. Now run "west update" inside /home/kelk/zephyrproject.

Go to the new directory:

(.venv) kelk@kelk-ThinkPad-P15-Gen-1:~$ cd zephyrproject/
(.venv) kelk@kelk-ThinkPad-P15-Gen-1:~/zephyrproject$ ll
total 20
drwxrwxr-x 5 kelk kelk 4096 Mar 14 15:11 ./
drwxr-x--- 17 kelk kelk 4096 Mar 14 15:08 ../
drwxrwxr-x 5 kelk kelk 4096 Mar 14 15:08 .venv/
drwxrwxr-x 2 kelk kelk 4096 Mar 14 15:11 .west/
drwxrwxr-x 23 kelk kelk 4096 Mar 14 15:11 zephyr/

Let west retrieve git repos:

(.venv) kelk@kelk-ThinkPad-P15-Gen-1:~/zephyrproject$ west update
=== updating acpica (modules/lib/acpica):
--- acpica: initializing
Initialized empty Git repository in /home/kelk/zephyrproject/modules/lib/acpica/.git/
--- acpica: fetching, need revision 8d24867bc9c9d81c81eeac59391cda59333affd4
remote: Enumerating objects: 144870, done.
remote: Counting objects: 100% (1037/1037), done.
remote: Compressing objects: 100% (174/174), done.
remote: Total 144870 (delta 912), reused 863 (delta 863), pack-reused 143833 (from 2)
Receiving objects: 100% (144870/144870), 158.58 MiB | 17.24 MiB/s, done.
Resolving deltas: 100% (103003/103003), done.
From https://github.com/zephyrproject-rtos/acpica
* [new branch] master -> refs/west/master
* [new branch] zephyr -> refs/west/zephyr
* [new branch] zephyr-v3.5 -> refs/west/zephyr-v3.5
HEAD is now at 8d24867bc Merge pull request #5 from dcpleung/kernel/mm_z_phys_map_unmap_rename
HEAD is now at 8d24867bc Merge pull request #5 from dcpleung/kernel/mm_z_phys_map_unmap_rename
=== updating cmsis (modules/hal/cmsis):
--- cmsis: initializing
....... keeps on forever!
Export a Zephyr CMake package:
(.venv) kelk@kelk-ThinkPad-P15-Gen-1:~/zephyrproject$ west zephyr-export
Zephyr (/home/kelk/zephyrproject/zephyr/share/zephyr-package/cmake)
has been added to the user package registry in:
~/.cmake/packages/Zephyr
ZephyrUnittest (/home/kelk/zephyrproject/zephyr/share/zephyrunittest-package/cmake)
has been added to the user package registry in:
~/.cmake/packages/ZephyrUnittest

Environment

Update the environment – there were bad paths with “/zephyr/zephyr” before.
This meant that the following step went bad.
OBS – this step is not in the Getting Started Guide.
(.venv) kelk@kelk-ThinkPad-P15-Gen-1:~/zephyrproject/zephyr$ source zephyr-env.sh
# This is my updated environment
(.venv) kelk@kelk-ThinkPad-P15-Gen-1:~/zephyrproject/zephyr$ env
SHELL=/bin/bash
SESSION_MANAGER=local/kelk-ThinkPad-P15-Gen-1:@/tmp/.ICE-unix/1599,unix/kelk-ThinkPad-P15-Gen-1:/tmp/.ICE-unix/1599
ZEPHYR_BASE=/home/kelk/zephyrproject/zephyr
QT_ACCESSIBILITY=1
COLORTERM=truecolor
XDG_CONFIG_DIRS=/etc/xdg/xdg-ubuntu:/etc/xdg
SSH_AGENT_LAUNCHER=gnome-keyring
XDG_MENU_PREFIX=gnome-
GNOME_DESKTOP_SESSION_ID=this-is-deprecated
LANGUAGE=en_US:en
GNOME_SHELL_SESSION_MODE=ubuntu
SSH_AUTH_SOCK=/run/user/1000/keyring/ssh
XMODIFIERS=@im=ibus
DESKTOP_SESSION=ubuntu
GTK_MODULES=gail:atk-bridge
PWD=/home/kelk/zephyrproject/zephyr
LOGNAME=kelk
XDG_SESSION_DESKTOP=ubuntu
XDG_SESSION_TYPE=wayland
SYSTEMD_EXEC_PID=1633
XAUTHORITY=/run/user/1000/.mutter-Xwaylandauth.QXHH32
HOME=/home/kelk
USERNAME=kelk
IM_CONFIG_PHASE=1
LANG=en_US.UTF-8
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.webp=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:
XDG_CURRENT_DESKTOP=ubuntu:GNOME
VIRTUAL_ENV=/home/kelk/zephyrproject/.venv
VTE_VERSION=6800
WAYLAND_DISPLAY=wayland-0
GNOME_TERMINAL_SCREEN=/org/gnome/Terminal/screen/e6ef9f31_1a45_482c_890d_3ba46c171203
GNOME_SETUP_DISPLAY=:1
LESSCLOSE=/usr/bin/lesspipe %s %s
XDG_SESSION_CLASS=user
TERM=xterm-256color
LESSOPEN=| /usr/bin/lesspipe %s
USER=kelk
GNOME_TERMINAL_SERVICE=:1.159
DISPLAY=:0
SHLVL=1
QT_IM_MODULE=ibus
VIRTUAL_ENV_PROMPT=(.venv)
XDG_RUNTIME_DIR=/run/user/1000
PS1=(.venv) \[\e]0;\u@\h: \w\a\]${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$
XDG_DATA_DIRS=/usr/share/ubuntu:/usr/local/share/:/usr/share/:/var/lib/snapd/desktop
PATH=/home/kelk/zephyrproject/zephyr/scripts:/home/kelk/zephyrproject/.venv/bin:/home/kelk/zephyrproject/zephyr/zephyr/scripts:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/snap/bin
GDMSESSION=ubuntu
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
OLDPWD=/home/kelk/zephyrproject
_=/usr/bin/env

Board support and SDK

Get all the board packages:
(.venv) kelk@kelk-ThinkPad-P15-Gen-1:~/zephyrproject$ west packages pip --install
Ignoring windows-curses: markers 'sys_platform == "win32"' don't match your environment
Ignoring python-magic-bin: markers 'sys_platform == "win32"' don't match your environment
Collecting pyelftools>=0.29
Downloading pyelftools-0.32-py3-none-any.whl (188 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 188.5/188.5 KB 3.7 MB/s eta 0:00:00
Requirement already satisfied: PyYAML>=6.0 in ./.venv/lib/python3.10/site-packages (from -r /home/kelk/zephyrproject/zephyr/scripts/requirements-base.txt (line 11)) (6.0.2)
Requirement already satisfied: pykwalify in ./.venv/lib/python3.10/site-packages (from -r /home/kelk/zephyrproject/zephyr/scripts/requirements-base.txt (line 14)) (1.8.0)
Collecting canopen
Downloading canopen-2.3.0-py3-none-any.whl (64 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 64.2/64.2 KB 6.7 MB/s eta 0:00:00
Requirement already satisfied: packaging in ./.venv/lib/python3.10/site-packages (from -r /home/kelk/zephyrproject/zephyr/scripts/requirements-base.txt (line 18)) (24.2)
Collecting progress
Downloading progress-1.6.tar.gz (7.8 kB)
Preparing metadata (setup.py) ... done
Collecting patool
Using cached patool-4.0.0-py2.py3-none-any.whl (86 kB)
Collecting psutil
Downloading psutil-7.0.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl (277 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 278.0/278.0 KB 7.0 MB/s eta 0:00:00
Collecting pylink-square
Downloading pylink_square-1.5.0-py2.py3-none-any.whl (85 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 85.3/85.3 KB 6.6 MB/s eta 0:00:00
Collecting pyserial
Downloading pyserial-3.5-py2.py3-none-any.whl (90 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 90.6/90.6 KB 7.2 MB/s eta 0:00:00
Collecting requests
Downloading requests-2.32.3-py3-none-any.whl (64 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 64.9/64.9 KB 7.8 MB/s eta 0:00:00
Collecting semver
Downloading semver-3.0.4-py3-none-any.whl (17 kB)
Collecting tqdm
Downloading tqdm-4.67.1-py3-none-any.whl (78 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 78.5/78.5 KB 8.6 MB/s eta 0:00:00
Collecting anytree
Downloading anytree-2.12.1-py3-none-any.whl (44 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 44.9/44.9 KB 7.7 MB/s eta 0:00:00
Collecting intelhex
Downloading intelhex-2.3.0-py2.py3-none-any.whl (50 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 50.9/50.9 KB 8.9 MB/s eta 0:00:00
Requirement already satisfied: west>=0.14.0 in ./.venv/lib/python3.10/site-packages (from -r /home/kelk/zephyrproject/zephyr/scripts/requirements-base.txt (line 36)) (1.3.0)
Requirement already satisfied: colorama in ./.venv/lib/python3.10/site-packages (from -r /home/kelk/zephyrproject/zephyr/scripts/requirements-build-test.txt (line 7)) (0.4.6)
.... THIS GOES ON FOR A LONG TIME ..

Now for the Zephyr SDK:

(.venv) kelk@kelk-ThinkPad-P15-Gen-1:~/zephyrproject$ west sdk install
Found '/home/kelk/zephyrproject/zephyr/SDK_VERSION', installing version 0.17.0.
Fetching Zephyr SDK list...
Fetching sha256...
Downloading https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.17.0/zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz...
zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz: 100%|####################################################################################################################| 44.5M 10.8M/s [00:04]
Downloaded: /home/kelk/tmp2grp3_2g/zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz
Extract: /home/kelk/tmp2grp3_2g/zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz
INFO patool: Extracting /home/kelk/tmp2grp3_2g/zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz ...
INFO patool: running /usr/bin/tar --extract --xz --force-local --file /home/kelk/tmp2grp3_2g/zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz --directory /home/kelk/tmp2grp3_2g
INFO patool: ... /home/kelk/tmp2grp3_2g/zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz extracted to `/home/kelk/tmp2grp3_2g'.
Move: /home/kelk/tmp2grp3_2g/zephyr-sdk-0.17.0 to /home/kelk/zephyr-sdk-0.17.0.
Zephyr SDK 0.17.0 Setup
Registering Zephyr SDK CMake package ...
Zephyr-sdk (/home/kelk/zephyr-sdk-0.17.0/cmake)
has been added to the user package registry in:
~/.cmake/packages/Zephyr-sdk
All done.
Zephyr SDK 0.17.0 Setup
Installing 'aarch64-zephyr-elf' toolchain ...
toolchain_linux-x86_64_aarch64-zephyr-elf.tar.xz 100%[===============================================================================================================>] 55.99M 28.1MB/s in 2.0s
Installing 'arc64-zephyr-elf' toolchain ...
toolchain_linux-x86_64_arc64-zephyr-elf.tar.xz 100%[===============================================================================================================>] 54.25M 21.1MB/s in 2.6s
Installing 'arc-zephyr-elf' toolchain ...
toolchain_linux-x86_64_arc-zephyr-elf.tar.xz 100%[===============================================================================================================>] 85.03M 
... THIS GOES ON FOR A LONG TIME
Installing host tools ...
All done.

Build & Flash

Build the Beacon sample – for the specific board. The boardname was found via https://docs.zephyrproject.org/latest/boards/index.html#boards
(.venv) kelk@kelk-ThinkPad-P15-Gen-1:~/zephyrproject/zephyr$ west build -p always -b nrf52840dongle/nrf52840 samples/bluetooth/beacon
-- west build: making build dir /home/kelk/zephyrproject/zephyr/build pristine
-- west build: generating a build system
Loading Zephyr default modules (Zephyr base).
-- Application: /home/kelk/zephyrproject/zephyr/samples/bluetooth/beacon
-- CMake version: 3.22.1
-- Found Python3: /home/kelk/zephyrproject/.venv/bin/python3 (found suitable version "3.10.12", minimum required is "3.10") found components: Interpreter
-- Cache files will be written to: /home/kelk/.cache/zephyr
-- Zephyr version: 4.1.99 (/home/kelk/zephyrproject/zephyr)
-- Found west (found suitable version "1.3.0", minimum required is "0.14.0")
-- Board: nrf52840dongle, qualifiers: nrf52840
-- ZEPHYR_TOOLCHAIN_VARIANT not set, trying to locate Zephyr SDK
-- Found host-tools: zephyr 0.17.0 (/home/kelk/zephyr-sdk-0.17.0)
-- Found toolchain: zephyr 0.17.0 (/home/kelk/zephyr-sdk-0.17.0)
-- Found Dtc: /home/kelk/zephyr-sdk-0.17.0/sysroots/x86_64-pokysdk-linux/usr/bin/dtc (found suitable version "1.6.0", minimum required is "1.4.6")
-- Found BOARD.dts: /home/kelk/zephyrproject/zephyr/boards/nordic/nrf52840dongle/nrf52840dongle_nrf52840.dts
-- Generated zephyr.dts: /home/kelk/zephyrproject/zephyr/build/zephyr/zephyr.dts
-- Generated pickled edt: /home/kelk/zephyrproject/zephyr/build/zephyr/edt.pickle
-- Generated devicetree_generated.h: /home/kelk/zephyrproject/zephyr/build/zephyr/include/generated/zephyr/devicetree_generated.h
-- Including generated dts.cmake file: /home/kelk/zephyrproject/zephyr/build/zephyr/dts.cmake
Parsing /home/kelk/zephyrproject/zephyr/Kconfig
Loaded configuration '/home/kelk/zephyrproject/zephyr/boards/nordic/nrf52840dongle/nrf52840dongle_nrf52840_defconfig'
Merged configuration '/home/kelk/zephyrproject/zephyr/samples/bluetooth/beacon/prj.conf'
Configuration saved to '/home/kelk/zephyrproject/zephyr/build/zephyr/.config'
Kconfig header saved to '/home/kelk/zephyrproject/zephyr/build/zephyr/include/generated/zephyr/autoconf.h'
-- Found GnuLd: /home/kelk/zephyr-sdk-0.17.0/arm-zephyr-eabi/arm-zephyr-eabi/bin/ld.bfd (found version "2.38")
-- The C compiler identification is GNU 12.2.0
-- The CXX compiler identification is GNU 12.2.0
-- The ASM compiler identification is GNU
-- Found assembler: /home/kelk/zephyr-sdk-0.17.0/arm-zephyr-eabi/bin/arm-zephyr-eabi-gcc
CMake Warning at /home/kelk/zephyrproject/zephyr/subsys/usb/device/CMakeLists.txt:22 (message):
CONFIG_USB_DEVICE_VID has default value 0x2FE3.
This value is only for testing and MUST be configured for USB products.
CMake Warning at /home/kelk/zephyrproject/zephyr/subsys/usb/device/CMakeLists.txt:28 (message):
CONFIG_USB_DEVICE_PID has default value 0x100.
This value is only for testing and MUST be configured for USB products.
-- Using ccache: /usr/bin/ccache
-- Configuring done
-- Generating done
-- Build files have been written to: /home/kelk/zephyrproject/zephyr/build
-- west build: building application
[1/213] Preparing syscall dependency handling
[2/213] Generating include/generated/zephyr/version.h
-- Zephyr version: 4.1.99 (/home/kelk/zephyrproject/zephyr), build: v4.1.0-633-gbec4a8474934
[213/213] Linking C executable zephyr/zephyr.elf
Memory region Used Size Region Size %age Used
FLASH: 85436 B 1020 KB 8.18%
RAM: 25324 B 256 KB 9.66%
IDT_LIST: 0 GB 32 KB 0.00%
Generating files from /home/kelk/zephyrproject/zephyr/build/zephyr/zephyr.elf for board: nrf52840dongle

Create a zip-file for the downloader (I did not try the simpler “west flash”):
(note nrfutil must also be installed)
(.venv) kelk@kelk-ThinkPad-P15-Gen-1:~$ .nrfutil/bin/nrfutil-nrf5sdk-tools pkg generate --hw-version 52 --sd-req=0x00 --application zephyrproject/zephyr/build/zephyr/zephyr.hex --application-version 1 beacon.zip
|===============================================================|
|## ## ### ######## ## ## #### ## ## ###### |
|## ## ## ## ## ## ## ### ## ## ### ## ## ## |
|## ## ## ## ## ## ## #### ## ## #### ## ## |
|## ## ## ## ## ######## ## ## ## ## ## ## ## ## ####|
|## ## ## ######### ## ## ## #### ## ## #### ## ## |
|## ## ## ## ## ## ## ## ### ## ## ### ## ## |
| ### ### ## ## ## ## ## ## #### ## ## ###### |
|===============================================================|
|You are not providing a signature key, which means the DFU |
|files will not be signed, and are vulnerable to tampering. |
|This is only compatible with a signature-less bootloader and is|
|not suitable for production environments. |
|===============================================================|
Zip created at beacon.zip
Press the small metallic button – sideways towards the PC (not the bigger white one). This starts the bootloader in the dongle.
Note the new port (if you search for it before pressing the button – it’s not there):
(.venv) kelk@kelk-ThinkPad-P15-Gen-1:~$ ll /dev/ttyAC*
crw-rw---- 1 root dialout 166, 0 Mar 14 22:11 /dev/ttyACM0
The /dev/ttyACM0 is often used. I recently updated a Laird-dongle – same concept. ACM stands for “Abstract Control Module”, which – according to Tom’s computer pages – originally meant support for  the old Hayes “AT” commands. If you know what that is, chances are you are at my age 🙂
Flash the zip to the nRF52 dongle:
(.venv) kelk@kelk-ThinkPad-P15-Gen-1:~$ sudo .nrfutil/bin/nrfutil-nrf5sdk-tools dfu usb-serial -pkg beacon.zip -p /dev/ttyACM0
[sudo] password for kelk:
[####################################] 100%

Test

Now the beacon is found in e.g., the phone-app “nRF Connect “. It matches the struct in main.c in the sample (Eddystone protocol and wwww.zephyrproject.org). Should also be the one with the highest dBm’s in  RSSI (smallest absolute number – but negative) if the phone is near the dongle. We can see that it transmits with an interval of ~105 ms, and it tells us that it transmits with 0 dBm (1 mW).
In Denmark a Wi-Fi signal is allowed to be 20 dBm (100 mW), so it’s clear that this device uses much less power than a Wi-Fi transmitter. More on these things on WiFi – the letters and Wireless Technologies
Test by e.g., unplugging the dongle. The dBm will stop changing, but a rescan is needed to make it go away.
iPhone nRF Connect
Screenshot

 

Building a BLE-Controller for the 52840 Dongle

To see the few steps needed now for a new build – and to have a BLE controller to play around with – I decided to build the HCI USB sample. This is  a BLE Controller with a HCI – Host Controller Interface – over the USB. This time I am not showing the output – looks much like above.
Restart the virtual environment and go to the zephyr folder:
kelk@kelk-ThinkPad-P15-Gen-1:~$ source zephyrproject/.venv/bin/activate
(.venv) kelk@kelk-ThinkPad-P15-Gen-1:~$ cd zephyrproject/zephyr/
Build the hci_usb sample. Note the use of the “-p” parameter (again). This makes the build “pristine” – meaning that the build folder is deleted and everything is built from scratch:
(.venv) kelk@kelk-ThinkPad-P15-Gen-1:~/zephyrproject/zephyr$ west build -p always -b nrf52840dongle/nrf52840 samples/bluetooth/hci_usb
Back to the home folder, generate the zip and flash it (remembering to press the button for the bootloader):
(.venv) kelk@kelk-ThinkPad-P15-Gen-1:~/zephyrproject/zephyr$ cd 
(.venv) kelk@kelk-ThinkPad-P15-Gen-1:~$ .nrfutil/bin/nrfutil-nrf5sdk-tools pkg generate --hw-version 52 --sd-req=0x00 --application zephyrproject/zephyr/build/zephyr/zephyr.hex --application-version 1 hci_usb.zip
(.venv) kelk@kelk-ThinkPad-P15-Gen-1:~$ sudo .nrfutil/bin/nrfutil-nrf5sdk-tools dfu usb-serial -pkg hci_usb.zip -p /dev/ttyACM0
To see the new device:
(.venv) kelk@kelk-ThinkPad-P15-Gen-1:~$ hcitool dev
Devices:
hci1 00:00:00:00:00:00
hci0 F8:5E:A0:7F:75:B9
Note that the new controller has an all zero address. That’s because the hcitool shows public addresses. The new controller protects it’s privacy and only has a random resolvable address.
# The bluetoothctl cmd finds both:
(.venv) kelk@kelk-ThinkPad-P15-Gen-1:~$ bluetoothctl
Agent registered
[CHG] Controller F8:5E:A0:7F:75:B9 Pairable: yes
[CHG] Controller C5:1D:32:85:22:A1 Pairable: yes

Next steps

If you want to get serious and develop your own product based on Zephyr, it makes sense to understand west, and the organization of the code a bit deeper. I am sure that a few initial experiments with folder-structures and builds will be a good investment in the long run.

The process I ran through on this page retrieves all board-support packages. However, you can modify west.yml to contain only the packages you need. This will also allow you to have a folder-structure where you pull most of the source from the zephyr repos – and have other folders that refer to your own git repo.  Then run:

west update

Next, you may want to use menuconfig to disable some features (and maybe later enable some of these again):

west build -t menuconfig

There are more tricks, like configuring prj.conf to remove unused drivers etc. See e.g., https://docs.zephyrproject.org/latest/develop/application/index.html