IoT Zephyr

Zephyr Weekly Update – Introducing the new modem subsystem

The Zephyr community is back to pretty much full-speed as the summer break comes to an end, and this week’s Zephyr update features a new, highly-anticipated, modem subsystem.

In other news, and before announcing this more formally next week, we are launching a new series of YouTube live streams, the Zephyr Tech Talks, starting September 13, and I hope many of you will join us!

Our first guest will be Mike Szczys, and he will be telling us all about taking the continuous integration and testing of Zephyr-based projects to the next level using actual hardware. Just click that notification bell on YouTube to make sure you don’t miss it (or you’ll be able to catch up the replay, don’t worry)!

I am looking for folks from the community to join us on the show and chat about some cool Zephyr/embedded topics so feel free to submit your ideas here to participate in future sessions!

New modem subsystem

It’s not often that nearly 10,000 of lines of code get contributed, so I really hope to do justice to this awesome contribution coming from Bjarki Arge Andreasen! Without further ado, let me introduce the new modem subsystem (PR #56692)

You may know that Zephyr already provides drivers for a handful of modems (cellular, not RTC, despite the cheesy GIF above 😊). However, current modem support has been somehow constrained by Zephyr’s device driver model, as it lacks the flexibility that would allow to accommodate the wide-ranging features of modern modems.

The newly introduced modem subsystem implements concepts coming from the Linux world such as chat and pppd, and a CMUX module to make the whole stack more modular (indicating whether you talk to the modem over UART or, say, IPC should be as simple as changing KConfig, right?), easier to test, and overall more efficient.

  • chat allows to handily “script” interactions with modems, and to model how the typical request/responses for dial-up, hang-up, etc. sequence. This helps remove a lot of the boilerplate code typically associated with parsing AT commands. See for example the dial script for a standard GSM modem:
			      MODEM_CHAT_SCRIPT_CMD_RESP_MULT("AT+CGACT=0,1", allow_match),
			      MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=1", ok_match),
			      MODEM_CHAT_SCRIPT_CMD_RESP_NONE("ATD*99***1#", 0),);
  • pppd abstracts and isolates the lower-level tasks associated with managing a PPP (Point-to-Point Protocol) session (authentication, IP address negotiation, etc.)
  • CMUX provides a way to have multiple data channels on a single serial bus (i.e. the one used between the application processor and the modem). For example CMUX is what makes it possible for a modem to be able to receive SMS messages while having a voice or data channel active at the same time.

And if you’re only interested in all of this as an end-user, and not someone who might potentially need to write their own modem driver in the near future, then you’ll probably still be interested in hearing that this new architecture consumes about 30% less RAM (~12KB) than before 🙂

I highly encourage you to try out the newly added Cellular Modem code sample, which shows everything in action, and how well it integrates with existing Zephyr concepts:

  • Powering on the modem, using device power management API pm_device_action_run(modem, PM_DEVICE_ACTION_RESUME) ;
  • Bringing up the network interface, using network interface API (net_if_up(net_if_get_default())) and network management API ;
  • Talking to an Internet server over UDP using standard BSD sockets ;
  • Power-cycling the modem to demonstrate how the network management stack automatically re-establishes the connection to the network.

