IoT Zephyr

Zephyr Weekly Update – Bringing userspace to Xtensa

It was a lot of fun to play the guest in this week’s Zephyr Tech Talk. There was a lot to cover in “just” one hour (and there were tons of great questions from the audience to answer!), but I am happy that all the demos I wanted to show worked like I wanted. There are quite a few things that made my life easier when deciding I would migrate my “hackish” Arduino code to Zephyr, and the video dives into what these are.

Interestingly, by the end of the talk, I had shown most of the code on screen, all while digressing about many other things, answering questions, etc. I hope that helps make the point that Zephyr can really help you not reinvent the wheel, and help you focus more on the code that’s actually your application, and less on the boilerplate low-level stuff 🙂

Catch up on the recording here:

And as a reminder, all the code of the project is on GitHub, at so I encourage you to check it out!

And now, for the news from this past week…

Userspace on Xtensa

When building your application on top of Zephyr, you probably don’t want or need your entire code to run in supervisor mode, with full access to the memory, kernel objects, etc. While, say, a custom driver of your might require low-level interactions with the system, but your “actual” application probably only really cares about calling into a few APIs that will expose the data or functionality you need in your applications.

For architectures that include an MMU/MPU (Memory Management Unit / Memory Protection Unit), it is possible to instruct Zephyr to create so-called user-mode threads that end up running in their own sandbox, with very limited permissions unless explicitly granted.

This week, PR #61303 has introduced userspace support for Xtensa architectures, which is a major improvement, alongside a complete re-implementation of the MMU layer for Xtensa.

Picolibc 1.8.5

The newly released Zephyr SDK, version 0.16.4, ships the latest version of Picolibc, 1.8.5.

As per PR #62882, this new version of Picolibc brings more flexibility in selecting a printf/scanf variant to support only the format specifiers that one really needs, i.e. not bloat your binary if you don’t care about printing floats, for example.

As a reminder, while using a pre-compiled version from Picolibc straight from the SDK will give you faster compilation times, there is always the possibility to enable Kconfig option CONFIG_PICOLIBC_USE_MODULE if you want to tweak Picolibc further.

Stay tuned for a Zephyr Tech Talk entirely dedicated to Picolibc C on Wednesday, Dec. 6!

IGMPv3 support

The Internet Group Management Protocol (IGMP) is a protocol primarily used for managing multicast group memberships on IPv4 networks. It enables a host to inform its local router about its desire to join or leave a multicast group, which can be useful when building e.g. sensor networks where you want to use network resources as efficiently as possible.

