IoT Zephyr

Zephyr Weekly Update – Getting ready for Zephyr 3.5

Apologies for missing last week’s update. Last Friday was the feature freeze for Zephyr 3.5 and everyone, including myself, was pretty busy trying to push everything over the finish line!

Because of the feature freeze, no significant changes happened in the last week, so this update will still pretty much feel like a “weekly”, I guess 🙂 I will try to keep it short (…ish) since I am preparing a full write-up about what’s new in Zephyr 3.5, and I don’t want to spoil all the fun! I would also like to apologize to the Bluetooth contributors and maintainers in particular as I’m pretty sure I am missing important stuff — I definitely spotted lots of stabilization and bug fixing but if I forgot something important, please let me know in the comments or on Discord!

Also, remember to join Peter and me next Wednesday, Oct. 11, for our 3rd Zephyr Tech Talk, where we’ll discuss everything you need to know about Renode! I’d actually recommend you “RSVP” on LinkedIn, as this is the best way to make sure you will get a reminder as we go live. You can also of course spread the word in your network, if you feel like it.

Linkable loadable extensions (llext)

The newly introduced Linkable Loadable Extensions (llext) subsystem makes it possible to dynamically extend the functionality of an application at runtime. Extensions can be loaded from pre-compiled ELF formatted data which is verified, loaded, and linked with other extensions.

As often, an example is worth a thousand words and I encourage you to use the llext shell commands to get a feel of what it’s all about. A dedicated sample will give you all the instructions you need to build a “Hello World” binary, and then dynamically load it and invoke it using shell commands (there is even a command to load the hex-encoded binary, so you can actually do the whole thing without leaving your Zephyr shell!).

uart:~$ llext help
llext - Loadable extension commands
  list          :List loaded extensions and their size in memory
  load_hex      :Load an elf file encoded in hex directly from the shell input.
                 <ext_name> <ext_hex_string>
  unload        :Unload an extension by name. Syntax:
  list_symbols  :List extension symbols. Syntax:
  call_fn       :Call extension function with prototype void fn(void). Syntax:
                 <ext_name> <function_name>

