
Donguru Coming Q1–Q2 2027
A USB-C dongle with a USB hub, a serial port, a power switch and a power meter.
- Hub
- USB, on board
- Serial
- TX/RX flip
- Power
- switch + meter
Boards · Rust firmware · Open source
Boards, Rust firmware and the open-source software that ties them together, from Norway.
draft Copy not yet read by Marketing and PM. Board renders follow.

01Products
Three tools for bring-up, debugging and test, each with a Rust driver, a CLI and a GUI.

A USB-C dongle with a USB hub, a serial port, a power switch and a power meter.

Digital and analog I/O over USB. No programming needed.

USB and Ethernet bridges to isolated CAN FD, with SD card logging, and the adapters around them.
02Donguru · B153
Donguru sits between your computer and a board with a USB-C port. One cable carries USB, a serial console and power you can switch and measure.
A USB hub and a UART on the same cable. TX and RX are flipped for you.
Electronic switches on VBUS and the USB data lines, a power meter, and a mechanical switch for the boot mode.
A fast CLI, donguru or dg, with a Rust driver and Python behind it.
For development, debugging and production flashing of devices with a USB-C port.
03Software
IOWeaver plots what your device says. RockFace debugs the firmware that says it. WireWeaver keeps both sides speaking the same API.

// The API, once, for both sides (ww_uart):
#[ww_trait]
#[claim(exclusive)]
pub trait Uart {
#[counted]
stream!(rx: RxChunk<'i>);
#[credit]
sink!(tx: MaxLen<RefVec<'i, u8>, UART_TX_MAX>);
fn capabilities() -> Capabilities<'i>;
}
// A device with several ports lists them as one array:
ww_impl!(uart[]: ww_uart::Uart)
Protocol analyzer and grapher. Record, decode, plot and send. It ships with rePort and Donguru.
Firmware debugger: logs, stack and CPU use, zero-cost profiling, logs from a fleet. First paid release planned for January 2027.
One API definition for device and host: RPC, streams and properties, backwards and forwards compatible. Open source.
04From the lab
Four pieces from our own bench: Ethernet and USB to CAN FD, a laser scanner and a firmware debugger.

Ethernet to two isolated CAN FD buses, with SD card logging.

USB High Speed to isolated CAN FD, with SD card logging.

Optical inspection of solder paste and placed parts with a scanning green laser line.

A firmware debugger for running systems. First paid release planned for January 2027.
05Open source
The products stand on open crates, all Rust: the API and its wire format, units checked at compile time, and a bare-metal firmware template.
API description language and code generator: RPC, streams and properties, backwards and forwards compatible, no_std and no alloc.
#[ww_trait]
#[claim(exclusive)]
pub trait Uart {
#[counted]
stream!(rx: RxChunk<'i>);
#[credit]
sink!(tx: MaxLen<RefVec<'i, u8>, UART_TX_MAX>);
fn capabilities() -> Capabilities<'i>;
}Compact zero-copy wire format for microcontrollers. No allocator, dynamic types, packed down to the bit.
#[derive_shrink_wrap(ww_repr = u1)]
enum I2cAddress { Seven(U7), Ten(U10) } // 1 + 7 or 1 + 10 bits
#[derive_shrink_wrap]
struct I2cWrite<'i> {
addr: I2cAddress, // 0x50: 0 1010000
stop: bool, // 1 bit
fast: bool, // 1 bit
retries: Nibble, // 3: 0011, on a nibble
timeout_ms: Option<U10>, // Some(500): 1 0111110100
data: RefVec<'i, u8>, // ab cd, the count at the back
}
// 50 83 be 80 ab cd 02: 7 bytes. As a repr(C) struct: 20.Units of measure checked at compile time, with exact scales. The same bytes as the plain integer, no_std and no alloc.
// exact or refused, never rounded through a float
let t: Micros<u32> = Fixed::new(1500);
assert_eq!(t.to::<Milli, u16>(), None); // not whole ms
// V/V and W/W are different kinds: the kind picks the dB
type VGain = Fixed<Per<Volt, Volt>, One, f64>;
type PGain = Fixed<Per<Watt, Watt>, One, f64>;
VGain::new(2.0).to_db(); // 6.0206: 20·lg 2
PGain::new(2.0).to_db(); // 3.0103: 10·lg 2
// a threshold in dB, an integer at compile time
let v: Fixed<Per<Volt, Volt>, Milli, u16> = db!(-6); // 501
let p: Fixed<Per<Watt, Watt>, Milli, u16> = db!(-6); // 251
// a duty cycle has no level: 0.5 duty is not -3 dB
// Fixed::<Ratio, One, f64>::new(0.5).to_db();
// error[E0080]: decibels are for W/W or V/V, A/A, Pa/Pa:
// a plain Ratio has no level formBare-metal firmware template with ruggedizing, debugging and logging built in. Optional embassy, RTIC and HAL support.
use bedrock_led::code::*;
use bedrock_sync::{Config, Sync};
use cortex_m::asm::delay;
// A firmware that will not start
// says why on its status LED, then
// waits in the ROM bootloader.
if !guard.runs_board() {
let pause = |n| delay(n * KHZ);
blink(Code::UnknownRework,
led, pause);
reboot_into_rom_bootloader();
}
// One clock on all boards, steered
// by the host over WireWeaver:
// Acquiring, Locked within 2 ms.
// `ww sync` locks the boards in
// 1.2-1.6 s. On Donguru it costs
// about 1.5 KB of flash.
static SYNC: Sync =
Sync::new(Config::DEFAULT);
// clock.steer, once a second
let r = SYNC.with(|clock, now| {
server.steer(clock, now, &p)
});
// all boards act at the same µs
SYNC.wait_until_shared(t).await?;06Stay in the loop
Donguru launches on Crowd Supply. Its sign-up list opens with the pre-launch page; until then, send a line and you hear first. draft
Contact
Questions about the boards, the software or a project of your own: hello@vhrd.tech.
Engineering services are rare right now. What I do and how I work