Lingua Franca’s C-runtime supports the Zephyr RTOS. This enables developing and
of resource-constrained microcontrollers. In this guide we will see how LF
programs can be built, programmed and debugged both in emulation and on real
hardware. When developing LF programs for Zephyr we use a
west, which is the preferred build tool for Zephyr projects,
requires structuring the code base and development flow as expected by
west. To interact
with the Lingua Franca Compiler we provide custom
west-extensions which invoke
lfc before building the Zephyr application. This in contrast to our
Arduino-support, which is
- Linux or macOS development system
lfcv0.4.0 or greater
- nrf52 Development Kit (optional)
This section consists in part of borrowed sections from the Zephyr Getting
Please refer to the official Zephyr documentation for more background and
specifics regarding the use of
Pull the lf-west-template
git clone https://github.com/lf-lang/lf-west-template lf-west && cd lf-west
- Setup and activate a virtual environment
python3 -m venv .venv source .venv/bin/activate
pip3 install west
west is installed within a virtual environment. This environment has to
be activated every time you want to use west with LF
Installing Zephyr SDK
- Download and install Zephyr SDK to
cd ~ wget https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.15.2/zephyr-sdk-0.15.2_linux-x86_64.tar.gz wget -O - https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.15.2/sha256.sum | shasum --check --ignore-missing tar xvf zephyr-sdk-0.15.2_linux-x86_64.tar.gz --directory /opt/ cd /opt/zephyr-sdk-0.15.2 ./setup.sh
- Install udev rules for flashing and debugging boards
sudo cp /opt/zephyr-sdk-0.15.2/sysroots/x86_64-pokysdk-linux/usr/share/openocd/contrib/60-openocd.rules /etc/udev/rules.d sudo udevadm control --reload
Download the Zephyr RTOS
- Remove old Zephyr installations from your system.
should be empty.
should not contain
ZephyrUnittest. If they do, delete them. They will be replaced later when we do
- Download the Zephyr RTOS to the template repository. This step will take some time
- Export CMake packages for Zephyr
- Install Python dependencies
pip install -r deps/zephyr/scripts/requirements.txt
Now you should have the following installed:
west; Verify with
- Zephyr SDK located at
- Zephyr RTOS pulled down to
You should now be able to build and emulate a simple Hello World! LF program:
cd application west lf-build src/HelloWorld.lf -w "-t run"
HelloWorld.lf sets the target property
platform: "Zephyr" and
threading: false. This tells
lfc to create a Zephyr-compatible CMake project. In the example above the custom
lf-build is used to first invoke
lfc and then
west build on the resulting generated sources.
In this example we will program a simple Blinky program onto an nrf52dk. This
requires an actual nrf52 board and also the
nrfjprog utility is installed. See
the following installation guide
cd application west lf-build src/NrfBlinky.lf -w "-b nrf52dk_nrf52832 -p always" west flash
In this example we use the
-w flag to pass additional flags to
west build. In particular we inform
west that we are targeting a the nrf52 with
-b nrf52dk_nrf52832. We also tell west to clean the build directory first with
Kernel configuration options
The Lingua Franca Zephyr platform depends on some specific Zephyr Kernel configurations.
For instance, the Counter drivers must be linked with the application to provide
hi-resolution timing. These required configurations are stored in a file called
prj_lf.conf which is copied to the generated
src-gen folder by
can also supply your own configuration options in a file called
has to be located in the same folder as
west lf-build is invoked from.
There is such a file located in
~/application in the template. There is also a
debug.conf which is meant for containing debug options. Such
additional configuration files can also be passed to
west lf-build through the
--conf-overlays options. E.g.
west lf-build -c debug.conf.
lf-build west command
lf-build west command has already been used in previous sections.
It can be inspected in
lfc on the provided LF source file.
It then invokes
west build on the generated sources.
If you would like to pass forward arguments to the
west build command do so
-w flag. E.g.
-w -b nrf52dk_nrf52832 -p always passes information
about the dev-kit and also tells
west to clean the build folder before
One of the important functions of
lf-build is to parse a file called
CompileDefinitions.txt generated by
lfc. This file contains all the compiler
definitions which should be defined for the program.
lf-build passes all the
compiler definitions to the
west build command.
west lf-build -h for more information and the
Debugging LF Zephyr programs using QEMU and GDB
In this section we will see how a LF program can be debugged while running in QEMU emulation.
cd application west lf-build src/HelloWorld.lf -w "-b qemu_cortex_m3 -p always"
Note that we here, unlike the very first example, explicitly tell
lf-build that we are targeting a
qemu_cortex_m3 platform. This is the default platform which is used unless another is specified. It is added here for clarity.
- Start qemu as a debug server waiting for a local connection from
ninja -C build debugserver
gdband connect to the qemu server. Load the application image and run until main.
$ZEPHYR_SDK/arm-zephyr-eabi/bin/arm-zephyr-eabi-gdb (gdb) arm-zephyr-eabi/bin/arm-zephyr-eabi-gdb (gdb) target remote localhost:1234 (gdb) b main (gdb) c
From here you can step through the LF program. To get a more visual interface you can try:
(gdb) tui enable
Timing in QEMU emulations
The QEMU emulation is not cycle-accurate and implements optimizations such that if the system goes to sleep, like when the last active thread in the program calls
k_sleep(), then the emulator fast-forwards time.
This does not affect the QEMU-emulation of the unthreaded runtime since it implements sleeping between events using busy-waits.
However, the threaded runtime sleeps between events using a call to
k_cond_timedwait which has the side-effect that QEMU fast-forwards time.
This causes the emulation of threaded programs to appear as if the
fast target property was set to
Multiple Zephyr installations
If the follwing warning is shown when invoking
west lf-build or any other
WARNING: ZEPHYR_BASE=/path/to/zephyr in the calling environment will be used, but the zephyr.base config option in /path/to/lf-west-template is "deps/zephyr" which implies a different ZEPHYR_BASE=/path/to/lf-west-template/deps/zephyr To disable this warning in the future, execute 'west config --global zephyr.base-prefer env'
Then it means that you have multiple Zephyr repositories installed.
We do not recommend this as
west will link the application with the Zephyr found in the CMake package registry.
Please refer to the Getting Started section to purge the system of old Zephyr installations.
Wrong version of Zephyr
If, when trying to build an application with
west lf-build the following error occurs:
CMake Error at CMakeLists.txt:8 (find_package): Could not find a configuration file for package "Zephyr" that exactly matches requested version "3.2.0".
It means your Zephyr installation is of the wrong version.
Currently LF requires the exact version v3.2.0.
This restriction might be eased in the future.
lf-west-template will download this exact version automatically.
This might mean that you have other Zephyr installations.
Please remove them and the exported CMake packages.
Threaded Lingua Franca
In lfc v0.4.0 only the unthreaded runtime is supported with Zephyr.
threading: false is set, there will be the following error during compilation:
lf-west-template/application/src-gen/HelloWorld/core/platform/lf_zephyr_support.c:352:2: error: #error "Threaded support on Zephyr is not supported" 352 | #error "Threaded support on Zephyr is not supported"
Threaded Zephyr support is expected to be available soon.