Open source
Open source
Every crate and repository, from register to GUI: what it does, a code sample and where to read more.
The stack comes first. The first five are the core: the API, its wire format, units, the firmware template and the event counters. canzone is work in progress. The last ones are the tools around the boards: a test bench scheduler and the GUI building blocks. After the stack comes every other repository, by area. The ones marked “coming in the future” are not public yet. draft
- ProductsDonguru · rePort · CAN line · IOWeaver · RockFace
-
API
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>; } -
Wire format
Compact zero-copy wire format for microcontrollers. No allocator, dynamic types, packed down to the bit.
// 1 + 7 or 1 + 10 bits #[derive_shrink_wrap(ww_repr = u1)] enum I2cAddress { Seven(U7), Ten(U10) } #[derive_shrink_wrap] struct I2cWrite<'i> { // 0x50: 0 1010000 addr: I2cAddress, stop: bool, // 1 bit fast: bool, // 1 bit retries: Nibble, // 3: 0011 // Some(500): 1 0111110100 timeout_ms: Option<U10>, data: RefVec<'i, u8>, // ab cd } // 50 83 be 80 ab cd 02: 7 bytes, the // count (02) at the back. repr(C): 20. -
Units
exact_units
not on crates.io yetUnits 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 let t: Micros<u32> = Fixed::new(1500); assert_eq!(t.to::<Milli, u16>(), None); // 1500 µs is not a whole number of ms // V/V and W/W are different kinds, // and the kind picks the dB formula type V = Per<Volt, Volt>; type W = Per<Watt, Watt>; Fixed::<V, One, f64>::new(2.0).to_db(); // 6.0206 dB: 20·lg 2 Fixed::<W, One, f64>::new(2.0).to_db(); // 3.0103 dB: 10·lg 2 // a threshold in dB: an integer, exact, // 501 mV/V but 251 mW/W let v: Fixed<V, Milli, u16> = db!(-6); let p: Fixed<W, Milli, u16> = db!(-6); // 0.5 duty is not -3 dB: a Ratio has no 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 form -
Firmware
embedded_bedrock
not on crates.io yetBare-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?; -
Firmware
When logging is not an option, count: events and errors in a RAM array, safe in any interrupt, without a critical section. Read over the debug probe with `cnt read` or `cnt tui`.
// one RAM counter per call site, // no critical section, safe in an IRQ fn high_frequency_irq() { let r = do_something(); cnt::cnt_if!(r.is_err(), unpack_errors: u64); } fn process_packet() { cnt::cnt!(packet_count: u32); } // on the PC, over the debug probe: // $ cnt tui --chip STM32H533RE -
Firmware
canzone work in progress
renamed from mcan, not on crates.io yetStand-alone Rust driver for the Bosch M_CAN controller, aimed at STM32 G0, G4, H5, H7 and L5. Goals: no panics, no blocking waits without a timeout, optional async.
let mut can = unwrap!(can.into_config_mode()); can.set_nominal_bit_timing(unwrap!( NominalBitTiming::new(1, 55, 8, 1) )); unwrap!(can.set_layout(layout_fdcan1)); can.set_automatic_bus_off_recovery(true); let mut can = unwrap!(can.into_normal()); let id = unwrap!(StandardId::new(0x123)); can.write_tx_buffer_pend( tx_buffers.idx1, TxFrameHeader::fd_brs(Id::Standard(id)), &[0xAA, 0xBB, 0xCC], ); -
Test bench
choreograph
not on crates.io yetPlans and runs jobs over shared instruments and resources, with priorities and deadlines. Says why each waiting job waits.
[[resource]] name = "supply" kind = "supply" states = ["off", "3V0", "3V3", "3V6"] safe = "off" [[job]] name = "a-3V3" needs = [ { kind = "probe", state = "fw-a" }, { kind = "supply", state = "3V3" }, ] run = "10s" -
GUI
Fast table viewer and editor that only draws the visible rows. Data from vectors, files, databases or live bus traces.
let mut table = VariantTable::new([ ColumnDef::new("Name", VariantTy::Str), ]); let opts = TableViewOptions::default(); let mut view = TableView::new(opts); let mut config = TableViewConfig::default(); // Every frame: let output = view.show( ui, &mut table, &mut VariantCellUi, &mut config, ); -
GUI
vhrd_egui
not on crates.io yetegui building blocks: the widget frame every panel sits in, a dock that moves widgets between windows, an HDR phosphor scope.
// min, nom and wide sizes, and a tall form let hints = SizeHints::new( [90.0, 30.0], [200.0, 80.0], [360.0, 80.0], ) .tall(200.0); WidgetFrame::new("log") .sizes(hints) .show_area(ui, &mut state, |ui, area| { let rows = match area.height { Height::Min => 1, Height::Nom => 5, Height::Tall => 15, }; });
More repositories
Wire format and APIs
-
wire_weaver_template
WireWeaver over USB as a template: a shared API, example firmware and a Rust host driver with a REPL.
-
can_bus_ww
WireWeaver API and data structures for CAN bus bridges.
-
ww_lsp
Language server for WireWeaver APIs: units as inlay hints, beside rust-analyzer. A prototype.
-
napier
Parses SI values and units from text at run time, schematic shorthand like 4k7 included.
-
bitfield_introspect
Value descriptions on bitfield-struct fields, turned into structured data for decoding.
Firmware and embedded
-
typec_dongle
Donguru: a USB-C dongle with a USB hub, UART, I2C, GPIO and ADC, a power switch and a power meter.
-
logring
Power-cut-safe multi-track log store for embedded Rust, with USB disk access and MF4, MCAP and CSV export.
-
exfat_lite
Minimal exFAT for SD cards, no_std and no alloc: format, mount, contiguous files, read-only volumes.
-
usb_msc_device
USB Mass Storage device class for embassy-usb, async, with several LUNs.
-
motor_sim
Deterministic no_std electric motor simulator, for testing motor controllers in software.
-
nucleo_g0b1re_template
Firmware template for the ST Nucleo-G0B1RE: firmware, API, client library, CLI and Python module.
-
cannify_micro_template
Firmware template for the B129A CANnify Micro board (STM32G0): API, client library, CLI and Python module.
-
donguru_template
Firmware template for Donguru: a typed API, Rust client, CLI and Python module from one spec.
-
report_template
Firmware template for rePort: a typed API, Rust client, CLI and Python module from one spec.
-
b135_template
Firmware template for the B135B FDCAN-ISO-USB board: WireWeaver API, firmware, Rust client and CLI.
-
pico_template
Firmware template for the Raspberry Pi Pico: a typed API, Rust client, CLI and Python module from one spec.
-
pico2_template
Firmware template for the Raspberry Pi Pico 2: a typed API, Rust client, CLI and Python module from one spec.
Drivers and HALs
-
slg4682x
HAL for the SLG46824 and SLG46826 mixed-signal matrix: read, program and rewire it over I2C.
-
bq769x2
Register definitions for the BQ76952, BQ76942 and BQ769142 battery monitor AFEs.
-
usb4604
HAL for the GPIO and I2C of the USB4604 USB hub.
-
otm8009a
Bare-metal driver for the OTM8009A LCD controller.
-
i2c_periph
Async no_std I2C driver with one API across microcontrollers and I2C IPs.
-
pd_bench
A no_std FUSB302 USB PD driver, and a PC tool that acts as a sink to test PD sources.
Host tools and instruments
-
io_bridge
Client library that reads and drives GPIO, I2C, USART, SPI and ADC on a device over USB, Ethernet or CAN.
-
picoboot_host
The RP2040 and RP2350 USB boot ROM from a PC: flash, erase, verify and reboot a device in BOOTSEL mode.
-
m2k
The ADALM2000 from Rust, Python or the shell: scope, generator, supplies and voltmeter.
-
saleae_rs
Drive a Saleae logic analyzer from Rust, Python or the command line.
-
gw121
The EEVblog 121GW multimeter over Bluetooth LE: a Rust library, CLI, Python module and agent skill.
-
rvariant
A dynamically typed value like Qt's QVariant, with SI units: table cells, CSV import, BOM parsing.
-
vhrd_cli
A UX guide for Rust command-line tools. The shared crates it describes are still planned.
-
can_bus_cli
Command line for CAN bus bridges.
-
fpga_tools
FPGA lab tools on an Efinix board: a signal glitcher and a cycle-exact bus, UART and PWM generator.
-
popov
SDR and DSP toolkit: FIR filters, NCOs, a seeded test channel simulator and a command line.
-
mdcheck
Compile-checks the Rust code blocks in Markdown files, each against its own inferred Cargo.toml.
EDA and hardware tools
-
better_erc
Finds schematic mistakes beyond KiCad's own ERC, and turns KiCad files into readable git diffs.
-
kicad-library
VHRD's KiCad library: symbols, footprints, 3D models, drawing sheets and a project template.
-
radiated-immunity-tester
EN 61000-4-3 radiated immunity test bench with GNU Radio, a USRP SDR and a TEM cell.
-
eda_lens
Reads schematic PDFs, images and scans into structured netlist data; Gerbers and PCB photos next.