Skip to content

Instantly share code, notes, and snippets.

@oberstet
Created July 24, 2026 17:56
Show Gist options
  • Select an option

  • Save oberstet/41d33d3ab6c3175a555b290dd1ef9945 to your computer and use it in GitHub Desktop.

Select an option

Save oberstet/41d33d3ab6c3175a555b290dd1ef9945 to your computer and use it in GitHub Desktop.

This is a great concrete example because it gets to a point where "Zenoh runs on microcontrollers" needs some unpacking. The interesting question is not whether Zenoh can run on an MCU, but where you put the Zenoh endpoint and how you bridge between your real-time application core and the networking core.

Your MCXN947 scenario is actually very similar to architectures used in industrial MCUs and heterogeneous SoCs:

                 MCU
+--------------------------------+
|                                |
|  Core 1                        |  Core 0
|  (application)                 |  (communications)
|                                |
|  Bare metal C                  |  Ethernet stack
|  Hardware control              |  Zenoh client/router
|                                |
|       |                        |
|       | shared memory IPC      |
|       | + interrupts           |
|       v                        |
|                                |
+--------------------------------+

             |
             |
          Ethernet
             |
             v

        Zenoh network

The key question is: does the Zenoh session live on Core 1 or Core 0?

There are several possible designs.


Option 1: Zenoh on Core 0, custom IPC bridge to Core 1 (likely best fit)

This is probably what you would do if you want minimal changes to the bare-metal application.

Core 1 keeps doing:

void control_loop()
{
    read_sensors();
    update_actuators();
}

You add a very thin IPC layer:

publish_sensor_data(value);

which writes into the shared-memory queue.

Core 0 runs:

Shared memory IPC adapter
          |
          v
       Zenoh API
          |
          v
       Ethernet

Conceptually:

Core 1 application
        |
        | "sensor.temperature = 42"
        |
        v
 IPC message queue
        |
        v
Core 0 Zenoh bridge
        |
        v
zenoh_put("sensor/temperature", data)

The bare-metal code never knows about Zenoh.

This is architecturally very similar to how people use:

  • DDS-XRCE agents
  • ROS 2 micro-ROS agents
  • CAN/Ethernet gateways
  • industrial fieldbus gateways

The communication core becomes a Zenoh gateway.


Option 2: Native Zenoh-Pico on Core 1

Zenoh does have a small-footprint implementation:

Eclipse Zenoh provides zenoh-pico, aimed at constrained devices.

The idea is:

Core 1
+----------------+
| Application    |
|                |
| Zenoh-Pico     |
+----------------+
        |
        |
   Ethernet / UDP /
   shared transport

Advantages:

  • no custom bridge
  • direct participation in Zenoh
  • less latency

Disadvantages:

  • your bare-metal application now depends on:

    • Zenoh APIs
    • memory management requirements
    • networking integration
    • timing behavior

For a safety-critical motor-control loop, you might not want that.


Option 3: Zenoh over the inter-core transport

This is the interesting hybrid case.

Zenoh itself has the concept of transports and links. In principle, the communication path could look like:

Core 1
Zenoh endpoint
     |
     |
shared-memory transport
     |
     |
Core 0
Zenoh router/session
     |
     |
Ethernet

The MCU becomes a single Zenoh node from the outside.

This is closer to the "native" Zenoh model.

The caveat is that the inter-core transport has to be implemented as a Zenoh transport/link, or you need an adapter layer. The shared-memory queue is not automatically a Zenoh transport just because the hardware provides it.


How does this compare with WAMP?

This example is actually where the earlier discussion gets interesting.

A WAMP architecture would likely look very similar:

Core 1
bare metal C
    |
    | IPC
    |
Core 0
Crossbar/Autobahn component
    |
    |
WAMP
    |
Ethernet

The difference is what the endpoint abstraction is.

With WAMP, Core 0 exposes:

  • procedures
  • events
  • topics

Example:

device.temperature
device.set_motor_speed()
device.get_status()

With Zenoh, Core 0 exposes:

  • key expressions

Example:

device/temperature
device/motor/speed
device/status

The engineering pattern is almost identical.


The "deep embedded" nuance

This is where I would slightly refine my earlier wording.

When people say "Zenoh runs on deeply embedded devices", that usually means:

The Zenoh protocol stack can be made small enough to run close to constrained hardware.

It does not necessarily mean:

Every piece of application logic should directly call Zenoh APIs inside a hard real-time bare-metal loop.

In many embedded designs, the best architecture is:

real-time domain
       |
       | deterministic IPC
       |
communication domain
       |
       | Zenoh
       |
network/cloud

which is exactly the kind of architecture your MCXN947 example naturally suggests.


Where I think Zenoh is particularly interesting here

The place where Zenoh has an advantage over many older messaging systems is that the communication-core firmware can become a distributed data endpoint, not just a protocol gateway.

For example:

Core 1 publishes:

robot/joint/1/position

Core 0 can:

  • forward it live
  • store it
  • answer queries about historical values
  • aggregate it

without Core 1 changing.

That "data fabric" model is quite compelling.


But your "touch bare metal C as little as possible" requirement changes the answer

For that specific requirement, I would probably rank the options:

  1. Core 0 Zenoh gateway + shared-memory IPC

    • least invasive
    • keeps real-time code isolated
    • easiest certification story
  2. Native Zenoh-Pico on Core 1

    • cleaner architecture
    • more invasive
  3. Zenoh transport over IPC

    • elegant
    • probably the most work initially

And interestingly, this is also exactly where a WAMP/Crossbar architecture would be very competitive: the "communication core as a gateway, application core untouched" pattern is not unique to Zenoh.

The real differentiator would then shift back to the earlier discussion: data-centric Zenoh namespace/query model vs. application-centric WAMP session/RPC model.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment