A cargo-generate template
that scaffolds a well-structured, no_std, embedded-hal
device driver crate on top of the device-driver
toolkit (v1.0.9).
Answer three prompts and you get a compiling driver crate with a register map, a transport layer, a high-level API, dependency-free mock tests, and a runnable host example — in seconds.
- Register map generated ahead of time from a
device.yamlmanifest, so the generated crate depends only on thedevice-driverruntime — no proc-macro in your build. - Pick one or more interfaces:
gpio,i2c,spi. Unused modules are pruned. - Pick your API surface: blocking (
embedded-hal), async (embedded-hal-async), or both. Resolved at generation time — no feature-flag soup. - Generated crate is
#![no_std]and builds for bare-metal targets (for examplethumbv7em-none-eabihf). - Optional
defmtsupport behind a cargo feature. - Dependency-free integration tests (mock bus, no hardware required).
- A
pico.rsexample that runs the driver against real hardware from your laptop over a Pico de Gallo USB bridge.
cargo install cargo-generate
cargo install device-driver-cli
The template's post-generation hook shells out to device-driver-cli to compile
device.yaml into src/registers.rs.
cargo generate --git https://github.com/OpenDevicePartnership/drive-rs template --allow-commands
The trailing template selects the template subfolder within the repository.
Or, from a local checkout of this repository:
cargo generate --path template --allow-commands
--allow-commands is required (otherwise answer the interactive confirmation)
because the post-hook runs device-driver-cli.
You will be prompted for three things:
- Project name (kebab-case) — becomes the crate name; its PascalCase form becomes the device struct name.
- interfaces — a multi-select of
gpio,i2c,spi(choose one or more). - mode —
sync,async, orboth.
A sample session:
Project Name: acme-sensor
Which bus/interface(s) does the device use? i2c
Generate blocking, async, or both APIs? both
Selecting no interface aborts with a clear message — a driver needs at least one.
The generated layout depends on your answers:
<project-name>/
Cargo.toml # license MIT OR Apache-2.0; async/defmt deps as selected
device.yaml # register-map source of truth (i2c/spi only)
src/
lib.rs # #![no_std] crate root
error.rs # generic Error<E>, preserves the bus/pin error
registers.rs # generated by device-driver-cli (i2c/spi only)
interface.rs # RegisterInterface transport (i2c/spi only)
driver.rs # high-level driver + constructors (i2c/spi only)
gpio.rs # discrete output/input pin type (gpio only)
tests/integration.rs # mock-based tests, no hardware
examples/pico.rs # runs on a host over Pico de Gallo
src/interface.rs—I2cInterface/SpiInterfaceimplementing device-driver'sRegisterInterface/AsyncRegisterInterface. I2C useswrite_read; SPI uses a CS-managedSpiDevicewith a read/write command bit.src/driver.rs— the high-level driver type withnew_i2c/new_spiconstructors and example methods (device_id,set_enable, plus_asyncvariants when async is selected).src/gpio.rs— a discrete pin type. When a bus is also present it models auxiliary reset/interrupt lines; whengpiois the only interface it is the main driver.src/error.rs— a genericError<E>that carries the underlying bus or pin error.
See examples/acme-sensor/ for a concrete, committed example of what the
template produces: an I2C driver exposing both sync and async APIs, with a
generated register map and a Pico de Gallo example.
device.yaml is the single source of truth for the register map. After editing
it to match your datasheet, regenerate src/registers.rs:
device-driver-cli -m device.yaml -o src/registers.rs -d <Device>Registers
where <Device> is the PascalCase form of your crate name (for example
AcmeSensorRegisters). The generated file is committed to the crate.
The generated crate ships with mock-based integration tests that need no hardware:
cargo test
cargo clippy -- -D warnings
cargo build --target thumbv7em-none-eabihf
Every valid combination — 7 interface sets across 3 modes — is verified to
build and to pass cargo clippy -D warnings and cargo test.
device-driver— the register toolkit the generated crate is built on.embedded-hal— the trait abstractions the driver is generic over.pico-de-gallo-hal— the USB bridge that powers the hostpico.rsexample.
Generated crates are licensed under MIT OR Apache-2.0.