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.
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.
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.
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.
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.
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.
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.
For that specific requirement, I would probably rank the options:
-
Core 0 Zenoh gateway + shared-memory IPC ⭐
- least invasive
- keeps real-time code isolated
- easiest certification story
-
Native Zenoh-Pico on Core 1
- cleaner architecture
- more invasive
-
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.