| Crates.io | drv8301-dd |
| lib.rs | drv8301-dd |
| version | 0.2.0 |
| created_at | 2025-11-30 22:23:57.574439+00 |
| updated_at | 2025-11-30 22:47:57.363968+00 |
| description | A driver for the DRV8301 gate driver IC (uses device-driver crate) |
| homepage | |
| repository | https://github.com/okhsunrog/drv8301-dd |
| max_upload_size | |
| id | 1958919 |
| size | 2,868,660 |
This crate provides a no_std driver for the DRV8301 three-phase gate driver IC, a highly integrated motor driver from Texas Instruments. The project aims to support the full functionality of the DRV8301, leveraging the device-driver crate with a declarative YAML manifest (device.yaml) for a robust, type-safe register map definition. The low-level API covers 100% of the DRV8301's registers, with device.yaml providing a comprehensive and accurate description of all registers and their fields.
The drv8301-dd driver offers:
device.yaml, enabling device-driver to generate a type-safe, low-level register access API. This approach enhances maintainability and extensibility.bisync crate to provide both asynchronous (Drv8301Async) and blocking (Drv8301) drivers from the same codebase, with no feature flags required.ll field of the Drv8301/Drv8301Async struct) offers direct, type-safe access to all registers defined in device.yaml.no_std and no-alloc: Optimized for bare-metal and RTOS environments.defmt and the log facade for debugging.device.yaml.device-driver.device.yaml for details)
no_std and no-alloc.defmt and log facade.Add drv8301-dd to Cargo.toml:
[dependencies]
drv8301-dd = "0.2.0"
# For blocking usage (Drv8301):
embedded-hal = "1.0.0"
# For async usage (Drv8301Async):
embedded-hal-async = "1.0.0"
Note: Add the relevant
embedded-halcrate for your use case, no need for both
- Use
embedded-halfor blocking drivers (Drv8301)- Use
embedded-hal-asyncfor async drivers (Drv8301Async)
Instantiate the driver with your SPI device:
Blocking:
use drv8301_dd::{Drv8301, OcAdjSet, OcpMode, ShuntAmplifierGain};
use embedded_hal::spi::SpiDevice;
let spi_device = /* your SPI device */;
let mut drv = Drv8301::new(spi_device);
// Configure overcurrent protection
drv.set_oc_threshold(OcAdjSet::Vds250mV)?;
drv.set_ocp_mode(OcpMode::CurrentLimit)?;
// Set PWM mode and amplifier gain
drv.set_pwm_mode(false)?; // 6-PWM mode
drv.set_shunt_amplifier_gain(ShuntAmplifierGain::Gain20)?;
// Read device status
let device_id = drv.get_device_id()?;
let has_fault = drv.has_fault()?;
// Get comprehensive fault status
let status = drv.get_fault_status()?;
if status.has_overcurrent() {
// Handle overcurrent on any phase
}
if status.phase_a_overcurrent() {
// Phase A specific fault
}
Async:
use drv8301_dd::{Drv8301Async, OcAdjSet, OcpMode, ShuntAmplifierGain};
use embedded_hal_async::spi::SpiDevice;
let spi_device = /* your SPI device */;
let mut drv = Drv8301Async::new(spi_device);
// Configure overcurrent protection
drv.set_oc_threshold(OcAdjSet::Vds250mV).await?;
drv.set_ocp_mode(OcpMode::CurrentLimit).await?;
// Set PWM mode and amplifier gain
drv.set_pwm_mode(false).await?; // 6-PWM mode
drv.set_shunt_amplifier_gain(ShuntAmplifierGain::Gain20).await?;
// Read device status
let device_id = drv.get_device_id().await?;
let has_fault = drv.has_fault().await?;
// Get comprehensive fault status
let status = drv.get_fault_status().await?;
if status.has_overcurrent() {
// Handle overcurrent on any phase
}
if status.has_thermal() {
// Handle overtemperature warning or shutdown
}
The driver provides direct access to all DRV8301 registers through the low-level API via drv.ll. This API is automatically generated from device.yaml and provides type-safe access to all register fields.
Use .read() to read a register and access its fields:
// Read status register 1
let status1 = drv.ll.status_register_1().read()?;
let has_fault = status1.fault();
let gvdd_uv = status1.gvdd_uv();
let otw = status1.otw();
// Read status register 2
let status2 = drv.ll.status_register_2().read()?;
let device_id = status2.device_id();
// Read control register 1
let ctrl1 = drv.ll.control_register_1().read()?;
let gate_current = ctrl1.gate_current();
let gate_reset = ctrl1.gate_reset();
Use .write() with a closure to modify register fields. The closure receives a mutable reference to the register structure:
// Configure control register 1
drv.ll.control_register_1().write(|w| {
w.set_gate_current(GateCurrent::Ma1700);
w.set_gate_reset(false);
w.set_pwm_mode(PwmMode::SixPwm);
w.set_oc_adj_set(OcAdjSet::Vds250mV);
})?;
// Configure control register 2
drv.ll.control_register_2().write(|w| {
w.set_octw_set(OctwSet::Both);
w.set_gain(ShuntAmplifierGain::Gain20);
w.set_dc_cal_ch1(false);
w.set_dc_cal_ch2(false);
w.set_ocp_mode(OcpMode::CurrentLimit);
})?;
Use .modify() to read-modify-write, preserving other fields:
// Enable DC calibration for channel 1 without affecting other settings
// modify() reads the register, applies your changes, then writes it back
drv.ll.control_register_2().modify(|w| {
w.set_dc_cal_ch1(true); // Only modify this field, others preserved
})?;
The low-level API has async versions for use with Drv8301Async. Simply append _async to the method name:
// Async read
let status1 = drv.ll.status_register_1().read_async().await?;
let status2 = drv.ll.status_register_2().read_async().await?;
// Async write
drv.ll.control_register_1().write_async(|w| {
w.set_gate_current(GateCurrent::Ma1700);
w.set_pwm_mode(PwmMode::SixPwm);
}).await?;
// Async modify
drv.ll.control_register_2().modify_async(|w| {
w.set_gain(ShuntAmplifierGain::Gain40);
}).await?;
Register and field names in the LL API follow snake_case and are derived from the names in device.yaml:
StatusRegister1 → status_register_1()gate_current → set_gate_current() / gate_current()ControlRegister2 → control_register_2()dc_cal_ch1 → set_dc_cal_ch1() / dc_cal_ch1()device.yaml - All registers and fields are documented theredrv.ll. to see all available registers.read() then autocomplete to see available field gettersExamples for ESP32-C3 using esp-hal are included. Setup is required (see esp-hal docs). Both examples demonstrate high-level convenience methods and low-level register API usage.
examples/test_drv_async.rs
cargo run --release --example test_drv_async --features defmt
examples/test_drv_blocking.rs
cargo run --release --example test_drv_blocking --features defmt
The DRV8301 register map is defined in device.yaml, which device-driver uses to generate Rust code. This file specifies:
The DRV8301 requires SPI communication with specific characteristics:
default = []: No default features; async and blocking drivers are always available.std: Enables std features for thiserror.log: Enables log facade logging. Requires log = { version = "0.4", optional = true }.defmt: Enables defmt logging. Requires defmt = { version = "1.0", optional = true }.Contributions are welcome! While the register map in device.yaml is complete, you can contribute by:
Please submit issues, fork the repository, and create pull requests.
This project is dual-licensed under the MIT License or Apache License 2.0, at your option.