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:[] = "0.2.0" # For blocking usage (Drv8301): = "1.0.0" # For async usage (Drv8301Async): = "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 ; use SpiDevice; let spi_device = /* your SPI device */; let mut drv = new; // Configure overcurrent protection drv.set_oc_threshold?; drv.set_ocp_mode?; // Set PWM mode and amplifier gain drv.set_pwm_mode?; // 6-PWM mode drv.set_shunt_amplifier_gain?; // 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 if status.phase_a_overcurrent -
Async:
use ; use SpiDevice; let spi_device = /* your SPI device */; let mut drv = new; // Configure overcurrent protection drv.set_oc_threshold.await?; drv.set_ocp_mode.await?; // Set PWM mode and amplifier gain drv.set_pwm_mode.await?; // 6-PWM mode drv.set_shunt_amplifier_gain.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 if status.has_thermal
-
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?;
// Configure control register 2
drv.ll.control_register_2.write?;
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?;
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.await?;
// Async modify
drv.ll.control_register_2.modify_async.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.rs - Blocking Example:
examples/test_drv_blocking.rs
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.