Tprrt's Blog

Embedded Linux, Zephyr RTOS, open-source hardware, Linux gaming, retro gaming, and competitive fitness

May 26, 2026

RIOT-OS 2026.04 "Fire Rizzlease" is out

RIOT-OS 2026.04, codenamed Fire Rizzlease, was released on May 6, 2026. RIOT is a multi-threading operating system targeting microcontrollers found in the Internet of Things — from 8-bit and 16-bit MCUs to lightweight 32-bit processors — with a focus on energy-efficiency, soft real-time capabilities, and a small memory footprint.

This release spans 84 days of development, 125 merged pull requests composed of 229 commits, and contributions from 27 people. 1,141,523 lines were deleted against 25,007 inserted, mostly from a vendor code cleanup.

Codeberg mirror

RIOT is now synced to Codeberg (#21997), a non-profit community forge, alongside GitHub.

Massive EFM32 vendor code removal

Over one million lines of vendor code have been removed from the EFM32 family, replaced by a pkg/gecko_sdk dependency (#22040). This accounts for most of the deletions and shrinks the codebase for Silicon Labs EFM32-based boards.

Raspberry Pi Pico 2 / RP2350 improvements

RP2350 support was reworked (#21753):

  • Unified abstractions between the RISC-V and ARM cores of the RP2350.
  • Added the XH3IRQ interrupt controller.
  • Updated UART driver.
  • Added RISC-V support.

The scope of this work was large enough to inspire a bachelor's thesis at HAW Hamburg.

New board and CPU support

Three new targets join the supported hardware list:

  • pro-micro-nrf52840 (#22089) — a popular nRF52840-based Pro Micro form-factor board.
  • slstk3301a (#22069) — Silicon Labs EFM32 Tiny Gecko starter kit.
  • STM32H7 (#21978) — high-performance STM32 family, with additional peripheral support for the nucleo-h753zi (#22076).

New device drivers

  • AMG88xx (#22104) — infrared array sensor (thermal camera) from Panasonic.
  • ADS1X1X (#21694) — family of Texas Instruments I²C ADCs.

Guide site and documentation

The RIOT Guide Site is the entry point for new users and is replacing Doxygen for prose documentation. This release adds:

  • More tutorials.
  • An experimental Supported Boards section.
  • Unit tests in tutorials (#22042).
  • Updated Astro v6 framework (#22145).

The Doxygen API reference remains available at api.riot-os.org.

Networking improvements

Several additions to the GNRC networking stack:

  • New gnrc_pktshark module to pretty-print network traffic (#21284).
  • gnrc_ipv6_nib_dyn_lladdr_get() API (#22013).
  • ABR (Authoritative Border Router) now run-time configurable (#21081).
  • Generic UDP shell command (#22049).

Notable bug fixes

43 bugs were fixed in this release, including:

  • ESP8266 crashes on reboot and startup (#22014, #22010).
  • Potential buffer overflow in the atwinc15x0 driver (#22041).
  • NanoCoAP message corruption in coap_build_reply() (#22094).
  • Wrong byte order for gyro and accelerometer reads in the MPU-9x50 driver (#22135).
  • LVGL configuration and SDL issues on native (#22005, #22139).
posted at 12:00  · 2 min read  ·   ·  riot  rtos  embedded  iot  article

Jul 29, 2022

Zephyr Device Tree Guide

Introduction

The Zephyr project, hosted by the Linux Foundation since 2016, provides a real-time operating system (RTOS), under the Apache 2.0 license, for connected devices too small for Linux or acting as companions to a Linux core. It targets microcontrollers and IoT devices, is modular, and is written in C (C11, with C++17 supported).

It can be configured to run on devices with as little as 10 KB of memory. It supports 32-bit and 64-bit architectures (Cortex-A, Cortex-M, Cortex-R, RISC-V, x86-64, etc.), many boards (Feather, nRF52840, ST Discovery, ST Nucleo, ESP32, etc.), connectivity such as Bluetooth, Ethernet, Wi-Fi and LoRa, and network protocols including IPv4, IPv6, UDP, TCP, CoAP, LWM2M, MQTT and DNS.

Like Linux, Zephyr uses Kconfig, and its device model is mainly based on device tree.

Device tree

Device trees are tree data structures that describe the hardware components and their relationships in a system. They are stored in text files, the device tree sources (*.dts), which developers write to describe the hardware of SoCs and boards. The operating system uses them to determine how to initialize and interact with the hardware.

Each node describes a device of the system, has properties that describe its characteristics, and has exactly one parent (except the root node).

Each device driver is associated with a specific device tree node, which represents a hardware component in the system. The device driver provides the necessary code and data to control the behavior of the hardware component.

test_i2c_bme280: bme280@6 {
        compatible = "bosch,bme280";
        reg = <0x6>;
};

In the Linux kernel, device tree sources are compiled to device tree binaries (dtb) that the bootloader stages (U-Boot, TF-A...) and the kernel parse at boot, so the same binaries can support several hardware configurations.

In Zephyr, device tree sources are instead turned at build time into a devicetree_generated.h C header. It contains the macros and data structures that let drivers read the hardware description, such as a device's memory mapping, pin assignments and IRQ numbers:

#define DT_COMPAT_HAS_OKAY_bosch_bme280 1
#define DT_N_INST_bosch_bme280_NUM_OKAY 1
#define DT_FOREACH_OKAY_bosch_bme280(fn) fn(DT_N_S_soc_S_i2c_40005400_S_bme280_77)
#define DT_FOREACH_OKAY_VARGS_bosch_bme280(fn, ...) fn(DT_N_S_soc_S_i2c_40005400_S_bme280_77, __VA_ARGS__)
#define DT_FOREACH_OKAY_INST_bosch_bme280(fn) fn(0)
#define DT_FOREACH_OKAY_INST_VARGS_bosch_bme280(fn, ...) fn(0, __VA_ARGS__)
#define DT_COMPAT_bosch_bme280_BUS_i2c 1

Where:

  • DT_COMPAT_HAS_OKAY_bosch_bme280: indicates that there is at least one instance of BME280
  • DT_N_INST_bosch_bme280_NUM_OKAY: defines the number of BME280 instances that are marked okay
  • DT_FOREACH_OKAY_bosch_bme280: allows you to apply a function fn to each instance of the BME280
  • DT_FOREACH_OKAY_VARGS_bosch_bme280: also allows you to apply a function fn to each instance of the BME280, but with additional arguments
  • DT_FOREACH_OKAY_INST_bosch_bme280: allows you to apply a function fn to each instance of the BME280, passing the instance number as an argument
  • DT_FOREACH_OKAY_INST_VARGS_bosch_bme280: is similar to the previous macro, but this one allows for additional arguments
  • DT_COMPAT_bosch_bme280_BUS_i2c: indicates that the BME280 device is connected to an I2C bus.
  • DT_N_S_soc_S_i2c_40005400_S_bme280_77: refers to a specific node in the device tree, here it refers to the BME280 sensor connected to the I2C controller with the base address 0x40005400 within the SoC. The sensor's address on this I2C bus is 0x77.

In addition, device tree sources can be extended or overridden, for example to connect additional devices to a board, or to disable board devices which will not be used:

/ {
        aliases {
                bme280 = &bme280;
        };
};

&spi1 {
        status = "disabled";
};

&i2c1 {
        status = "okay";
        bme280: bme280@77 {
                compatible = "bosch,bme280";
                reg = <0x77>;
        };
};

Binding

The content of device tree sources is described in binding files, written in YAML. They are also used to validate device tree sources against the YAML description.

description: BME280 integrated environmental sensor

compatible: "bosch,bme280"

include: [sensor-device.yaml, i2c-device.yaml]

Device driver

A Zephyr driver reads the properties of its device tree node through macros defined in C headers. For example, this code initializes a BME280 sensor using properties from the device tree:

#include <device.h>
#include <drivers/i2c.h>
#include <devicetree.h>
#include <zephyr.h>

// Define the node identifier for the BME280 sensor
#define BME280_NODE DT_N_S_soc_S_i2c_40005400_S_bme280_77

// Function to initialize the BME280 sensor
static int bme280_init(const struct device *dev)
{
    // Check if the node is available
    if (!device_is_ready(dev)) {
        printk("Device %s is not ready\n", dev->name);
        return -ENODEV;
    }

    // Retrieve the I2C device associated with the BME280 node
    const struct device *i2c_dev = DEVICE_DT_GET(DT_BUS(BME280_NODE));

    if (!device_is_ready(i2c_dev)) {
        printk("I2C device not ready\n");
        return -ENODEV;
    }

    // Write some initialization code here, such as configuring registers

    printk("BME280 sensor initialized\n");
    return 0;
}

// Initialize the BME280 sensor at boot time
SYS_INIT(bme280_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);

Conclusion

Anyone who has written a BSP or driver for Linux will find this familiar. It is a steeper step for people coming from bare microcontroller development.

posted at 20:32  · 4 min read  ·   ·  zephyr  device-tree  rtos  embedded  article