As of this week, IGMPv3 is now supported. (PR #65293)

Among other things, IGMPv3 allows source filtering, enabling a system to report interest in receiving packets only from specific source addresses, or from all but specific source addresses, sent to a particular multicast address.

Boards & SoCs

STM32U5A9J-DK development board


  • A new pwm-clock binding allows to add a clock control device for a PWM node, such that the PWM can be controlled using the clock control API.
pwmclock: pwmclock {
    status = "okay";
    compatible = "pwm-clock";
    #clock-cells = <1>;
    pwms = <&pwm_ccu40 2 PWM_HZ(1000000) PWM_POLARITY_NORMAL>;
  • New regulator driver for Smartbond DA1469X SoC. (PR #65226)


  • The Bluetooth Hearing Access (HAS) server now uses non-volatile settings to restore the client awareness of preset list entries exposed by the server. (PR #64164)
  • A lot of work went into cleaning up the documentation of the POSIX API available in Zephyr.
  • A new Kconfig option, CONFIG_SDL_DISPLAY_ZOOM_PCT allows to artificially tweak the scale of the main display when using a native simulation on your desktop.
    This can be really useful when testing, say, a 200x200px smartwatch GUI on your 32″ Retina display, without killing your eyes 🙂 (PR #65556)
  • New shell commands (that can be enabled using CONFIG_PLIC_SHELL) to display the hit count of each interrupt controller’s IRQ line. (PR #65533)
uart:~$ plic stats get interrupt-controller@c000000
   IRQ        Hits
    10         236

uart:~$ plic stats clear interrupt-controller@c000000
Cleared stats of interrupt-controller@c000000.

uart:~$ plic stats get interrupt-controller@c000000
   IRQ        Hits
    10          90

  • Various improvements and optimizations to the modem UART backend (PR #65194)

A big thank you to the 12 individuals who had their first pull request accepted this week, 💙 🙌: @ajarmouni-st, @lukas-fwdev, @adolfogc, @adleris, @arnaudmz, @adrienbruant, @wmrsouza, @falvia, @deveritec-rosc, @kamilrakoczy, @ndrs-pst, and @idruzhinin.

As always, I very much welcome your thoughts and feedback in the comments below!

If you enjoyed this article, don’t forget to subscribe to this blog to be notified of upcoming publications! And of course, you can also always find me on Twitter and Mastodon.

Catch up on all previous issues of the Zephyr Weekly Update:

IoT Zephyr

Zephyr Weekly Update – C11 threads, Enhanced logging, and more

This has been a very busy week for the community, with an above average amount of new drivers and boards getting merged. Speaking of recently added boards, I am very excited to include one, the super tiny M5Stack AtomS3, in my Zephyr Tech Talk presentation next Wednesday! 🙂

I hope many of you will join, as I will be covering how I ended up migrating my now pretty old, and frankly quite hackish, Artificial Nose project to Zephyr in a matter of hours. I used this opportunity to deep more into some Zephyr features that I hadn’t add a chance to touch before, like Zbus, and I can’t wait to share my experience with y’all.

You should register to make sure you don’t miss the live stream, and of course feel free to also share the event with your network!

Support for C11 threads

The C11 standard introduced a native multi-threading API that aims at establishing a portable API for all things threads.

POSIX is of course a very popular programming model for manipulating threads, but being part of the language itself, the API introduced in the 2011 version of the C standard is effectively (or should be at least!) supported on *any* platform that supports the C11 standard.

#include <stdio.h>
#include <threads.h>

// Thread function
int printHelloWorld(void *arg) {
    printf("Hello, World!\n");
    return 0;

int main() {
    thrd_t thread;

    // Create a new thread
    if (thrd_create(&thread, printHelloWorld, NULL) != thrd_success) {
        fprintf(stderr, "Error creating thread\n");
        return 1;

    // Wait for the created thread to terminate
    thrd_join(thread, NULL);

    return 0;

Chris Friedt has been working on bringing C11 threads support to Zephyr and this materialized this week with PR #60759 being merged. Quite interestingly, since Zephyr already exposes a POSIX API, most of the threads.h APIs end up mapping mostly 1-to-1 to POSIX functions.

Logging to multiple UARTs

A new zephyr,log-uart chosen node can be used to indicate that log outputs may be sent to multiple UARTs.

Until now, the UART log backend would have been only logging to the zephyr,console chosen node, but with PR #64917 it’s now possible to have the following kind of node in your Devicetree to indicate the various UARTs where you’d like logs to show up:

/ {
	chosen {
		zephyr,log-uart = &log_uarts;

	log_uarts: log_uarts {
		compatible = "zephyr,log-uart";
		uarts = <&uart0 &uart1>;


New keyboard matrix GPIO driver

A new type of driver has been introduced to allow modeling a keyboard matrix out of any set of GPIOs. The gpio-kbd-matrix binding allows you to define your keyboard matrix configuration such as:

  kbd-matrix {
          compatible = "gpio-kbd-matrix";
          row-gpios = <&gpio0 0 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>,
                      <&gpio0 1 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
          col-gpios = <&gpio0 2 GPIO_ACTIVE_LOW>,
                      <&gpio0 3 GPIO_ACTIVE_LOW>,
                      <&gpio0 4 GPIO_ACTIVE_LOW>;

More details in PR #65117.

Boards & SoCs

  • The nRF9131 Evaluation Kit from Nordic is a single-board evaluation kit for the nRF9131 SiP for LTE-M and NB-IoT.
nRF9131 EK (Credit: Nordic Semiconductor)
  • The M5Stack AtomS3 is a *very* tiny ESP32-S3 based developer kit that manages to fit a small 0.85″ LCD display on what is effectively a 1×1″ (24×24mm) piece of electronics!
    Since it also has an on-board accelerometer, it can run the LVGL Accelerometer Chart code sample out-of-the-box!
LVGL Accelerometer Chart code sample running on the M5Stack AtomS3 board.
  • The Renesas Starter Kit+ for RZ/T2M is an evaluation and development kit for the RZ/T2M MPU. (PR #64566)
  • Support has been added for the Verdin iMX8M Plus Computer on Module (CoM) from Toradex. (PR #61713)
  • UP Squared Pro 7000 is now supported. It is the 3rd generation of palm-sized developer board of UP Boards series and it is powered by an Intel Alder Lake N (Intel N-series Platform) SoC. (PR #65019)
  • Support has been added for the STM32H7B0 SoC series. (PR #65092)


  • New driver for the Linear Technologies LTC2451 ADC, an ultra-tiny 16-bit ADC. (PR #64390)
  • New driver for Renesas HS3001 and HS3003 temperature/humidity sensors (PR #63016)
  • A charger driver has been added to the already existing regulator driver for the MAX20335 multi-function device. (PR #64971)
  • The LPS22DF altimeter / pressure sensor is now supported. It is an ultracompact, piezoresistive, absolute pressure sensor that can be used as a digital output barometer, with an output data rate up to 200 Hz (PR #62028)
  • The NXP LPC DMA driver now supports hardware triggering. (PR #64573)
  • New driver for NXP FlexRAM memory controller. FlexRAM is a highly configurable and flexible RAM memory array, found on e.g. RT10XX and RT11XX series. (PR #62788)
  • New modem driver for Quectel EG25-G. (PR #64746)
  • New driver for ExplorIR-M CO2 sensor. A new co2_polling code samples was also introduced to make it easy to try things out with this driver (or any other CO2 driver really!). (PR #64621)
  • A new CAN shell command (can timing) adds support for setting raw timing values. (PR #65054)


  • The inter-core messaging (ICMsg) backend now supports the transfer of dynamically allocated buffers. (PR #58741)
  • Added API to BLE Audio CAP to set codec capabilities. (PR #63223)
  • Zephyr native simulator is now the recommended target for running Zephyr in your desktop/POSIX environment, and the documentation has been updated to reflect that.
  • The UART Shell backend has been reworked to support the asynchronous UART API. (PR #63967)
  • A new set of shell commands (cred ...) allow to interactively set TLS network credentials. See the list of commands here. (PR #64343)
  • MCUmgr OS management group now has functions for getting/setting the current time to/from the rtc alias device. (PR #64934)
  • The Bluetooth “broadcast audio source” code sample now supports using e.g. your host computer as the audio source.
    Granted that you are running the sample on a device that has a USB Device stack and Audio support, enabling CONFIG_USE_USB_AUDIO_INPUT will make your device show up as a sound device when plugged to your computer, and any audio that you will send to this “virtual speaker”, will be broadcast over LE Audio! 🔊

A big thank you to the 11 individuals who had their first pull request accepted this week, 💙 🙌: @TimTTP, @GabrielHAFs, @LipinskiPNordicSemi, @michael-whg, @josuah, @CkovMk, @CharlesDias, @ndaneil, @xvigo, @KamilxPaszkiet, and @mpenate-ellenbytech.

As always, I very much welcome your thoughts and feedback in the comments below!

If you enjoyed this article, don’t forget to subscribe to this blog to be notified of upcoming publications! And of course, you can also always find me on Twitter and Mastodon.

Catch up on all previous issues of the Zephyr Weekly Update:

IoT Zephyr

Zephyr Weekly Update – New CoAP service

Hi everyone! In case you missed it, the Eclipse Foundation just released the results of their 2023 IoT Developer Survey. It is always a challenge to understand the trends in adoption of open source software as there is no obligation on the adopters’ side to tell when and where they are using open source projects 🙂

This survey is very helpful in shedding some light on the technology stacks people are using in their IoT solutions, and it’s nice to see Zephyr is on their radar.

Developer Embedded OS Preferences on Constrained Devices

Linux (43%), and FreeRTOS
(25%) are the top embedded
OS choices for constrained
devices. A solid 17% of
developers prefer no OS at all,
while Zephyr enjoys a
respectable 13%, compared to
only 8% in 2022.

In other news, here are some of the things that have kept the Zephyr community busy this week!

CoAP “servlets”

When building an IoT device, one typically wants to spend time writing their actual application logic, not reinventing the wheel regarding how they should implement the “Internet” aspect of their “Thing”

A merged pull request from this week, PR #64265, is introducing a CoAP server API that allows to easily register CoAP resources against a CoAP “service”, effectively getting rid of most of the boilerplate one would have to come up with if building on lower layer APIs.

In a nutshell, and in a slightly simplified way, a minimal CoAP server + /hello resource would not require much more code than:


static int my_get(struct coap_resource *resource, struct coap_packet *request,
                  struct sockaddr *addr, socklen_t addr_len)
    static const char *msg = "Hello, world!";
    struct coap_packet response;
    /** ... **/
    coap_packet_append_payload(&response, (uint8_t *)msg, sizeof(msg));

    return coap_resource_send(resource, &response, addr, addr_len);

static const char * const my_resource_path[] = { "hello", NULL };
COAP_RESOURCE_DEFINE(my_resource, coap_server, {
    .path = my_resource_path,
    .get = my_get

The CoAP service can then be started/stopped using coap_service_start()/coap_service_stop() (in the example above it’s set to start automatically) or using shell commands, and things like the magic ./well-known/core endpoint, retransmissions, etc. are automatically taken care of by the service.

I love it when Zephyr gets new features like this. This new service feels very much like what you would expect to find in a full-blown operating system, and yet we’re still talking about super constrained devices here.

You should definitely check out the code sample to get more familiar with this new API.

Boards & SoCs

  • Arm Cortex-A and Cortex-R now support SMP! It is worth noting that FPU_SHARING and USERSPACE are not supported yet. (PR #61206)
  • It is now possible to have a custom interrupt control interface implementation on Cortex-M, using the CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER option.
    While all Cortex-M platforms have an NVIC controller,custom SoCs may have additional IRQ controllers, or require custom handling. This option allows to indicate that these SoCs are using custom interrupt control interface implementation
  • The Firefly ROC-RK3568 mini computer is an ARM64 board with a quad-core Cortex-A55 @ 2GHz, 4GB of LPDDR, 32GB of eMMC, M.2 PCI Express slots, dual Gigabit Ethernet ports, and more. It is now supported in Zephyr! (PR #64217)
Lolin S2 Mini dev kit
  • Support has been added for the Lolin S2 Mini (also known as Wemos S2 Mini …and I am realizing as I am typing this that I have one sitting on my desk, and one connected to my electricity meter monitoring the consumption of my house! Guess I need to do some hacking and porting soon!). This small devkit features an ESP32-S2 with 4MB of Flash, 2MB of PSRAM, and can be used with a variety of shields.
  • On STM32, the ADC driver now supports power management. A code sample has been added to demonstrate the improvements (spoiler alert: consumption can be almost 20x less now). (PR #64191)
  • Clock control driver is now available for Ambiq SoCs. (PR #63097)
  • Added support for NXP Multirate Timer peripheral. (PR #64801)


  • A new Wi-Fi driver is available for the Infineon AIROC, as found in CYW4343W, CYW4373, CYW43012, CYW43012, CYW43439. It is pretty exciting since among other things, it means we should soon see Wi-Fi support added to the Rasperry Pi Pico W. (PR #63721)
  • The aforementioned Wi-Fi module supports both SPI and SDIO interfaces, and it’s the latter that’s used by the driver for now.
    SDIO is an extension of the SD specification covering I/O functions, and it turns out support for it was also just added to Zephyr. (PR #56869)
  • The Analog AD5592 is a versatile multifunction IC that has 8 I/O pins that can be independently configured to act as DAC output, ADC inputs, or regular GPIOs.
    A new “multi-function” driver is now available to leverage all these different options easily from the Devicetree. (PR #64592)
  • New Ethernet driver for Microchip LAN8651. (PR #63614)
  • New driver for the TSL2561 light sensor. (PR #56869)


  • A new spinlock mechanism, ticket spinlocks, has been introduced. It is meant to help in situations where traditional locking would be “unfair” across multiple CPUs due to how the implementation only relies on a single atomic variable. Ticket spinlocks provide true FIFO ordering at the cost of slightly increased memory footprint. (PR #61541)
  • Some awesome work to implement the official LwM2M interoperability tests, in particular the ones related to bootstrapping, registration, device management and service enablement interface, and information reporting interface. I highly encourage you to have a look as this is also a great way to get up to speed with using Pytest for Zephyr testing 🙂 (PR #64013)

    I wonder if the Open Mobile Alliance still organizes PlugFests, but I would live to see Zephyr participate in the future.
  • CMSIS version has been updated to 5.9.0 in the Zephyr manifest. (PR #64851)
  • API for Bluetooth CAP Commander has been introduced. (PR #64645)

A big thank you to the 7 individuals who had their first pull request accepted this week, 💙 🙌: @cocoeoli, @mgolu, @topisani, @samueltardieu, @p9n, @BenjaminDeuter, and @raffi-g.

As always, I very much welcome your thoughts and feedback in the comments below!

If you enjoyed this article, don’t forget to subscribe to this blog to be notified of upcoming publications! And of course, you can also always find me on Twitter and Mastodon.

Catch up on all previous issues of the Zephyr Weekly Update: