Getting Started with Zephyr RTOS: A Beginner’s Step-by-Step Guide

The world of embedded systems is evolving fast — and with it, the need for more powerful, flexible, and secure real-time operating systems (RTOS). Whether you’re building a low-power sensor node, a Matter-ready smart device, or simply want to move beyond Arduino-level projects, Zephyr RTOS offers an incredibly robust foundation.

But it can also seem intimidating at first.

This guide is for makers, developers, and curious tinkerers who want to get hands-on with Zephyr — no prior RTOS experience required. By the end of this tutorial, you’ll have:

  • Set up the Zephyr toolchain on your machine
  • Built and flashed your first Zephyr application
  • Learned how to modify a sample program
  • Understood the basics of Zephyr’s modular architecture

Whether you’re using a Nordic nRF52-DK, STM32 Nucleo, or even just running code on a virtual board using QEMU, this guide will walk you through the essentials — step by step.

Let’s get started.

Prerequisites

Before jumping into the setup, it’s important to make sure you have the right tools and hardware ready. Zephyr supports a wide range of platforms, but this guide will focus on the most accessible options to help you get started smoothly.

Hardware (choose one):

  • nRF52-DK (Nordic Semiconductor)
  • STM32 Nucleo (STMicroelectronics)
  • FRDM-K64F (NXP)
  • QEMU virtual board (if you don’t have hardware yet)

Operating System:

Zephyr supports Linux, macOS, and Windows (via WSL2). This guide will use Ubuntu 22.04 as the base example, but most steps can be adapted to your OS.

Software Requirements:

  • Python 3.8+
  • CMake (>=3.20)
  • Ninja build system
  • Git
  • Zephyr SDK (includes compilers, tools, etc.)
  • west CLI tool (Zephyr’s project manager)

A basic understanding of C or C++ and comfort using a terminal will help, but you don’t need to be an expert.

Step 1: Install the Zephyr SDK and Toolchain

Setting up Zephyr begins with installing its core development tools. These include the Zephyr SDK, the west tool, and a few common build dependencies.

This guide assumes you’re using Ubuntu 22.04. If you’re on macOS or Windows (via WSL2), the steps are nearly identical with minor path adjustments.

1.1 Install System Dependencies

Open your terminal and run:

sudo apt update
sudo apt install --no-install-recommends git cmake ninja-build gperf \
ccache dfu-util device-tree-compiler wget python3-pip python3-setuptools \
python3-wheel xz-utils file make gcc gcc-multilib

1.2 Install West (Zephyr’s CLI Tool)

west is Zephyr’s official tool for managing repositories and building projects.

pip3 install --user west

Make sure ~/.local/bin is in your PATH. You can add it with:

echo 'export PATH=$HOME/.local/bin:$PATH' >> ~/.bashrc
source ~/.bashrc

1.3 Set Up the Zephyr Project Directory

Create a working folder for Zephyr and initialize the project:

mkdir zephyrproject
cd zephyrproject
west init -m https://github.com/zephyrproject-rtos/zephyr
west update
west zephyr-export

This pulls in Zephyr and all its required modules.

1.4 Install Python Dependencies

pip3 install -r zephyr/scripts/requirements.txt

1.5 Download and Install the Zephyr SDK

Download the latest SDK from the official page, then:

chmod +x zephyr-sdk-<version>-linux-x86_64-setup.run
./zephyr-sdk-<version>-linux-x86_64-setup.run

During installation, point it to your Zephyr base directory when prompted.


Your environment is now set up. Next, you’ll configure your board and flash your first program.

Step 2: Set Up Your Development Board

Now that Zephyr is installed, it’s time to prepare your development board. Zephyr supports over 450 boards, so chances are yours is already compatible.

We’ll use the STM32 Nucleo F401RE as an example, but you can follow similar steps for other boards like the nRF52-DK, FRDM-K64F, or any board listed in Zephyr’s official supported boards list.

2.1 Identify Your Board Name

Each supported board has a unique “board name” used during compilation. For example:

  • STM32 Nucleo F401RE → nucleo_f401re
  • nRF52-DK → nrf52dk_nrf52832
  • FRDM-K64F → frdm_k64f

You can browse all options in the boards directory on GitHub.

2.2 Install Required Drivers (Linux)

Most modern Linux distributions will detect and mount USB-enabled development boards automatically. But for STM32 boards, you may need to install udev rules:

wget -O st-link.rules https://raw.githubusercontent.com/stlink-org/stlink/develop/config/udev/rules.d/49-stlinkv*.rules
sudo cp st-link.rules /etc/udev/rules.d/
sudo udevadm control --reload
sudo udevadm trigger

This allows your OS to detect and flash STM32 boards over USB.

For Nordic boards, flashing is typically done using the built-in J-Link interface, which may require nRF Command Line Tools if you’re debugging more advanced applications.

2.3 Connect Your Board

Plug your development board into your PC using a USB cable. Make sure it powers up and is recognized (you can check with dmesg or lsusb on Linux).


Your board is now ready for action. Let’s build and flash your first Zephyr application in the next step.

Step 3: Build and Flash Your First Zephyr Application

With your toolchain set up and board connected, it’s time to build and flash your first application. Zephyr comes with a variety of sample projects — the perfect place to start is with the classic blinky app.