Boards & SoCs

  • Support for the STM32F765xx series of SoC has been introduced. (PR #62055)
  • A new QEMU board definition for Xtensa Diamond DC233 has been added, which is particularly useful for testing all things MMU on Xtensa. (PR #61864)


  • New driver for the Fujitsu MB85RC FRAM. In case you’re not familiar with FRAM (Ferroelectric RAM), it is a type of non-volatile memory that combines the fast read and write access of dynamic RAM (DRAM) with the ability to retain data when power is removed, similar to flash memory. (PR #61653)
  • You can now monitor on-die operational temperature for NXP SoCs with a Temperature Monitor Module (TEMPMON). (PR #61119)
  • The USART driver for STM32 now supports wide data, and you can now use a word length of 9 bits when CONFIG_UART_WIDE_DATA is set. (PR #54354)
  • Battery-backed RAM can now be accessed from user threads. (PR #61869)
  • Various bug fixes and enhancements in INA237 and INA230 drivers should make for a much better experience if you’re using these power monitors from TI in your Zephyr projects. (PR #60717)
  • New GPIO controller for TI DaVinci family of SoCs. (PR #61316)
  • Added PWM support for Nuvoton NuMaker series.(PR #61469)


  • The newly introduced CONFIG_NET_INTERFACE_NAME Kconfig option allows applications to give network interfaces a name in order to simplify network interface management. (PR #61876)
  • When using DTLS, you can now use CONFIG_MBEDTLS_SSL_DTLS_CONNECTION_ID to enable the DTLS Connection ID (CID) extension in Mbed TLS. This allows to identify DTLS connections across changes that may occur in the underlying transport. (PR #61483)


Last week I mentioned the line-up of nice improvements currently being made or about to be made to LVGL support in Zephyr.

A nice addition this week are the new zephyr,input-button-lvgl and zephyr,input-pointer-lvgl bindings. What they mean for you is that you can now declare in your Devicetree that a given input device should also act as an LVGL input device. The most straightforward application would be to convert a touch event on a touchscreen into a proper LVGL input event, but this can also be useful to map input keys to “virtual” touch events.

  Example configuration:

  pointer {
          compatible = "zephyr,lvgl-button-input";
          input = <&buttons>;
          input-codes = <INPUT_KEY_0 INPUT_KEY_1>;
          coordinates = <120 220>, <150 250>;

  When the device receives an input_event with code INPUT_KEY_0
  a click event will be performed at (120,220).

In practice, the underlying driver the underlying driver takes care of capturing the input events (ex. a touch screen), and exposes the Zephyr input device as a standard LVGL input device. (PR #60867)


demo_tag [00:00:01.165,204] <err> [log_demo_thread_id] main: Error message example.
demo_tag [00:00:01.165,230] <wrn> [log_demo_thread_id] main: Warning message example.
demo_tag [00:00:01.165,258] <inf> [log_demo_thread_id] main: Info message example.
  • A couple of new POSIX functions have been added:
    • clock_nanosleep(), which allows the calling thread to sleep for an interval specified with nanosecond precision. (PR #61671)
    • pthread_condattr_*() functions, to properly handle the attributes object of a condition variable. (PR #61926)

A big thank you to the 11 individuals who had their first pull request accepted this week 💙 🙌: @ickochar, @rahul-arasikere, @mdwt-ot, @robertkowalewski, @TomFinet, @tbitcs, @n1zzo, @rghaddab, @Durchbruchswagen, @almir-okato, and @mariopaja.

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 – Scan away with me

I hope everyone had a great week! After a pretty massive heat wave in Southern Europe this week, it’s time to put together this week’s recap of Zephyr news. Not an awful lot, but some pretty cool topics nevertheless! As always please feel free to yell at me if you feel I forgot something important!

Zephyr docs get a major speed boost!

Recent tweaks in the configuration of the Zephyr documentation server are making it up to 5x faster.

This should make for a huge boost in your overall user experience when browsing the documentation, especially if your Internet connection speed is a bit average. Please let me know in the comments if it’s making an improvement for you, and feel free to share other feedback regarding the documentation in general!

Enhanced Wi-Fi management capabilities

The Wi-Fi management API now provides the ability to perform advanced scanning operations, for example to only scan on a particular band and/or channel range. The best way to start tinkering with the newly added functionalities is probably to use the wifi scan shell command. (PR #60686)

 Scan for Wi-Fi APs

    [-t, --type <active/passive>] : Preferred mode of scan. The actual mode of scan can depend on factors such as the Wi-Fi chip implementation, regulatory domain restrictions. Default type is active.
    [-b, --bands <Comma separated list of band values (2/5/6)>] : Bands to be scanned where 2: 2.4 GHz, 5: 5 GHz, 6: 6 GHz.
    [-a, --dwell_time_active <val_in_ms>] : Active scan dwell time (in ms) on a channel. Range 5 ms to 1000 ms.
    [-p, --dwell_time_passive <val_in_ms>] : Passive scan dwell time (in ms) on a channel. Range 10 ms to 1000 ms.
    [-s, --ssids <Comma separate list of SSIDs>] : SSID list to scan for.
    [-m, --max_bss <val>] : Maximum BSSes to scan for. Range 1 - 65535.
    [-c, --chans <Comma separated list of channel ranges>] : Channels to be scanned. The channels must be specified in the form band1:chan1,chan2_band2:chan3,..etc. band1, band2 must be valid band values and chan1, chan2, chan3 must be specified as a list of comma separated values where each value is either a single channel or a channel range specified as chan_start-chan_end. Each band channel set has to be separated by a _. For example, a valid channel specification can be 2:1,6-11,14_5:36,149-165,44
    [-h, --help] : Print out the help for the scan command.

Boards & SoCs

ESP32S3-CORE from LuatOS
  • A new ESP32S3-based developer kit is supported, the ESP32S3-CORE from LuatOS. My Chinese knowledge being more than limited, I don’t have a lot of details on this board, but LuatOS is apparently an open source project aimed at enabling Lua on constrained devices (16K RAM, 128K Flash). I don’t know if the LuatOS framework runs Zephyr under the hood, but I guess it’s now a possibility on the ESP32S3-CORE at least!


  • If you are using the fuel gauge driver API, it now has support for battery cutoff (PR #61435). The main application for this functionality (also referred to as ship mode or shelf mode) is to help reduce battery drain while devices are stored.
  • The driver for nPM1300 PMIC now supports trigger mode. This is particularly useful to treat events such as “battery removed”, or “charge completed” as actual interrupts in your system. (PR #60677)
  • The newly added regulator-gpio driver introduces basic support for controlling a regulator using GPIOs (ex. 1 pin sets output voltage to X, another pin sets it Y, and another pin allows to enable/disable it). The documentation for the regulator-gpio binding actually does a great job of explaining the concept. (PR #58411)
  • On NXP S32 boards, the GPIO driver now allows you to use the pin_get_config() and port_get_direction() APIs. (PR #61590)

A big thank you to the 8 individuals who had their first pull request accepted this week, 💙 🙌: @bene42, @nguyenmthien, @butok, @danielstuart14, @andrmuel, @LuskeyNoah, @laroche, @sachinthegreen.

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

Enabling CodeChecker for your Zephyr RTOS Project

Last week, when putting together my weekly Zephyr update, I spent some time recording a short(ish!) demo of how to run CodeChecker against your Zephyr RTOS project. This static code analysis tool is really impressive, and very good at spotting “smells” in your code base. Check it out, and let me know if you have any questions!

Note: Since I recorded the video, a new option has been added to directly upload results to a CodeChecker server (similar to what I demo in the video, except that I am doing this step manually)!
To use it, just pass the CODECHECKER_STORE=y CMake option when running the build, and you will be all set.