I am really excited about what’s going to come next now that one of the most requested feature since many years is basically unlocked. There’s still a lot that needs to be done (as an example, in this initial version, one may need to disable memory protection for llext to work…) but that makes things even more exciting! (PR #57086)

Binary descriptors

Binary descriptors are a new feature that makes it super simple to describe data objects (think: “model number” of your device, “kernel version”, etc.) that end up being linked at a known offset in your binary.

Like I just said, binary descriptors are really easy to use:

#include <zephyr/bindesc.h>


“Standard” binary descriptors such as build time, or kernel version, can be enabled without having to change anything in your code, just by enabling the dedicating Kconfig options.

A new west bindesc command has been introduced to allow developers to read binary descriptors in .bin, .hex, .elf, or .uf2 binary files.

You may want to check out the new code sample to familiarize yourself with the different macros and tools surrounding binary descriptors.

(PR #54464)

Object cores

Object cores are a new kernel debugging tool that can be used to both identify and perform operations on registered objects.

Kernel objects such as semaphores, message queues, etc. may now (if enabled via the dedicated CONFIG_OBJ_CORE_ * Kconfig options) embed a new “object core” that can be used to gather and access all sorts of statistics about the object.

The documentation page for this new feature is quite frankly excellent, so I would recommend you check it out as it’s gonna do a better job than I ever will at explaining things!

(PR #59075)

Boards & SoCs

Raspberry Pi Model 4 B
  • As everyone is talking about the Raspberry Pi 5 these days, this will likely not get all the attention it deserves, but did you know that Zephyr now supports Raspberry Pi 4 Model B?
    It is very early stage and very few peripherals are supported at the moment, but the idea of being able to run Zephyr on an MPU board that many people already have handy is very cool. And it’s always nice to see new Arm64 SoCs and boards being added!
    (PR #62320).
  • Support for Nucleo U5A5ZJ-Q was added. As a reminder the U5 series features Arm® Cortex®-M33 cadenced at up to 160 MHz, and the “U” stands for ultra low-power 🙂 (PR #63144)


HM330X particle sensor
  • Added TMAG5170 3d Hall effect sensor driver. It is a pretty complete driver with power management, CRC-based error detection, trigger mode, … so you may want to bookmark it for next time you need to write a sensor driver! (PR #61346)
  • New HM330X particle sensor driver. I actually wrote this driver as it’s a sensor that I’ve been using to monitor dust levels in my pottery studio. It’s proven to be very accurate and reliable even when running 24/7 which, to be honest, is not always the case for “cheap” maker-oriented sensors. I think it might have been my first sensor driver contribution to the project, and I have to admit it went pretty smoothly! (PR #62786)
  • New Microchip CAN-FD MCP251xFD driver, “an important addition to the existing range of Zephyr CAN drivers” to quote Brix, one of the maintainer of the CAN subsytem. (PR #59968)
  • New DMA driver for NXP SMARTDMA. This IP is is a custom peripheral intended for graphics acceleration on the NXP RT595 (PR #57616)
  • STM32 I2C driver now supports 10-bit addressing (PR #60620)
  • RTC driver for STM32 now supports sub-second ticks (note that this increases power consumption). (PR #61580)
  • New PWM pulse capture driver for S32K344. (PR #62695)
  • Added eDMA support for S32K344. (PR #61311)
  • New bit-bang driver for MDIO. (PR #56679)
  • New ALTERA Parallel I/O (PIO) driver. It supports calibration, setting/getting alarms, and alarm callbacks. (PR #61162)
  • New Ambiq AM1805 RTC driver. (PR #62357)
  • Support has been added for Intel eMMC host controller. (PR #61108)
  • New vertical decoder API for decoding sensor data. (PR #61022)
  • adc_read_dt() function to read from an ADC by providing a Devicetree node . (PR #63010)


A big thank you to the 21 individuals who had their first pull request accepted in the past 2 weeks, 💙 🙌: @moritzstoetter, @ivaniushkov, @fkwasowi, @nik012003, @meshium, @jandriea, @hlord2000, @wouterh, @srisurya1, @JeroenReeskamp, @bjda, @Fladdan, @zohavas, @lifenggitacc, @dcorbeil, @stasys0, @AirChandler, @lindblandro, @graffiti, @rahul-sin, and @tbr-tt.

As always, I very much welcome your thoughts and feedback in the comments below. See you in two weeks, as I don’t think next week will see any noteworthy update as the final release approaches.

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 – Participate in Zephyr Developer Survey 2023!

There is one week to go until the feature freeze for Zephyr 3.5, and also just about a week to participate in this year’s Zephyr Developer survey.

Whether you are using Zephyr for work or just for a pet project, we’d love to hear from you and understand what you love about the project and the community, and what you’d want to see improved. I promise it should take you less than 10 minutes to fill out, and your input will be incredibly useful to shape the future of the project.

Understanding and troubleshooting initialization levels

Understanding initialization levels and how all the various drivers “light up” when a Zephyr application starts can be pretty intimidating.

That’s why you will likely appreciate the introduction of a new tool making things very visual when it comes to the bootstrapping of your application.

The new initlevels target in west gives you a quick way to dump the list of init functions that are being called at each stage of the booting process. (PR #62459)

Let’s say I want to use this with the newly added LVGL demo apps, running on an M5Stack Core2.

 west build -t initlevels -p -b m5stack_core2 -s .\samples\modules\lvgl\demos\ --  -DCONFIG_LV_Z_DEMO_MUSIC=y

The output would be as follows, giving me a good overview of when each driver is kicking in, and making it easier to spot potential bugs in the bootstrap sequence of my application.

  __init___device_dts_ord_5: clock_control_esp32_init(__device_dts_ord_5)
  __init_statics_init_pre: statics_init(NULL)
  __init___device_dts_ord_11: gpio_esp32_init(__device_dts_ord_11)
  __init___device_dts_ord_13: gpio_esp32_init(__device_dts_ord_13)
  __init___device_dts_ord_58: entropy_esp32_init(__device_dts_ord_58)
  __init___device_dts_ord_61: uart_esp32_init(__device_dts_ord_61)
  __init_uart_console_init: uart_console_init(NULL)
  __init_sys_clock_driver_init: sys_clock_driver_init(NULL)
  __init_enable_logger: enable_logger(NULL)
  __init_enable_shell_uart: enable_shell_uart(NULL)
  __init_malloc_prepare: malloc_prepare(NULL)
  __init_k_sys_work_q_init: k_sys_work_q_init(NULL)
  __init___device_dts_ord_12: i2c_esp32_init(__device_dts_ord_12)
  __init___device_dts_ord_25: mfd_axp192_init(__device_dts_ord_25)
  __init___device_dts_ord_84: spi_esp32_init(__device_dts_ord_84)
  __init___device_dts_ord_80: regulator_axp192_init(__device_dts_ord_80)
  __init___device_dts_ord_81: regulator_axp192_init(__device_dts_ord_81)
  __init___device_dts_ord_82: regulator_axp192_init(__device_dts_ord_82)
  __init___device_dts_ord_85: regulator_axp192_init(__device_dts_ord_85)
  __init___device_dts_ord_26: gpio_axp192_init(__device_dts_ord_26)
  __init_gpio_hogs_init: gpio_hogs_init(NULL)
  __init___device_dts_ord_86: ili9xxx_init(__device_dts_ord_86)
  __init___device_dts_ord_14: ft5336_init(__device_dts_ord_14)
  __init___device_dts_ord_15: NULL(__device_dts_ord_15)
  __init_lvgl_init: lvgl_init(NULL)

Running LVGL demos is now (much) easier!

Thanks to Fabian’s excellent work in PR #62904, running one of the default LVGL ‘demo’ apps has become significantly easier this week.

Check out the instructions of the newly added code sample to get started in no time. It’s really exciting to see all the improvements being made around all things GUI recently!

By the way, in case you didn’t know, LVGL code can also run in an HTML canvas, which I find really cool.

Music Player App demo. More LVGL demos here.

Boards & SoCs

  • MPU/MMU-based stack guard is now enabled on ARM64. If you enable CONFIG_ARM64_STACK_PROTECTION, the system will trigger a fatal error if the current process stack overflows. This is done by preceding all stack areas with a fixed guard region. (PR #62902)
  • The Nuvoton NPCX7M6FB evaluation board is a development platform to for Nuvoton NPCX7 series of microcontrollers. It features an Arm Cortex-M4F MCU, with 256 KB RAM / 64 KB ROM — now supported! (PR #62799)


  • hwinfo driver is now available for TI SimpleLink CC13xx/CC26xx series. It allows to retrieve the device ID and to access the cause of reset. (PR #62537)
  • STMPE811 touch controller is now supported. (PR #61826)
  • RAM disk driver (which I didn’t know Zephyr had until today!) can now be easily configured directly via Devicetree. It now also supports multiple instances. (PR #60149)
/ {
	ramdisk0 {
		compatible = "zephyr,ram-disk";
		disk-name = "RAM";
		sector-size = <512>;
		sector-count = <192>;
  • The MCAN driver now supports statistics. It can be enabled using Kconfig CONFIG_CAN_STATS. (PR #62758)
  • New driver for NXP VREF. (PR #56822)
  • LTC2990 Quad I2C Voltage, Current and Temperature Monitor (no less!) from Analog Devices is now supported. (PR #60842)
  • On all STM32 ADC, it is no longer possible to read sensor channels (Vref, Vbat or temperature) using the ADC driver, and the dedicated sensor driver should be used instead. (PR #62345)
  • The driver for the LIS2DH accelerometer can now trigger an interrupt when a single tap is detected. (PR #62498)
  • Various improvements to the NVMe disk driver. (PR #62820)


  • When using the modem subsystem to describe “chat scripts” (ex. “If I send you this AT command, I’m interested in capturing this portion of your response”), you can now dynamically create chat scripts.
    This makes it possible to adapt to the runtime conditions, as the parameters of the various commands, or the expected responses, might not always be known at build time. (PR #62703)
    By the way, don’t forget to join us on Wednesday for our second episode of the Zephyr Tech Talks, as this will be your chance to learn more about the new modem subsystem from its author 🙂
  • A new lwm2m create shell command makes it easy to create and register new LWM2M objects on the fly. (PR #62869)
    Note to self: I need to prepare some demos around using LWM2M with Zephyr at some point 🙂
  • If you’re using the USB Device stack for building some kind of audio gadget, you can now expose volume control functionality to the host. (PR #60973)
  • SO_REUSEADDR and SO_REUSEPORT socket options are now supported, making it possible to have multiple sockets bound to the same local IP-port combination (PR #61885)
  • The shell commands settings read and settings write now accept an optional ‘type’ argument. Ex:
settings write string foo bar
settings write hex key2 c0ffee

A big thank you to the 9 individuals who had their first pull request accepted this week, 💙 🙌: @raitraak-rrk, @kapbh, @iandmorris, @gwa-storck, @kunoh, @icsys-aal, @aaronyegx, @SawXu, and @TaiJuWu.

As always, please feel free to jump in with your thoughts or questions in the comments below. See you next week!

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 – Hello M5Stack Core2, Picolibc, et al.

This week, I am using the recently added support for M5Stack Core2 (thank you, Martin!) as an excuse to show you some pretty cool Zephyr tricks that I’m confident many of you didn’t know about 🙂

Before jumping right in, I want to say a big thank you to everyone who tuned in to the first Zephyr Tech Talk earlier this week. It was a lot of fun, there were tons of questions, and Mike was the perfect guest for this first episode.

On Wednesday, September 27, I will be chatting with Bjarki Arge Andreasen about the newly introduced modem subsystem, and I highly encourage you to sign up already to make sure you don’t miss this!

M5Stack Core2 is now supported, and why I find it extra cool

M5Stack Core2
M5Stack Core2
Did I mention the M5Stack Core2 is *packed* with on-board peripherals?

I am really excited that the support for M5Stack Core2 finally got merged this week. This is yet another great contribution from Martin Kiepfer and, similarly to the M5StickC Plus, I particularly like how this device is packed with on-board peripherals that happen to just work out-of-the-box in Zephyr.

I might record a longer demo video in the next few days, but in the meantime let me just show you three examples of why having out-of-the-box and full-blown support for the on-board peripherals is really neat:

  • The M5Stack Core2 features a power-management IC (PMIC), an AXP192, which is one of the supported regulators in Zephyr. It controls, among other things, the voltage being sent to the LCD backlight.
    Not sure what would be an appropriate brightness level for the LCD in your application? Curious about how low you can get until things are not really readable for your end-users anymore?
    Well, just use the built-in shell commands to interact with the regulator, and voila! No need to write custom test code and—maybe more importantly—no risk to fry your device since the min/max limits for all the power outputs are configured separately in the Devicetree.
uart:~$ regulator vget DCDC3
2.800 V
uart:~$ regulator vset DCDC3 2.5V
uart:~$ regulator vset DCDC3 3.3V
Why, yes, being able to interact with voltage regulators through shell commands is super convenient.
  • There is a real-time clock on board of the device (BM8563), connected to the main ESP32 over I2C.
    It’s of course a pretty useful companion for many applications where you need the date and. Again, not only is this particular RTC chip supported (so you can interact with it using the standard RTC API), but similarly to the regulator shell before you can, for example, easil set the date and time interactively, without having to write a single line of code for that.
uart:~$ rtc get pfc8563@51
uart:~$ rtc set pfc8563@51 2022-12-22
uart:~$ rtc get pfc8563@51
  • Last and certainly not least, the Core2 has an LCD display and a touch panel.
    I’ve mentioned it many times before but LVGL is an awesome tool for building embedded GUIs, and the fact that this particular device also has a touch interface makes it even more interesting, since LVGL input device interfaces and Zephyr’s input subsystem can work hand-in-hand. And as it seems to be all about shell awesomeness this week, here’s one more trick for you: the LVGL shell!
    It can be enabled using CONFIG_LV_Z_SHELL and it adds a couple commands that can be particularly useful for testing/troubleshooting your GUI. We all know that UI testing can be tricky, and even more so on embedded systems, and one such command allows you to enable an LVGL monkey which can be a great alternative to basically stress-test your UI and catch potential bugs, memory leaks, etc. Also, it’s super fun to watch, just see below!
uart:~$ lvgl monkey create pointer
Someone is really messing up with that touchscreen, eh? 🐵


This one is a pretty significant change! Picolibc is now the default C library for Zephyr.

Picolibc is a library offering standard C library APIs that targets small embedded systems with limited RAM.

In a nutshell, Picolibc brings even more modularity and configurability, making it easier to fine tune the footprint/performance of the C library. It’s also meant to bring you the best of both worlds between Zephyr’s minimal libc (small, but lacking too many features), and newlib (too heavy for most applications).

But frankly, I think I need to invite Keith, Picolibc’s author, to tell us more about it during an upcoming Zephyr Tech Talk (Keith, if you’re reading this… 😊).

You can of course still use CONFIG_LIBC_IMPLEMENTATION Kconfig to use another C library implementation.

Other boards & SoCs

Other boards added this week:

  • ESP32C3 LuatOS. Pretty nice to see more RISC-V boards, it had been a while! (PR #61915)
  • Raytac MDBT53-DB-40 and MDBT53V-DB-40 (PR #58841)


This week has been insane on the drivers front. Apologies if the list below is maybe not diving as deep as I typically try to into the specifics of each sensor as I usually do, but there’s just too much to cover this week. Hopefully the list below is a good and useful summary nevertheless.

  • Add support for devices of the ADC family MAX11102-MAX11117. (PR #60328)
  • TI TAS6422 is a two-channel audio amplifier for automotive applications (PR #59678)
  • TI BQ27z746 fuel gauge. (PR #59382)
  • TSL2540 ambient light sensor, a sensor that has, according to its datasheet, near photopic responsiveness (and yes, you too probably learned a word today!). (PR #59330)
  • When using RTC on STM32, it’s now possible to use calibration features (set_calibration / get_calibration), thanks to PR #62304, which also brings other fixes/improvements.
  • CAN-FD support has been added to ISO-TP, and the ISO-TP code sample has been updated accordingly. (PR #60323)
  • LPDAC (Low-Power Digital-to-Analogue Converter) support has been added for NXP LPCXpresso55S36. (PR #61459)
  • Native SD card support added for Microchip SAM4E MCU series (using ATMEL HSMCI peripheral). (PR #58233)
  • TI TCAN4x5x series of CAN controllers now supported, alongside the dedicated evaluation board, TCAN4550EVM. (PR #62033)
TCAN4550EVM (Credit: Texas Instruments)¶
  • Current sense amplifier driver, providing an easy way to describe a current sensing circuit hooked to an ADC, using some Devicetree magic, just see below. (PR #59139)
test_current: current_amp {
	status = "okay";
	compatible = "current-sense-amplifier";
	io-channels = <&my_adc_3>;
	io-channel-names = "CURRENT_AMP";
	sense-resistor-micro-ohms = <10>;
	sense-gain-mult = <1>;
	sense-gain-div = <1>;
  • It’s now possible to use NXP’s MU (Messaging Unit) as an MBOX device for inter-process communication.
  • Added support for Raspberry Pi Pico timer. (PR #57134)
  • KSCAN driver for Microchip now supports low-power mode. (PR #60806)
  • Driver for SSD1306 display now supports connections over SPI and I2C simultaneously. (PR #56887)
  • Driver for the BMM150 magnetometer now supports trigger mode. (PR #57985)


  • In addition to Bash and zsh, you can setup autocompletion for your West commands in fish shell. (PR #62477)
  • Added architectural support for shared interrupts. (PR #61422)
    I invite you to read this to learn more.
  • More LVGL goodness! PR #62141 introduces support for encoders as input devices. This can make for cool user interactions where you can e.g. use an encoder to focus on next/previous widget in the UI.
  • Wi-Fi shell keeps improving with PR #62201.

A big thank you to the 12 individuals who had their first pull request accepted this week, 💙 🙌: @electrocnic, @chuangzhu, @tswaehn, @andy3469, @likongintel, @Albort12138, @JPHutchins, @yclistanford, @vg-sc, @VivekUppunda, @wkhadgar, and @Emplis.

As always, please feel free to jump in with your thoughts or questions in the comments below. See you next week!

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: