Skip to main content

Zephyr Weekly Update – Multiplexing all the things!

By December 1, 2023No Comments

Howdy! Before diving into this week’s updates, I would like to take a minute to encourage you to have a look at the Call for Papers for two really good open source conferences where I would love to see lots of cool Zephyr content 😉

  • FOSDEM 2024, Feb. 3-4 in Brussels, Belgium—The CfP for the Embedded, Mobile and Automotive devroom closes a week from now, on December 8, so don’t wait to submit.
  • Zephyr Developer Summit 2024 (co-located with Embedded Open Source Summit), Apr. 16-18 in Seattle, WA— You have a bit more time for this one, but make sure to not miss the January 14, 2024 deadline if you are interested in speaking at the event!

Also, a quick plug for the next Zephyr Tech Talk live stream on Wednesday, December 6 (note: we’ll be going live one hour later than our usual time, at 2pm GMT).

I will be chatting with open source rockstar Keith Packard about Picolibc, and how it can help you make your Zephyr application faster and leaner. I am very much looking forward to this one and hearing tons of C trivia from Keith 🙂

You can register here to make sure you get a reminder when we’ll go live, and you may of course consider spreading the word with your network, it’s always much appreciated!

Device multiplexing

There are many (maybe too many!) interesting tricks that can be implemented on top of Devicetree, and it gives a lot of flexibility in describing and tweaking the capabilities of your hardware.

This week, a new device multiplexer pseudo-device has been introduced. In a nutshell, this gives you a way to have a node in your Devicetree that acts as a proxy for other devices.

A typical application for this would be to be able to dynamically change which UART to use as the Zephyr console. Another interesting use case would be to have the devmux act as that one accel0 accelerometer sensor you’re using in your code, except that you could easily switch back and forth between an actual sensor, and an emulated one, for example. And all of this without having to continually update your Devicetree, recompile it, and run it again.

A picture being worth a thousands word, here’s a diagram that summarizes what’s going on under the hood.

            +----------+                            +----------+
            |  devmux  |                            |  devmux  |
            |          |                            |          |
 dev0       |          |                 dev0       |          |
 +---------->          |                 +---------->          |
            |          |                            |          |
 dev1       |          |       dev0      dev1       |          |       dev2
 +---------->      O   +---------->      +---------->      O   +---------->
            |          |                            |     /    |
 dev2       |          |                 dev2       |    /     |
 +---------->          |                 +---------->   /      |
            |          |                            |          |
            |          |                            |          |
            |          |                            |          |
            +-----^----+                            +-----^----+
                  |                                       |
   select == 0    |                       select == 2     |
   +--------------+                       +---------------+

From a Devicetree perspective, and for a use case where you’d want to multiplex multiple UARTs, it would look like the below:

/ {
    chosen {
        zephyr,console = &devmux0;
        zephyr,shell_uart = &devmux0;
    &uart0 {
        status = "okay";
    euart0: uart_emul0 {
        compatible = "zephyr,uart-emul";
        current-speed = <0>;
        status = "okay";
    euart1: uart_emul1 {
        compatible = "zephyr,uart-emul";
        current-speed = <0>;
        status = "okay";

Memory attributes based allocator

When configuring memory regions in the Devicetree, one can use the zephyr,memory-attr property to specify some flags that can then be used at runtime. This may be used for example by some drivers to indicate that they won’t function properly if used with specific types of memory, e.g. a DMA driver may require the use of non-cacheable memory.

A recently added feature makes it possible to fine-tune the way memory can be allocated from the heap, to help you easily get the right type of memory for your use case.

When CONFIG_MEM_ATTR_HEAP is set, all memory regions marked with specific flags (ex. DT_MEM_SW_ALLOC_CACHE) are added to a pool of memory heaps from which one can then allocate memory from by requesting chunks of memory of the desired type.

// Init the pool

// Allocate 0x100 bytes of cacheable memory
block = mem_attr_heap_alloc(DT_MEM_SW_ALLOC_CACHE, 0x100);

// Allocate 0x200 bytes of non-cacheable memory aligned to 32 bytes
block = mem_attr_heap_aligned_alloc(ATTR_SW_ALLOC_NON_CACHE, 0x100, 32);

// Allocate 0x100 bytes of cacheable and dma-able memory
block = mem_attr_heap_alloc(DT_MEM_SW_ALLOC_CACHE | DT_MEM_SW_ALLOC_DMA, 0x100);

Adding support for recvmsg()

Zephyr’s BSD Sockets now implement proper support for the recvmsg() API.

As opposed to recv(), recvmsg() can be used with both connected (ex. TCP) and connection-less (ex. UDP) protocols to receive a message from an arbitrary network address.

When used alongside the IP_PKTINFO flag, it can also be useful to get additional information about an incoming packet, for example the address of the sender.

Check out PR #65694 for more details.

Boards & SoCs

  • Arduino has gone a long way since its beginnings as a protyping tool for interaction design students. There is now a plethora of Arduino products very much geared towards industrial applications, and Arduino OPTA is one of them.
    Based on an STM32H747XI dual-core Arm® Cortex®-M7 +M4 MCU, it is basically a highly capable PLC (Programmable Logic Controller), that includes high-power relay switches, Modbus TCP and RTU capabilities, and more.
    As of this week and PR #64101, the M4 core of the Arduino OPTA is now officially supported in Zephyr!
Arduino OPTA.
  • The NXP UCANS32K1SIC is a CAN signal improvement capability (SIC) evaluation board designed for both automotive and industrial applications that provides 2 CAN SIC interfaces and is based on a Cortex-M4F NXP S32K146 MCU. Now supported 🙂 (PR #65461)
  • The Renesas R-Car Spider board is the reference board for evaluating the Renesas R-Car S4 SoC family.
    Both the SoC and the board are now supported as of this week! (PR #56043)
  • The Waveshare Pico UPS-B shield is a UPS (Uninterruptible Power supply) module designed for the Raspberry Pi Pico.
    It communicates with the Raspberry Pi Pico over I²C and allows to transparently control the charge of its battery and use it to power the Pi. It just joined the list of supported shields in Zephyr. (PR #60384)


  • The recently added GNSS subsystem gets a new generic NMEA driver, that can be used with any source of NMEA frames.
    When you really only care about getting and decoding the raw NMEA data straight from your GPS receiver, and have no interest in tinkering with the module’s settings (or maybe it doesn’t even have any), then this driver will be your new friend. (PR #65422)
&uart0 {
          current-speed = <9600>;
          gnss: gnss-nmea-generic {
                  compatible = "gnss-nmea-generic";
  • I²C support added for Nuvoton Numaker. (PR #65673)
  • Added support for NXP TJA1103 Ethernet PHY. (PR #65756)
  • New experimental NXP ENET Ethernet driver. (PR #62833)


A big thank you to the 9 individuals who had their first pull request accepted this week, 💙 🙌: @ShaharHD, @kilejin, @boz, @timwoolliscroft-opteran, @marcowidmer, @Grin00, @borrelunde, @arkwad, and @adamfc2000.

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


Benjamin Cabé