Skip to content
Basic

Overview

ww_stdlib is a set of crates with ready-made WireWeaver traits and data types: GPIO, UART, I2C, CAN, logging, firmware info, firmware updates, physical units and more. Instead of designing its own GPIO or logging API, a device picks the crates it needs and puts their traits into its API, and a host (driver, CLI, GUI) gets a matching typed client from the same codegen.

[dependencies]
ww_gpio = "0.1"
ww_firmware_info = { version = "0.1", default-features = false }
#[ww_api_root]
pub trait MyBoard {
    ww_impl!(firmware: ww_firmware_info::FirmwareInfo);
    ww_impl!(gpio: ww_gpio::Bank);
    fn my_own_method(value: u8);
}

A crate's name and version are part of the wire contract (see folder structure), so using ww_gpio on both ends is what lets tools of unrelated projects recognize "this is a GPIO bank" without agreeing on anything else: ww info reads the firmware info of any device that has it, wherever it sits in the API.

All crates are no_std by default; the std feature adds owned types (..Owned, String instead of &str) for host code. Most of them live under ww_stdlib/ in this repo (canonical home: vhrdtech/ww_stdlib); the framework crates ww_self and ww_global live in the wire_weaver repo root, versioned the same way.

Picking crates

Start from what the device has:

  • Every device implements the device contract: which firmware and board it is, which unit, its log and counters, so ww info and a support case have one place to look whatever the device does.
  • Add the I/O traits for the hardware the device exposes over the wire (a GPIO bank, a UART bridge, an I2C master, ...). Pick only what is bridged: a thermometer implements Adc, not AdcStream as well.
  • Use the data types in your own methods and types: a physical value is a ww_si quantity, not a raw integer with an implied unit, and an API's error enum nests ww_error::CommonError first.
  • The framework crates are used by the codegen and introspection; an API crate rarely depends on them directly.

I/O

Traits for devices that expose IO over the wire: a dev board bridging its pins to a host, a USB adapter, a motor controller, a sensor node. The IO trait family page has the conventions they share (capabilities queried at runtime, one configure() call per bus, common errors, typed ww_si values, counted streams).

  • ww_gpio — Bank, Pin: read, drive and reconfigure pins, edge events as a stream
  • ww_uart — Uart: bridge a serial port, optionally watch a link without driving it
  • ww_can_bus — Can, CanGroup, CanTimeTriggered, CanXl: CAN, CAN FD and CAN XL controllers, from simple bridges to bus debuggers
  • ww_i2c — I2c, I2cWatch, I2cMonitor: master transfers and bus recovery, autonomous polling, bus sniffing
  • ww_spi — Spi: transfers with CS held across operations, optional bus sniffing
  • ww_adc — Adc, AdcStream, AdcCapture: one calibrated reading, continuous streaming, triggered block capture
  • ww_pwm — Pwm, PwmCapture: PWM outputs, pulse and frequency measurement
  • ww_onewire — OneWire: reset, ROM search, addressed transactions, strong pull-up
  • ww_timebase — Clock: device time, clock sync (master/slave), time of day
  • ww_logic_analyzer — LogicAnalyzer, LogicStream: timestamped capture of many digital channels
  • ww_signal_generator — PatternGenerator, WaveformGenerator: digital pattern playback, DAC waveforms
  • ww_memory — Memory8, Memory32: read and write words at addresses, optional watches, for register maps and raw memory access
  • ww_pin_diag — PinDiag: raw access to a board's digital points for bring-up and production tests (shorts, pulls, connectivity), the board's rules kept in the firmware; with ww_interned names as ids
  • ww_block — BlockDevice: read, CRC, erase and write an SD card, eMMC or flash by block; writes under a lease that stops the card's own user, optional bulk sink and read stream
  • ww_sd — SdCard: an SD card's state, raw registers, init with a per-step report, raw commands with response, status bits and timing

Device contract

The crates every device implements, whatever it does, so generic tools have one place to look. The device contract page shows where to put them and how a host finds the firmware's ELF.

  • ww_firmware_info — FirmwareInfo (name, version, git, build time, build id), LastReset (why the device last reset: fault record, stack words, boot count)
  • ww_board_info — BoardInfo: PCB series, revision and how the revision was determined
  • ww_uid — Uid: the unit's unique ids (chip id, MAC, EUI-64, ...)
  • ww_user_info — UserInfo: a name and notes the user gives a unit
  • ww_log — LogDefmt, LogText: device logging over a reliable stream, raw defmt frames or text; ww_defmt_logger (repo root) is the device side
  • ww_counters — Counters: the device's cnt counters, decoded on the host with the firmware's ELF (ww counters)
  • ww_recorder — Recorder, Track: control a logger that writes tracks to an SD card or flash: status, card facts, two-step format, recordings, markers, flush settings, counters
  • ww_indication — Indication: LED and buzzer mode, brightness, identify
  • ww_dfu — UpdateNode, BootControl, Inventory, Stage, StageBulk: firmware updates, A/B or in place, step by step or bulk

Data types

Types other crates and your own API build on.

  • ww_si — Volt, Hertz, Second, ...: physical values with their unit, in whatever number type the device picks
  • ww_error — CommonError, HasCommon: the errors every API can return (Unsupported, InUse, Busy, ...), nested first in a crate's own error enum
  • ww_date_time — DateTime (ISO 8601, optional time zone and nanoseconds, 32 bits minimum), NaiveDate, NaiveTime
  • ww_numeric — NumericValue, NumericBaseType, NumericAnyType: the number types ww_si quantities are stored as

Framework

Used by the codegen and introspection; an API crate rarely depends on these directly.

  • ww_version — Version, FullVersion (SemVer, with pre and build strings), CompactVersion (a global type id and the version numbers): how an API is identified on the wire
  • ww_client_server — Request, Event, Error: the protocol every generated server and client speaks underneath a device's own API
  • ww_self — ApiBundle, ApiLevel, Type, Value: WireWeaver's model of an API and its types, for introspection and dynamic access (repo root, not ww_stdlib/)

ww_global (the global type id registry, see addressing) is the other framework crate in the wire_weaver repo root; it has no page of its own.

Host-side _hl crates

Crates with a more ergonomic client on top of a generated one, for drivers, CLIs and GUIs rather than firmware.

  • ww_gpio_hl — async, blocking and promise wrappers over ww_gpio's generated client, with embedded-hal digital traits (ww_gpio)
  • ww_i2c_hl — embedded-hal I2C (blocking and async) over a remote ww_i2c::I2c: stock driver crates run unchanged on the host