Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

drive-rs

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.

Features

  • Register map generated ahead of time from a device.yaml manifest, so the generated crate depends only on the device-driver runtime — 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 example thumbv7em-none-eabihf).
  • Optional defmt support behind a cargo feature.
  • Dependency-free integration tests (mock bus, no hardware required).
  • A pico.rs example that runs the driver against real hardware from your laptop over a Pico de Gallo USB bridge.

Prerequisites

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.

Quick start

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:

  1. Project name (kebab-case) — becomes the crate name; its PascalCase form becomes the device struct name.
  2. interfaces — a multi-select of gpio, i2c, spi (choose one or more).
  3. modesync, async, or both.

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.

What you get

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.rsI2cInterface / SpiInterface implementing device-driver's RegisterInterface / AsyncRegisterInterface. I2C uses write_read; SPI uses a CS-managed SpiDevice with a read/write command bit.
  • src/driver.rs — the high-level driver type with new_i2c / new_spi constructors and example methods (device_id, set_enable, plus _async variants when async is selected).
  • src/gpio.rs — a discrete pin type. When a bus is also present it models auxiliary reset/interrupt lines; when gpio is the only interface it is the main driver.
  • src/error.rs — a generic Error<E> that carries the underlying bus or pin error.

Browse the output

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.

Regenerating the register map

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.

Testing and verification

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.

See also

  • 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 host pico.rs example.

License

Generated crates are licensed under MIT OR Apache-2.0.

About

Cargo template for Rust based drivers

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages