drv8301_dd/lib.rs
1#![cfg_attr(not(any(test, feature = "std")), no_std)]
2//! # DRV8301 Gate Driver Interface
3//!
4//! This crate provides a bisync-based driver for the DRV8301 three-phase gate driver IC,
5//! built upon the `device-driver` crate for robust, declarative register
6//! definitions via a YAML manifest. It supports both asynchronous (`async`)
7//! and blocking operation through a unified API, using the [`bisync`](https://docs.rs/bisync) crate
8//! for seamless compatibility with both `embedded-hal` and `embedded-hal-async` traits.
9//!
10//! ## Features
11//!
12//! * **Declarative Register Map:** Full device configuration defined in `device.yaml`.
13//! * **Unified Async/Blocking Support:** Write your code once and use it in both async and blocking contexts via bisync.
14//! * **Type-Safe API:** High-level functions for common operations (e.g., setting overcurrent thresholds)
15//! and a generated low-level API (`ll`) for direct register access.
16//! * **Comprehensive Register Coverage:** Supports the full feature set of the DRV8301.
17//! * **`defmt` and `log` Integration:** Optional support for logging and debugging.
18//!
19//! ## Getting Started
20//!
21//! To use the driver, instantiate `Drv8301` (blocking) or `Drv8301Async` (async) with your SPI bus implementation:
22//!
23//! ```rust,no_run
24//! # use embedded_hal::spi::SpiDevice;
25//! # use drv8301_dd::Drv8301;
26//! let spi_device = todo!();
27//! let mut drv = Drv8301::new(spi_device);
28//!
29//! // Check for faults
30//! let has_fault = drv.has_fault()?;
31//! # Ok::<(), drv8301_dd::DrvError<()>>(())
32//! ```
33//!
34//! For async environments, use `Drv8301Async` (re-exported from the `asynchronous` module):
35//!
36//! ```rust,no_run
37//! # use embedded_hal_async::spi::SpiDevice;
38//! # use drv8301_dd::Drv8301Async;
39//! let spi_device = todo!();
40//! let mut drv = Drv8301Async::new(spi_device);
41//!
42//! // Check for faults
43//! let has_fault = drv.has_fault().await?;
44//! # Ok::<(), drv8301_dd::DrvError<()>>(())
45//! ```
46//!
47//! For a detailed register map, please refer to the `device.yaml` file in the
48//! [repository](https://github.com/okhsunrog/drv8301-dd).
49//!
50//! ## Warning!
51//!
52//! ***Caution!*** This chip controls power FETs that can handle high voltages and currents.
53//! Incorrect configuration can potentially damage FETs, motors, or other components.
54//! Proceed with care and always consult the DRV8301 datasheet.
55
56#[macro_use]
57pub(crate) mod fmt;
58
59use thiserror::Error;
60
61device_driver::create_device!(device_name: DrvLowLevel, manifest: "device.yaml");
62
63#[derive(Debug, Error)]
64#[cfg_attr(feature = "defmt", derive(defmt::Format))]
65pub enum DrvError<SpiErr> {
66 #[error("SPI error")]
67 Spi(SpiErr),
68 #[error("SPI frame error detected in response")]
69 FrameError,
70 #[error("Feature or specific mode not supported/implemented: {0}")]
71 NotSupported(&'static str),
72}
73
74/// Complete fault status from both DRV8301 status registers
75///
76/// This struct provides a comprehensive view of all fault conditions
77/// reported by the DRV8301 gate driver IC.
78#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
79#[cfg_attr(feature = "defmt", derive(defmt::Format))]
80pub struct FaultStatus {
81 /// Master fault indicator (OR of all fault conditions)
82 pub fault: bool,
83 /// GVDD undervoltage fault (GVDD < ~8V)
84 pub gvdd_uv: bool,
85 /// GVDD overvoltage fault (GVDD > ~16V)
86 pub gvdd_ov: bool,
87 /// PVDD undervoltage fault (PVDD < ~5.9V)
88 pub pvdd_uv: bool,
89 /// Overtemperature shutdown (die temp > ~150°C)
90 pub otsd: bool,
91 /// Overtemperature warning (die temp > ~130°C)
92 pub otw: bool,
93 /// Phase A high-side FET overcurrent
94 pub fetha_oc: bool,
95 /// Phase A low-side FET overcurrent
96 pub fetla_oc: bool,
97 /// Phase B high-side FET overcurrent
98 pub fethb_oc: bool,
99 /// Phase B low-side FET overcurrent
100 pub fetlb_oc: bool,
101 /// Phase C high-side FET overcurrent
102 pub fethc_oc: bool,
103 /// Phase C low-side FET overcurrent
104 pub fetlc_oc: bool,
105}
106
107impl FaultStatus {
108 /// Returns true if any overcurrent fault is active on any phase
109 pub fn has_overcurrent(&self) -> bool {
110 self.fetha_oc
111 || self.fetla_oc
112 || self.fethb_oc
113 || self.fetlb_oc
114 || self.fethc_oc
115 || self.fetlc_oc
116 }
117
118 /// Returns true if any thermal condition (warning or shutdown) is active
119 pub fn has_thermal(&self) -> bool {
120 self.otsd || self.otw
121 }
122
123 /// Returns true if any voltage fault (UV or OV) is active
124 pub fn has_voltage_fault(&self) -> bool {
125 self.gvdd_uv || self.gvdd_ov || self.pvdd_uv
126 }
127
128 /// Returns true if no faults are active
129 pub fn is_ok(&self) -> bool {
130 !self.fault
131 }
132
133 /// Returns true if any phase A FET has an overcurrent fault
134 pub fn phase_a_overcurrent(&self) -> bool {
135 self.fetha_oc || self.fetla_oc
136 }
137
138 /// Returns true if any phase B FET has an overcurrent fault
139 pub fn phase_b_overcurrent(&self) -> bool {
140 self.fethb_oc || self.fetlb_oc
141 }
142
143 /// Returns true if any phase C FET has an overcurrent fault
144 pub fn phase_c_overcurrent(&self) -> bool {
145 self.fethc_oc || self.fetlc_oc
146 }
147}
148
149pub struct DrvInterface<SpiBus> {
150 spi_bus: SpiBus,
151}
152
153impl<SpiBus> DrvInterface<SpiBus> {
154 pub fn new(spi_bus: SpiBus) -> Self {
155 Self { spi_bus }
156 }
157}
158
159#[path = "."]
160mod asynchronous {
161 use bisync::asynchronous::*;
162 use device_driver::AsyncRegisterInterface as RegisterInterface;
163 use embedded_hal_async::spi::SpiDevice;
164 mod driver;
165 pub use driver::*;
166}
167pub use asynchronous::Drv8301 as Drv8301Async;
168
169#[path = "."]
170mod blocking {
171 use bisync::synchronous::*;
172 use device_driver::RegisterInterface;
173 use embedded_hal::spi::SpiDevice;
174 #[allow(clippy::duplicate_mod)]
175 mod driver;
176 pub use driver::*;
177}
178pub use blocking::Drv8301;