Benjamin Cabé

Zephyr Weekly Update – Multiplexing all the things!

Zephyr Weekly Update - December 1, 2023

Zephyr Weekly Update - December 1, 2023

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 😉

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
mem_attr_heap_pool_init();

// 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 OPTA.

Drivers

&uart0 {
          current-speed = <9600>;
          ...
          gnss: gnss-nmea-generic {
                  compatible = "gnss-nmea-generic";
          };
  };

Miscellaneous


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!

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:

Exit mobile version