Hi all,
We’ve been working on Eclipse zenoh-pico support for the Cortex-R5F core of the TI AM67A (J722S) and wanted to share the results here, since the same silicon is used on the BeagleY-AI. The work was done on the T3 Gemstone O1 board, but the platform layer sits at the SoC level rather than the board level.
Upstream PR: eclipse-zenoh/zenoh-pico#1271
The problem: no Ethernet on the R5F
If you want a pub/sub middleware running on the R5F, the obvious route is CPSW + lwIP. But in most realistic system designs the Ethernet MAC/PHY is already owned by Linux on the A53 cluster, or the board simply doesn’t expose a second PHY. Handing CPSW to the R5F means taking it away from Linux — usually a non-starter.
So instead of giving the R5F its own PHY, we gave it a virtual Ethernet link over RPMsg IPC. From zenoh-pico’s point of view nothing changes: it still talks UDP multicast over lwIP. The difference is that Ethernet frames travel through shared DRAM VRINGs instead of over a wire.
R5F (FreeRTOS) Linux A53
────────────── ─────────
zenoh-pico zenoh router / peer
│ UDP/IP │ UDP/IP
lwIP netif (rp0) rpmsg0 (virtual Ethernet)
│ Ethernet frames │
rpmsg_lwip_netif.c rpmsg_net.ko
│ RPMessage_send/recv │ rpmsg_endpoint
└──────── VRING shared DRAM ──────────────┘
(0xA2000000, non-cached)
On the Linux side, an out-of-tree kernel module (rpmsg_net.ko) exposes a standard netdev called rpmsg0. The R5F firmware announces the "rpmsg-enet" service at boot; the module matches on that name and probes the device. After that it’s ordinary networking — ip addr add, ip link set up, and you can ping the R5F.
Both transports are selectable at build time:
| Mode | CMake flag | Hardware needed | Linux side |
|---|---|---|---|
| CPSW Ethernet (default) | (none) | CPSW PHY + cable | standard IP routing |
| RPMsg IPC | -DZENOH_TI_AM67A_IPC=ON |
none (shared DRAM) | rpmsg_net.ko |
Three examples are included — z_pub, z_sub, z_pubsub — all running in peer mode over UDP multicast, so no router is strictly required. zenohd on the A53 also works if you want to bridge out to the rest of the network.
Constraints worth knowing
- MTU is 478 bytes. The default VirtIO VRING buffer is 512 B → RPMsg payload max 496 B → IP MTU 478 B (496 − 14 ETH_HLEN − 4 FCS). zenoh-pico’s
Z_FEATURE_FRAGMENTATION=1handles larger messages transparently, so this is not a hard ceiling on payload size, but it does mean more fragments per sample than you’d get on real Ethernet. - VRING carveout must match the DTS. We use
0xA2000000, matchingmain-r5fss-dma-memory-region@a2000000in the J722S device tree. Different DTS → updateCONFIG_MPU_LINUX_IPC.baseAddrin the SysConfig file. - MPU attributes must be
NonCached(tex=1), notDevice(tex=0).DCCIMVACcache maintenance is architecturally UNPREDICTABLE on Device memory, which makes both the VRING and the trace buffer invisible to Linux.
Two silent failure modes
These are AM67A/MCU+ SDK issues rather than zenoh issues, so they may be useful to anyone doing R5F + lwIP work. Both fail without a diagnostic, which is what makes them expensive:
trace0stays empty whilevirtio0: rpmsg host is onlinelooks healthy. With SysConfig’s defaultenableCssLog = true, the generatedputchar_()calls the C stdlibputchar()before writing to the trace buffer. On bare metal without a JTAG debugger, that triggers ARM semihosting (BKPT #0xAB) and hangs the firmware, with no output to tell you so. SetenableCssLog,enableUartLogandenableSharedMemLogall tofalse.pbuf_allocfailures dropping ARP and SCOUT packets. The SDK’slwipopts.hsetsPBUF_POOL_SIZE = 0because the CPSW driver uses custom DMA pbufs. A software-copy receive path has to allocatePBUF_RAMinstead ofPBUF_POOL.
Also worth a mention: the TI SDK builds lwIP with LWIP_TCPIP_CORE_LOCKING = 1, so calls into lwIP internals from outside tcpip_thread need LOCK_TCPIP_CORE(). Less of a trap than the two above — the assertion tells you exactly what’s wrong — but it will bite you if you’re wrapping netif_find().
There’s a fuller troubleshooting table in the example README, including the #iface=rp0 locator requirement and the zenohd -l ... EADDRNOTAVAIL trap.
Links
- Fork / working branch: GitHub - t3gemstone/zenoh-pico: Eclipse zenoh for pico devices · GitHub
- Example + full build instructions:
examples/ti_am67a/README.md - Upstream PR: New Platform Support: T3 Gemstone O1 (Texas AM67A) by gemstonedevteam · Pull Request #1271 · eclipse-zenoh/zenoh-pico · GitHub
rpmsg-netkernel module: GitHub - t3gemstone/rpmsg-net: RPMsg Virtual Ethernet Driver · GitHub- Roadmap notes: Roadmap - T3 Foundation Gemstone Project
Toolchain used: MCU+ SDK (J722S) 11.02.01, TI ARM Clang 3.2.2.LTS, SysConfig ≥ 1.26.2 (tested 1.28.0), CMake ≥ 3.20.
