How Does Rosette Put an RP2350 + W5100S Board on a ROS 2 Network Without a micro-ROS Agent?
Rosette runs a DDSI-RTPS stack and rmw_rosette on bare-metal RP2350, using W5100S hardware UDP sockets so stock Fast DDS sees the board as a ROS 2 node.
0
Project description
📚 Context: CenteredSolutions/Rosette — a DDSI-RTPS 2.5 stack and rmw implementation for microcontrollers. A stock rclc program on a WIZnet EVB board joins a ROS 2 network directly, next to Fast DDS and Cyclone DDS nodes.
01 — What changes without the agent

With micro-ROS, the agent on a host joins DDS for the board. Rosette puts RTPS on the board itself. The firmware is an unmodified rclc program linked against rmw_rosette. Stock rcl and rclc are still built with micro_ros_setup's generate_lib, but rmw_microxrcedds is never linked.
| Proven (README) | Where |
|---|---|
| Topics and services both ways with stock rmw_fastrtps_cpp (Humble) | interop harness |
| ros2 node list / node info show Rosette nodes | same harness |
| rclc on RP2350 + W5100S, no RTOS, rcl heap steady at about 4 KB | W5100S-EVB-Pico2 |
| 64 KB messages through a link that drops datagrams over 1472 B | fragmentation harness |
| DHCP, IPv6 link-local and SLAAC, UDP echo | W6100-EVB-Pico |
02 — The chip and the boards
Rosette does not use ioLibrary. It has its own header-only driver, WiznetDevice<Chip, Bus> in ports/net/wiznet/, and on a board the network is the chip's hardware UDP. The board CMake states the result: no RTOS, a cooperative superloop.
| Item | W5100S-EVB-Pico2 |
|---|---|
| Bus | SPI0, mode 0, 31.25 MHz, blocking |
| Interrupt | INT on GPIO21; 2 ms polling without it |
| MAC | 00:08:DC + 3 bytes of the RP2350 unique ID |
| Address | DHCP (hostname option); link-local after 15 s, retry every 60 s |
| Board | State |
|---|---|
| w5100s-evb-pico2 (RP2350) | ROS examples run against stock ROS 2; default board on every host except macOS |
| w6100-evb-pico (RP2040) | dual-stack UDP echo runs; ROS examples build |
| w6100-evb-pico2, w6300-evb-pico2, w5100s-evb-pico | build |
03 — Four sockets, three for RTPS

- RTPS holds three sockets for the life of the participant. DHCP and SNTP borrow the fourth only during an exchange; the DHCP client's header notes this "matters on a chip with four hardware sockets".
- RX memory is tilted toward user data. A socket that needs more calls
set_receive_buffer_size()beforebind(). - When a full 4096-byte sample outgrows the 4 KiB buffer, the reader recovers the lost fragments with NACK_FRAG one heartbeat later.
04 — Multicast and ARP on the chip
The SPDP group socket is configured in device.hpp before it is opened:
write(Chip::socket_dest_hardware(socket), group_mac.data(), group_mac.size());
write(Chip::socket_dest_ip(socket), group.data(), group.size());
write_u16(Chip::socket_dest_port(socket), group_port);
write_u8(Chip::socket_mode(socket),
static_cast<uint8_t>(Chip::mode_udp() |
Chip::mode_multicast() |
Chip::mode_igmp_v2()));| Chip behaviour | How Rosette handles it |
|---|---|
| Multicast membership is latched at OPEN | join the group before bind() |
| A multicast address has no ARP answer | W5100S: SEND_MAC with the group MAC in Sn_DHAR. W6100/W6300: Sn_MR2 manual destination MAC |
| Inline ARP to a silent peer stalls a send for about 1.8 s | own ARP cache, MAC handed to each send, unknown hops resolved in the background |
| Same Sn_DIPR on reopen skips ARP and reuses an old MAC | Sn_DIPR cleared on reopen |
| Some Wi-Fi APs and managed switches drop multicast | the network notes call a wired switch "the reliable setup" |
05 — 1472 bytes, no IP reassembly

| Direction | Handling |
|---|---|
| Board → peers | samples split into DATA_FRAG at 1472 B (IPv4) or 1452 B (IPv6) |
| Repairs to the board | one missing change per ACKNACK, so each repair is a single DATA |
| Large samples from stock peers | cap Fast DDS maxMessageSize on the peer |
RMW_ROSETTE_STRICT_LINK=1 makes a host drop every datagram over the limit, so the host tests face the board's losses against real stock traffic.
06 — No heap, measured footprint
The RTPS core and rmw_rosette never call malloc or new; every pool is sized at build time, so running out of room shows up at boot, not after a week in the field.
| W5100S-EVB-Pico2, RP2350, -O3 | Flash | Static RAM |
|---|---|---|
| rtps_chatter (RTPS core) | 204,488 B | 62,836 B |
| rclc_chatter, default capacity | 285,236 B | 99,816 B |
| rclc_chatter, sized to what it creates | 279,108 B | 63,980 B |
| Scale (design note) | Value |
|---|---|
| Target network | 70–90 participants: dozens of controller boards plus camera, perception and control nodes |
| Peer table | 96 known peers at 68 B, full state for 8 active |
| Cost on an RP2040 | about 0.3 ms per datagram over SPI, 0.4–1.8 ms per SEDP sample |
Tests back this up: 152 DDSI-RTPS 2.5 statements in traceability matrices, the WIZnet driver run against a register model of the chip, and CI on Humble and Jazzy against Fast DDS and Cyclone DDS.
07 — Where it stands
- Hardware runs so far: the W5100S-EVB-Pico2 (ROS) and the W6100-EVB-Pico (UDP echo). Discovery multicast on the W6100/W6300 is confirmed when a ROS example first runs there.
- rclcpp nodes talk to Rosette nodes, but cannot load
rmw_rosettethemselves. - Firmware samples up to 4096 B by default; IPv4 locators only; no DDS-Security; pre-1.0.
On one wired switch, each controller board becomes a ROS 2 node in its own right, with no PC translating for it.
08 — Similar Projects on WIZnet Makers
- How to Bridge Physical I/O into ROS 2 with W6100 on RP2040? — one of Rosette's boards on the agent route: Zephyr and micro-ROS to an agent on the host.
- mros2-esp32-eth1 — the same no-agent goal on an ESP32-S3, with embeddedRTPS over lwIP and the W5500 as the interface. Rosette hands UDP to the chip instead.
- robo-con-for-Ethernet — a WIZnet board reaching ROS 2 through a command bridge.
Q&A
Q. In what mode is the WIZnet chip used?
Hardware UDP sockets through Rosette's own register driver. No lwIP, no RTOS; RTPS runs on the RP2350 on top.
Q. Does it need a micro-ROS agent?
No. An optional agent backend exists for setups that want one.
Q. Can it be reused?
Apache-2.0. The bundled Pico SDK board headers are BSD-3-Clause.
Original Link: https://github.com/CenteredSolutions/Rosette
WIZnet driver: ports/net/wiznet/device.hpp · RTPS sockets: src/rtps/transport.cpp · Memory: docs/mcu_memory_model.md · Network: docs/network_configuration.md
