As we mark the 8th anniversary of the Zephyr Project’s launch, I am thrilled to announce the release of Zephyr 3.6.0 today, a milestone made possible by the contributions of nearly 2,200 individuals since the project’s inception, including 538 contributors for this release alone.
I always like to start these announcement posts with a quick refresher about Zephyr. Zephyr is an open source real-time operating system (RTOS) that is designed to be small, scalable, and secure. It is used to build products in a wide range of industries, from consumer electronics to industrial automation, and from medical devices to smart agriculture. Zephyr is a Linux Foundation project, and is supported by a vibrant community of contributors, maintainers, and users.
One thing that makes Zephyr quite unique as an open source RTOS project, is how the community is organized to ensure that the project is always moving forward, with no vendor lock-in and a clear governance ensuring a level playing field for all contributors. This might sound like a detail—after all, if the code is open source, what more do you need?—but in practice, it makes a big difference in terms of the project’s ability to stay relevant, and to keep attracting new contributors and users!
During the past four months, the project has seen a number of significant changes and improvements, which I encourage you to check out in the detailed release notes. Some of the highlights are detailed in the rest of this article, and the following video also gives you a tour of Zephyr 3.6 through a few demos and some neat tips that should make your life as a Zephyr developer easier!
As you read through the article, clicking on the ▶️ symbol will directly take you to the section of the video that shows the feature in action.
Please also consider attending our special Zephyr Tech Talk episode next Wednesday (Feb. 28, 2024) where we will have several contributors and maintainers discussing the release and answering all your questions!
Without further ado, let’s dive into some of the noteworthy changes and additions in Zephyr 3.6.
New & Noteworthy
▶️ GNSS
Zephyr 3.5 introduced a generic infrastructure for implementing “modem” drivers. It drastically simplifies the implementation of the code associated with crafting the commands and parsing the responses when chatting with a modem (AT commands nostalgia anyone?). This new modem subsystem is actually a perfect foundation for other devices using similar communication interfaces, such as GNSS (Global Navigation Satellite System) receivers. Zephyr 3.6 introduced a new GNSS subsystem, built on top of the modem subsystem, that provides you with a way to easily integrate GNSS receivers into your Zephyr application.
Virtually any GNSS receiver that “speaks” NMEA 0183 is supported, and can easily be configured via Devicetree, with an equally easy way to declare what callbacks in your code should be invoked when a new fix/location is available.
▶️ Keyboard matrices
Zephyr now supports keyboard matrices, with a direct integration with the input subsystem.
A keyboard matrix is a way to connect a large number of keys to a microcontroller using a small number of pins (typically one pin per row and one pin per column in the matrix). A new GPIO keyboard matrix driver has been added and supports a large variety of keyboard matrix hardware configurations, with support for both polling and interrupt-based scanning.
▶️ Introducing support for Link-Time Optimization (LTO)
While a Zephyr application typically ends up being packaged as a single binary, it is obviously made up of a large number of intermediate object files, from your application code, to the Zephyr kernel, HALs, and all other modules your application depends on. Link-Time Optimization (LTO) is a compiler feature that allows the compiler to optimize the entire program at link time, rather than just the object files individually. This can lead to significant performance and code size improvements, and it is really great to see that Zephyr 3.6 now supports LTO. Enabling LTO is as simple as enabling the CONFIG_LTO
and CONFIG_ISR_TABLES_LOCAL_DECLARATION
Kconfig options, and the build system will take care of the rest.
▶️ Making LLEXT easier to use
Unveiled with Zephyr 3.5, Linkable Loadable EXTensions (LLEXT, in short) are a new way to dynamically load and execute binary code from a Zephyr application. While updates to an embedded application are often done by re-flashing the entire application, LLEXT provides a way to load and unload code modules at runtime, which can come in handy for a variety of use cases. Think, updating a TinyML model, deploying updates to a GUI, etc..
Under the hood, an LLEXT extension is nothing more than a relocatable ELF file, which the LLEXT subsystem can parse and load into memory. In order to make the generation of LLEXT extensions easier, a new CMake extension, add_llext_target
(), has been introduced. Alongside other helpers and macros, it is making it really easy for developers to expose and package functions in the form of LLEXT modules, and have them built as part of the Zephyr build system they are used to.
SBOM
Zephyr’s build system includes a tool to help generate the Software Bill of Materials (SBOM) for a Zephyr application. The SBOM is a list of all the software components that are used in a given application, and is a key part of the software supply chain security. Think of it as a snapshot of all the dependencies of your application that you can use to track what you are using, and to ensure that you are not using any components with known vulnerabilities, both when you are developing your application, and when it is deployed in the field and new vulnerabilities are discovered.
Ahead of the next Long-Term Support (LTS) release of Zephyr coming out later this year, work has been done in the 3.6 version to augment the SBOM with the list of Zephyr modules making up an application, and they are now properly captured as “packages” during the SPDX generation.
Future improvements will make it possible for Zephyr modules to actually indicate their CPE (Common Platform Enumeration) identifier (ex. cpe:2.3:a:arm:mbed_tls:3.5.1:*:*:*:*:*:*:*
) or a package URL using PURL notation (ex. pkg:github/Mbed-TLS/mbedtls@v3.5.2
), which will make it easier to track vulnerabilities in the future.
User space now supported on Xtensa
When building a Zephyr application, you can now choose to build it as a user space application, which means that the application will run in a separate memory space from the kernel. This is a great way to isolate the application from the kernel, and to ensure that a bug in the application—or a malicious application—cannot access or corrupt the kernel objects or memory.
User space mode is already supported on a variety of architectures by means of leveraging MMU (Memory Management Unit) and MPU (Memory Protection Unit) hardware features. Zephyr 3.6 added support for user space on the Xtensa architecture. It is using MMU only at the moment, but MPU support for Xtensa is shaping up as I am typing this.
▶️ Networking goodness
I am always impressed to see how the team looking at the networking stack in Zephyr is always game to take on significant refactoring work to address technical debt and keep the stack and its API relevant… and Zephyr 3.6 is no exception!
Two new services have been introduced to simplify the implementation of services on top of both plain sockets as well as CoAP. These services help get rid of the “boilerplate” code that is typically associated with writing new network services and, more importantly, helps share resources across the different service instances (ex. all socket-based network services may be processed in a single thread).
The new DHCPv4 server, built atop the socket service, is a great reference to familiarize yourself with the new service API.
New display drivers for modern displays
Zephyr has quite a rich offering of display drivers, and Zephyr 3.6 is adding support for a few more modern displays, such as the Galaxy Core GC9A01A display controller, used to drive the kind of round LCD displays you would find in e.g. smart watches.
Another noteworthy change on the display front is the addition of a new API for MIPI Display Bus Interface (DBI), a standard serial interface for communicating with display controllers.
▶️ Hello (again!) C++ World
I get asked about it quite often so I thought I should mention it here: yes, you may write your Zephyr applications in C++! It has been possible pretty much from day one, and enabling C++ support in your application is basically as simple as enabling the CONFIG_CPP
Kconfig option 😉
I want to call out the newly introduced “Hello C++ World” code sample, as it is a great reminder that Zephyr is not just for C developers, and whether you feel more comfortable in C++, don’t mind the potential overhead of C++, or are just looking to leverage some of the great C++ libraries out there, feel free to use it as a starting point for your next project!
… and so much more
Again, there is a lot more to Zephyr 3.6 than what I tried to summarize here: please check out the full release notes, and don’t forget the accompanying migration guide that will help you transition to 3.6 smoothly.
Speaking of documentation, you will probably be happy to hear that we’ve added a Google-powered search engine to the documentation (▶️) that makes it a lot easier to find relevant information. Please use and abuse it!
Meet our release managers for Zephyr 3.6
Zephyr 3.6 once again broke a record in terms of contributors—over 530 contributors helped shape this release, with a good third of them being first time contributors. A big thank you from my side, on behalf of the entire Zephyr community, to all of you who helped make this release happen!
There are two people in particular that deserve a special mention, for they’re the ones who are responsible for the release actually happening on time, and free of major issues. Maureen Helm and Henrik Brix Andersen were the release managers for Zephyr 3.6, and I have asked them to share a few words about what they are the most excited about in this release:
”As my first time serving as release engineer, it was amazing to witness the full community come together, collaborating to provide yet another high-quality release of the Zephyr RTOS.
It never ceases to amaze me that a community as diverse as ours, scattered among a large number of companies and individuals, still manages to work coherently on everything from bug fixes, exciting new features, tooling and documentation improvements.One of my personal favorites of this release is the shift from native_posix to native_sim as the default, native test platform. The native_sim platform allows compiling against embedded C-libraries instead of using the host's C-library, which brings tests much closer to how Zephyr applications are usually built and deployed.
Another exciting, new feature is the introduction of a MIPI Display Bus Interface (DBI) driver class. While we've only just seen the very first display driver migrated to use this new driver class, I trust we will see much more of these conversions towards v3.7.0 and hopefully even more displays supported by Zephyr in future releases.
Henrik Brix AndersenVestas
”It's exciting to see every Zephyr release get bigger than the one before, but with that growth comes additional complexity in coordinating releases. The introduction of an experimental merge queue to identify which pull requests satisfy merge criteria (and which ones don’t) was a game changer for the release team. The documented policy of requiring assigned maintainer approval and minimum time under review has historically been difficult to enforce, but now we can more easily find pull requests that satisfy these requirements and merge them sooner.
In this release, we merged almost 3x as many commits compared to my first release serving as release manager!
Maureen HelmAnalog Devices
If you enjoyed this article, don’t forget to subscribe to the Zephyr newsletter to receive insightful quarterly updates about all things Zephyr! You can also follow us on Twitter and LinkedIn.