Bifrost Dual W5500 VLAN Bridge for Raspberry Pi Pico
A Pico prototype bridges two W5500 modules in MACRAW mode and applies simple VLAN tag logic.
Software Apps and online services
Bifrost as a Dual-Port W5500 Bridge
Bifrost is a Raspberry Pi Pico prototype that connects two W5500 Ethernet modules and forwards Ethernet frames between them while applying simple VLAN tag rules. Instead of using the W5500 as a normal TCP or UDP endpoint, the firmware opens the chip in MACRAW mode and handles raw Ethernet frames at the RP2040 level. That makes the project interesting for makers who want to explore what the W5500 can do below application sockets: packet forwarding, 802.1Q tag insertion, tag stripping, and link-level filtering.
The repository is compact. It contains one Arduino-style firmware file, a KiCad schematic, a PDF schematic export, a README, and an Apache-2.0 license. There is no packaged build configuration, so this should be read as a prototype and reference implementation rather than a complete drop-in product. Even so, the code and schematic provide enough evidence to understand the hardware path and the intended data flow.
W5500 MACRAW Register Path
The main source file, ProtoType_Bifrost.c, uses two chip select pins: GP17 for the primary W5500 and GP16 for the secondary W5500. MISO, SCK, and MOSI are mapped to GP0, GP2, and GP3, with GP4 used as a shared reset line. Four switch pins, GP20, GP21, GP22, and GP26, are read as the current VLAN selector.
The code does not rely on a high-level Ethernet library. It defines W5500 SPI block selectors for socket register, TX buffer, and RX buffer access, then reads and writes the chip registers directly. In setup, both W5500 modules are reset, the SPI bus is started, and socket mode is set to 0x04, which is the MACRAW mode value for the W5500 socket mode register.
From ProtoType_Bifrost.c:
SPI.setRX(0); SPI.setSCK(2); SPI.setTX(3);
SPI.begin();
SPI.beginTransaction(SPISettings(50000000, MSBFIRST, SPI_MODE0));
w_reg(CS_LAN1, 0x0000, 0x04);
w_reg(CS_LAN2, 0x0000, 0x04);
while (!is_linked(CS_LAN1) || !is_linked(CS_LAN2)) {
update_vlan_id();
delay(10);
}
w_reg(CS_LAN1, 0x0001, 0x01);
w_reg(CS_LAN2, 0x0001, 0x01);Once both links are up, the main loop runs the bridge path in both directions. The firmware reads the RX received size and RX read pointer, pulls the raw frame from the W5500 RX buffer, updates the read pointer, and issues the receive command. If the frame should be forwarded, it writes the new frame payload into the other W5500 TX buffer, updates the write pointer, and issues the send command.
VLAN Tag Handling
Bifrost's most useful behavior is the small VLAN policy implemented inside bridge(). When the selected VLAN ID is 0, frames pass through transparently. In the PC-to-router direction, the firmware accepts outgoing frames and inserts an 802.1Q tag if the frame is not already tagged. In the router-to-PC direction, it only forwards tagged frames that match the current selector, then strips the VLAN tag before sending the frame to the PC side. Tagged frames with a different VLAN ID are dropped, and untagged frames coming from the router side are also dropped.
This is not a full managed switch, and the README is clear that the current hardware is still limited. The selector is a single rotary coded switch, and the source currently reads four selector bits, so the working prototype represents a small VLAN selection range. Wider VLAN coverage is listed as future work.
Schematic Evidence and Signal Integrity Notes
The included KiCad schematic matches the README wiring map. It shows a Raspberry Pi Pico connected to two W5500 module headers, with shared SPI signals, separate chip selects, a shared reset line, a rotary switch for tag selection, decoupling capacitors, and a 100 ohm damping resistor on the clock path.
The schematic and README both emphasize practical signal integrity details: stable 3.3 V power, short SPI traces, SCK damping, and 0.1 uF decoupling near each W5500 module. One point needs validation before reuse: the README recommends staying at or below 20 MHz SPI for link stability, while the current source sets SPISettings(50000000, MSBFIRST, SPI_MODE0). Builders should verify the intended SPI speed for their board layout and module wiring.
Where This Prototype Fits
Bifrost is valuable as a focused Ethernet experiment. It is small enough to read quickly, but it touches topics that are often hidden inside larger network stacks: W5500 register access, raw frame buffers, link status polling, VLAN tag parsing, and bidirectional forwarding. A maker could use it as a starting point for a lab VLAN adapter, a teaching aid for Ethernet frame handling, or a reference for dual-W5500 wiring on RP2040.
It should not be presented as a finished router or commercial bridge. There is no BOM, no ready-made Arduino project file, no throughput measurement, and no packet capture included in the repository. The README states that tagged and untagged traffic was verified by standard web browsing, but deeper validation would require traffic captures, long-run tests, and measured SPI timing.
FAQ
What does Bifrost use the W5500 for?
Bifrost uses two W5500 modules as raw Ethernet frame interfaces. The firmware opens MACRAW mode, reads frames from one W5500 RX buffer, applies VLAN handling, and writes the result to the other W5500 TX buffer.
Does this repository include a ready-to-build project?
Not yet. The repository includes an Arduino-style source file, but it does not include a PlatformIO file, Arduino sketch folder, CMake project, or board package notes. Builders need to provide an RP2040 Arduino-compatible build setup.
What VLAN behavior is implemented?
VLAN ID 0 is treated as transparent pass-through. For nonzero selections, PC-to-router frames can receive an 802.1Q tag, while router-to-PC frames must already carry the selected VLAN ID and are stripped before forwarding to the PC side.
Can this design be extended?
Yes, but the current repository should be treated as a prototype. The README lists wider VLAN ID selection and I/O optimization as future work, and any extension should also validate SPI clocking, module wiring, and long-run packet behavior.



