2 unstable releases
Uses new Rust 2024
| 0.2.0 | Nov 30, 2025 |
|---|---|
| 0.1.0 | Nov 30, 2025 |
#1314 in Hardware support
2.5MB
597 lines
DRV8301 Gate Driver IC Driver (drv8301-dd)
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.
Overview
The drv8301-dd driver offers:
- Declarative Configuration: The DRV8301 register map is defined in
device.yaml, enablingdevice-driverto generate a type-safe, low-level register access API. This approach enhances maintainability and extensibility. - Unified Async/Blocking API: Uses the
bisynccrate to provide both asynchronous (Drv8301Async) and blocking (Drv8301) drivers from the same codebase, with no feature flags required. - High-Level and Low-Level APIs:
- High-level methods simplify tasks like configuring overcurrent protection, PWM modes, and shunt amplifier gains.
- Low-level API (via the
llfield of theDrv8301/Drv8301Asyncstruct) offers direct, type-safe access to all registers defined indevice.yaml.
- Motor Control Features: Manages gate driver outputs, overcurrent protection, temperature monitoring, and current sensing.
no_stdandno-alloc: Optimized for bare-metal and RTOS environments.- Optional Logging: Supports
defmtand thelogfacade for debugging.
Features
- Declarative Register Map: Defined in
device.yaml. - Unified Async/Blocking API: Both async and blocking drivers are always available; no feature flags required.
- Type-Safe Register Access: Generated by
device-driver. - Comprehensive Control: (See
device.yamlfor details)- Three-phase half-bridge gate driver outputs
- Configurable overcurrent protection (VDS thresholds, OCP modes)
- Current shunt amplifiers with selectable gain (10/20/40/80 V/V)
- PWM mode selection (6-PWM or 3-PWM)
- Status monitoring (faults, temperature, voltage)
- DC calibration modes
no_stdandno-alloc.- Optional Logging: Supports
defmtandlogfacade.
Getting Started
-
Add
drv8301-ddtoCargo.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)
- Use
-
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 }
-
Low-Level API Usage
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.
Reading Registers
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();
Writing Registers
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);
})?;
Modifying Registers
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
})?;
Async Low-Level API
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?;
Field Naming Convention
Register and field names in the LL API follow snake_case and are derived from the names in device.yaml:
- Register:
StatusRegister1→status_register_1() - Field:
gate_current→set_gate_current()/gate_current() - Register:
ControlRegister2→control_register_2() - Field:
dc_cal_ch1→set_dc_cal_ch1()/dc_cal_ch1()
Finding Register/Field Names
- Check
device.yaml- All registers and fields are documented there - Use IDE autocomplete - Type
drv.ll.to see all available registers - Read a register - Use
.read()then autocomplete to see available field getters - Write a register - The closure parameter has autocomplete for all setters
Examples
Examples 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.
- Async Example:
examples/test_drv_async.rscargo run --release --example test_drv_async --features defmt - Blocking Example:
examples/test_drv_blocking.rscargo run --release --example test_drv_blocking --features defmt
Register Map
The DRV8301 register map is defined in device.yaml, which device-driver uses to generate Rust code. This file specifies:
- Register names, addresses, and sizes.
- Field names, bit positions, and access modes (Read-Only, Read-Write).
- Enumerations for field values (e.g., gate currents, OCP modes, amplifier gains).
- Reset values and descriptions based on the datasheet.
Hardware Setup
The DRV8301 requires SPI communication with specific characteristics:
- SPI Mode: CPOL=0, CPHA=1 (Mode 1)
- Clock Frequency: Up to 10 MHz
- Frame Format: 16-bit MSB first
- Voltage Levels: 3.3V or 5V logic compatible
- Connections: SCLK, MISO, MOSI, CS (chip select)
Datasheet
- DRV8301 Datasheet - PDF
- DRV8301 Datasheet - Markdown (OCR-converted for easier reference)
Feature Flags
default = []: No default features; async and blocking drivers are always available.std: Enablesstdfeatures forthiserror.log: Enableslogfacade logging. Requireslog = { version = "0.4", optional = true }.defmt: Enablesdefmtlogging. Requiresdefmt = { version = "1.0", optional = true }.
Contributions
Contributions are welcome! While the register map in device.yaml is complete, you can contribute by:
- Adding high-level convenience methods to simplify common operations (e.g., motor control sequences, calibration routines).
- Enhancing documentation with additional examples or clarifications.
- Reporting issues or suggesting improvements.
- Suggesting code refactoring.
Please submit issues, fork the repository, and create pull requests.
License
This project is dual-licensed under the MIT License or Apache License 2.0, at your option.
Dependencies
~8MB
~166K SLoC