3.1 Create a Sample Project Folder

Navigate to your workspace and create a directory for your first Zephyr project:

cd zephyrproject
mkdir my-zephyr-apps && cd my-zephyr-apps

Now create a new application folder and copy the blinky sample from Zephyr’s source:

cp -r ../zephyr/samples/basic/blinky ./blinky
cd blinky

3.2 Build the Application

Use the west tool to build your firmware for the correct board:

west build -b nucleo_f401re

Replace nucleo_f401re with your board’s name if you’re using a different device (check Zephyr’s board index if unsure).

If the build succeeds, you’ll see a message ending with:

csharpCopiazăEditează[100%] Built target zephyr_final

3.3 Flash the Firmware

Once built, you can flash it directly to your board using:

west flash

This will detect the connected board and upload the firmware using the correct backend (ST-Link, J-Link, etc.).

3.4 Monitor Serial Output (Optional)

To view logs or debug output, connect to the serial port using a tool like minicom, screen, or picocom:

sudo picocom /dev/ttyACM0 -b 115200

⚠️ Note: Replace /dev/ttyACM0 with your board’s actual serial device.

If all goes well, your board’s LED should start blinking — your first Zephyr project is live!


In the next step, we’ll modify the code to make it your own and explore Zephyr’s modular application structure.

Step 4: Modify the Code

Now that you’ve built and flashed your first Zephyr application, let’s personalize it. This step gives you a glimpse into Zephyr’s modular structure and how easy it is to customize your firmware.

4.1 Explore the Source Files

In your blinky folder, open the file:

src/main.c

You’ll see a simple program that toggles an LED using Zephyr’s device driver API:

#include <zephyr/kernel.h>
#include <zephyr/drivers/gpio.h>

#define LED0_NODE DT_ALIAS(led0)

static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(LED0_NODE, gpios);

void main(void)
{
gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE);

while (1) {
gpio_pin_toggle_dt(&led);
k_msleep(1000);
}
}

This code blinks the onboard LED every 1000 milliseconds (1 second).

4.2 Customize the Blink Rate

Try reducing the delay:

k_msleep(300);  // faster blink rate

Or, make it dynamic with a pattern:

while (1) {
gpio_pin_set_dt(&led, 1);
k_msleep(200);
gpio_pin_set_dt(&led, 0);
k_msleep(800);
}

4.3 Rebuild and Flash Again

After saving your changes, rebuild the project:

west build -t run

Or rebuild and flash in one go:

west flash

You should now see the LED blinking according to your updated timing logic.

4.4 Add a Log Statement (Optional)

Zephyr includes a built-in logging system. To enable basic output:

  1. Add this line at the top of main.c:
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(main);
  1. Add a log line in your loop:
LOG_INF("LED toggled");
  1. Enable logging in prj.conf:
CONFIG_LOG=y
CONFIG_LOG_DEFAULT_LEVEL=3

You’ll now see messages over the serial port when running the program — a helpful tool for debugging and testing more complex logic.


Next, we’ll explore what’s possible beyond blinking LEDs, and where to go from here.

Step 5: Next Steps

You’ve now built, flashed, and customized your first Zephyr RTOS application — congrats! From here, you can start exploring Zephyr’s full potential in real-world IoT development.

Here are some ideas to level up your skills and build more powerful, cloud-optional devices.

5.1 Explore More Sample Applications

Zephyr includes dozens of sample apps covering:

  • I²C, SPI, UART, and GPIO drivers
  • Networking protocols like MQTT, CoAP, and HTTP
  • Bluetooth Low Energy (BLE)
  • LoRa and IEEE 802.15.4 mesh networking
  • Power management and deep sleep modes

To try a new one, simply copy it into your workspace and repeat the build/flash process.

5.2 Add Peripheral Drivers

Want to connect a sensor, actuator, or display? Zephyr makes it easy to write or reuse device drivers using its devicetree system.

Some examples:

  • Read from a DHT22 or BMP280 temperature sensor
  • Display data on an OLED or e-paper screen
  • Use motion detection from an accelerometer

These examples are often covered in the samples/sensor/ directory.

5.3 Build for Networking

Zephyr includes built-in support for:

  • Wi-Fi (with supported chips)
  • BLE (Nordic, NXP, Intel)
  • Thread and Matter
  • MQTT and CoAP protocols

You can experiment with sending data over MQTT to a local Mosquitto broker, or creating BLE beacons — all with no reliance on proprietary APIs.

5.4 Join the Zephyr Community

The Zephyr ecosystem is growing fast — and the best way to keep learning is to engage with the community:

Conclusion

Zephyr RTOS might seem complex at first, but once you take the first few steps, it reveals itself as a powerful and flexible platform — ideal for developers who care about local control, modularity, and open-source freedom.

In this tutorial, you:

  • Set up your Zephyr development environment
  • Flashed your first working application
  • Modified the code and explored how Zephyr projects are structured
  • Got a preview of the many possibilities Zephyr offers for real-world IoT use cases

Whether you’re building a BLE-enabled sensor, a low-power data logger, or a Matter-compatible smart device, Zephyr gives you the tools to go beyond quick prototypes — and into production-grade IoT development.

3 thoughts on “Getting Started with Zephyr RTOS: A Beginner’s Step-by-Step Guide”

Leave a Comment