stm32_hrtim/
fault.rs

1#[cfg(feature = "hrtim_v2")]
2use crate::control::HrPwmControl;
3use crate::pac::HRTIM_COMMON;
4
5use super::control::HrPwmCtrl;
6
7/// Allows a FaultMonitor to monitor faults
8pub trait FaultMonitor {
9    fn enable_interrupt(&mut self, hr_control: &mut HrPwmCtrl);
10
11    /// Returns true if a fault is preventing PWM output
12    fn is_fault_active(&self) -> bool;
13
14    /// Clear the fault interrupt flag
15    ///
16    /// This will *NOT* resume normal PWM operation. The affected outputs need to be re-enabled to resume operation;
17    /// This will do nothing if the fault is still active.
18    fn clear_fault(&mut self);
19}
20
21pub enum FaultAction {
22    /// Output never enters fault mode
23    None = 0b00,
24
25    /// Output forced to `active` level on fault
26    ForceActive = 0b01,
27
28    /// Output forced to `inactive` level on fault
29    ForceInactive = 0b10,
30
31    /// The output is floating/tri stated on fault
32    Floating = 0b11,
33}
34
35/// # Safety
36/// Only implement for actual fault sources with correct `ENABLE_BITS`
37pub unsafe trait FaultSource: Copy {
38    const ENABLE_BITS: u8;
39}
40
41#[cfg(feature = "stm32g4")]
42pub struct SourceBuilder<I> {
43    _input: I,
44    src_bits: u8,
45
46    /// FLTxP
47    is_active_high: bool,
48
49    /// FLTxF[3:0]
50    filter_bits: u8,
51}
52
53#[cfg(feature = "stm32g4")]
54impl<I> SourceBuilder<I> {
55    /// # Safety
56    /// Caller needs to ensure that src_bits is a valid bit pattern
57    /// for fltXsrc bits in fltinr1/2 registers for the intended input
58    pub unsafe fn new(input: I, src_bits: u8) -> Self {
59        SourceBuilder {
60            _input: input,
61            src_bits,
62            is_active_high: false,
63            filter_bits: 0b0000,
64        }
65    }
66}
67
68#[cfg(feature = "hrtim_v2")]
69macro_rules! impl_faults {
70    ($(
71        $input:ident => $source:ident:
72            $enable_bits:literal,
73            $fltinrZ:ident, $fltWsrc_0:ident, $fltWsrc_1:ident, $fltWp:ident, $fltWf:ident, $fltWe:ident, $fltWlck:ident,
74    )+) => {$(
75        // This should NOT be Copy/Clone
76        #[non_exhaustive]
77        pub struct $input;
78
79        #[non_exhaustive]
80        #[derive(Copy, Clone)]
81        pub struct $source;
82
83        impl SourceBuilder<$input> {
84            pub fn finalize(self, _control: &mut HrPwmControl) -> $source {
85                let SourceBuilder{ _input, src_bits, is_active_high, filter_bits } = self;
86
87                // Setup fault source
88                unsafe {
89                    let common = &*HRTIM_COMMON::ptr();
90
91                    common.fltinr2().modify(|_r, w| w.$fltWsrc_1().bit(src_bits & 0b10 != 0));
92                    common.$fltinrZ().modify(|_r, w| w
93                        .$fltWsrc_0().bit(src_bits & 0b01 != 0)
94                        .$fltWp().bit(is_active_high)
95                        .$fltWf().bits(filter_bits)
96                        .$fltWe().set_bit() // Enable
97                    );
98
99                    // ... and lock configuration
100                    common.$fltinrZ().modify(|_r, w| w.$fltWlck().set_bit());
101                }
102
103                $source
104            }
105
106            pub fn polarity(mut self, polarity: super::Polarity) -> Self {
107                self.is_active_high = matches!(polarity, super::Polarity::ActiveHigh);
108                self
109            }
110
111            // TODO: add more settings
112            /* pub fn blanking(?) -> Self */
113
114            pub fn filter(mut self, filter: FaultSamplingFilter) -> Self {
115                self.filter_bits = filter as u8;
116                self
117            }
118        }
119
120        unsafe impl FaultSource for $source {
121            const ENABLE_BITS: u8 = $enable_bits;
122        }
123    )+}
124}
125
126#[cfg(feature = "hrtim_v2")]
127impl_faults!(
128    FaultInput1 => FaultSource1: 0b000001, fltinr1, flt1src, flt1src_1, flt1p, flt1f, flt1e, flt1lck,
129    FaultInput2 => FaultSource2: 0b000010, fltinr1, flt2src, flt2src_1, flt2p, flt2f, flt2e, flt2lck,
130    FaultInput3 => FaultSource3: 0b000100, fltinr1, flt3src, flt3src_1, flt3p, flt3f, flt3e, flt3lck,
131    FaultInput4 => FaultSource4: 0b001000, fltinr1, flt4src, flt4src_1, flt4p, flt4f, flt4e, flt4lck,
132    FaultInput5 => FaultSource5: 0b010000, fltinr2, flt5src, flt5src_1, flt5p, flt5f, flt5e, flt5lck,
133    FaultInput6 => FaultSource6: 0b100000, fltinr2, flt6src, flt6src_1, flt6p, flt6f, flt6e, flt6lck,
134);
135
136pub struct FaultInputs {
137    #[cfg(feature = "hrtim_v2")]
138    pub fault_input1: FaultInput1,
139    #[cfg(feature = "hrtim_v2")]
140    pub fault_input2: FaultInput2,
141    #[cfg(feature = "hrtim_v2")]
142    pub fault_input3: FaultInput3,
143    #[cfg(feature = "hrtim_v2")]
144    pub fault_input4: FaultInput4,
145    #[cfg(feature = "hrtim_v2")]
146    pub fault_input5: FaultInput5,
147    #[cfg(feature = "hrtim_v2")]
148    pub fault_input6: FaultInput6,
149}
150
151impl FaultInputs {
152    pub(crate) unsafe fn new() -> Self {
153        FaultInputs {
154            #[cfg(feature = "hrtim_v2")]
155            fault_input1: FaultInput1,
156            #[cfg(feature = "hrtim_v2")]
157            fault_input2: FaultInput2,
158            #[cfg(feature = "hrtim_v2")]
159            fault_input3: FaultInput3,
160            #[cfg(feature = "hrtim_v2")]
161            fault_input4: FaultInput4,
162            #[cfg(feature = "hrtim_v2")]
163            fault_input5: FaultInput5,
164            #[cfg(feature = "hrtim_v2")]
165            fault_input6: FaultInput6,
166        }
167    }
168}
169
170pub enum FaultSamplingFilter {
171    /// No filtering, fault acts asynchronously
172    ///
173    /// Note that this bypasses any f_flts (SamplingClkDiv)
174    None = 0b0000,
175
176    /// Sample directly at rate f_hrtim, with a count of 2
177    ///
178    /// Note that this bypasses: any f_flts (SamplingClkDiv)
179    HrtimN2 = 0b0001,
180
181    /// Sample directly at rate f_hrtim, with a count of 4
182    ///
183    /// Note that this bypasses any f_flts (SamplingClkDiv)
184    HrtimN4 = 0b0010,
185
186    /// Sample directly at rate f_hrtim, with a count of 8
187    ///
188    /// Note that this bypasses any f_flts (SamplingClkDiv)
189    HrtimN8 = 0b0011,
190
191    /// Sample at rate f_flts / 2, with a count of 6
192    FltsDiv2N6 = 0b0100,
193
194    /// Sample at rate f_flts / 2, with a count of 8
195    FltsDiv2N8 = 0b0101,
196
197    /// Sample at rate f_flts / 4, with a count of 6
198    FltsDiv4N6 = 0b0110,
199
200    /// Sample at rate f_flts / 4, with a count of 8
201    FltsDiv4N8 = 0b0111,
202
203    /// Sample at rate f_flts / 8, with a count of 6
204    FltsDiv8N6 = 0b1000,
205
206    /// Sample at rate f_flts / 8, with a count of 8
207    FltsDiv8N8 = 0b1001,
208
209    /// Sample at rate f_flts / 16, with a count of 5
210    FltsDiv16N5 = 0b1010,
211
212    /// Sample at rate f_flts / 16, with a count of 6
213    FltsDiv16N6 = 0b1011,
214
215    /// Sample at rate f_flts / 16, with a count of 8
216    FltsDiv16N8 = 0b1100,
217
218    /// Sample at rate f_flts / 32, with a count of 5
219    FltsDiv32N5 = 0b1101,
220
221    /// Sample at rate f_flts / 32, with a count of 6
222    FltsDiv32N6 = 0b1110,
223
224    /// Sample at rate f_flts / 32, with a count of 8
225    FltsDiv32N8 = 0b1111,
226}
227
228macro_rules! impl_flt_monitor {
229    ($($t:ident: ($fltx:ident, $fltxc:ident, $fltxie:ident),)+) => {$(
230        #[non_exhaustive]
231        pub struct $t;
232
233        impl FaultMonitor for $t {
234            fn enable_interrupt(&mut self, _hr_control: &mut HrPwmCtrl) {
235                let common = unsafe { &*HRTIM_COMMON::ptr() };
236                common.ier().modify(|_r, w| w.$fltxie().set_bit());
237            }
238
239            fn is_fault_active(&self) -> bool {
240                let common = unsafe { &*HRTIM_COMMON::ptr() };
241                common.isr().read().$fltx().bit()
242            }
243
244            fn clear_fault(&mut self) {
245                let common = unsafe { &*HRTIM_COMMON::ptr() };
246                common.icr().write(|w| w.$fltxc().clear());
247            }
248        }
249    )+};
250}
251
252impl_flt_monitor!(
253    FltMonitorSys: (sysflt, sysfltc, sysfltie),
254    FltMonitor1: (flt1, flt1c, flt1ie),
255    FltMonitor2: (flt2, flt2c, flt2ie),
256    FltMonitor3: (flt3, flt3c, flt3ie),
257    FltMonitor4: (flt4, flt4c, flt4ie),
258    FltMonitor5: (flt5, flt5c, flt5ie),
259);
260
261#[cfg(feature = "hrtim_v2")]
262impl_flt_monitor!(
263    FltMonitor6: (flt6, flt6c, flt6ie),
264);