imxrt_hal/common/flexpwm/
ral.rs

1//! Custom RAL API for PWM submodules.
2//!
3//! The auto-generated RAL API is cumbersome. This is a macro-compatible API that's
4//! easier to work with. It focuses on de-duplicating symbols for the submodules.
5
6#![allow(unused, non_snake_case, non_upper_case_globals)] // Compatibility with RAL
7use crate::ral::{RORegister, RWRegister};
8
9/// This is SM0 from the 1060 PWM peripheral, with the
10/// '0's removed. We then use *signed* registers when the
11/// reference manual indicates a signed value.
12#[repr(C)]
13pub struct RegisterBlock {
14    /// Counter Register
15    pub SMCNT: RORegister<i16>,
16
17    /// Initial Count Register
18    pub SMINIT: RWRegister<i16>,
19
20    /// Control 2 Register
21    pub SMCTRL2: RWRegister<u16>,
22
23    /// Control Register
24    pub SMCTRL: RWRegister<u16>,
25
26    _reserved1: [u16; 1],
27
28    /// Value Register 0
29    pub SMVAL0: RWRegister<i16>,
30
31    /// Fractional Value Register 1
32    pub SMFRACVAL1: RWRegister<u16>,
33
34    /// Value Register 1
35    pub SMVAL1: RWRegister<i16>,
36
37    /// Fractional Value Register 2
38    pub SMFRACVAL2: RWRegister<u16>,
39
40    /// Value Register 2
41    pub SMVAL2: RWRegister<i16>,
42
43    /// Fractional Value Register 3
44    pub SMFRACVAL3: RWRegister<u16>,
45
46    /// Value Register 3
47    pub SMVAL3: RWRegister<i16>,
48
49    /// Fractional Value Register 4
50    pub SMFRACVAL4: RWRegister<u16>,
51
52    /// Value Register 4
53    pub SMVAL4: RWRegister<i16>,
54
55    /// Fractional Value Register 5
56    pub SMFRACVAL5: RWRegister<u16>,
57
58    /// Value Register 5
59    pub SMVAL5: RWRegister<i16>,
60
61    /// Fractional Control Register
62    pub SMFRCTRL: RWRegister<u16>,
63
64    /// Output Control Register
65    pub SMOCTRL: RWRegister<u16>,
66
67    /// Status Register
68    pub SMSTS: RWRegister<u16>,
69
70    /// Interrupt Enable Register
71    pub SMINTEN: RWRegister<u16>,
72
73    /// DMA Enable Register
74    pub SMDMAEN: RWRegister<u16>,
75
76    /// Output Trigger Control Register
77    pub SMTCTRL: RWRegister<u16>,
78
79    /// Fault Disable Mapping Register 0
80    pub SMDISMAP0: RWRegister<u16>,
81
82    /// Fault Disable Mapping Register 1
83    pub SMDISMAP1: RWRegister<u16>,
84
85    /// Deadtime Count Register 0
86    pub SMDTCNT0: RWRegister<u16>,
87
88    /// Deadtime Count Register 1
89    pub SMDTCNT1: RWRegister<u16>,
90
91    /// Capture Control A Register
92    pub SMCAPTCTRLA: RWRegister<u16>,
93
94    /// Capture Compare A Register
95    pub SMCAPTCOMPA: RWRegister<u16>,
96
97    /// Capture Control B Register
98    pub SMCAPTCTRLB: RWRegister<u16>,
99
100    /// Capture Compare B Register
101    pub SMCAPTCOMPB: RWRegister<u16>,
102
103    /// Capture Control X Register
104    pub SMCAPTCTRLX: RWRegister<u16>,
105
106    /// Capture Compare X Register
107    pub SMCAPTCOMPX: RWRegister<u16>,
108
109    /// Capture Value 0 Register
110    pub SMCVAL0: RORegister<u16>,
111
112    /// Capture Value 0 Cycle Register
113    pub SMCVAL0CYC: RORegister<u16>,
114
115    /// Capture Value 1 Register
116    pub SMCVAL1: RORegister<u16>,
117
118    /// Capture Value 1 Cycle Register
119    pub SMCVAL1CYC: RORegister<u16>,
120
121    /// Capture Value 2 Register
122    pub SMCVAL2: RORegister<u16>,
123
124    /// Capture Value 2 Cycle Register
125    pub SMCVAL2CYC: RORegister<u16>,
126
127    /// Capture Value 3 Register
128    pub SMCVAL3: RORegister<u16>,
129
130    /// Capture Value 3 Cycle Register
131    pub SMCVAL3CYC: RORegister<u16>,
132
133    /// Capture Value 4 Register
134    pub SMCVAL4: RORegister<u16>,
135
136    /// Capture Value 4 Cycle Register
137    pub SMCVAL4CYC: RORegister<u16>,
138
139    /// Capture Value 5 Register
140    pub SMCVAL5: RORegister<u16>,
141
142    /// Capture Value 5 Cycle Register
143    pub SMCVAL5CYC: RORegister<u16>,
144
145    /// Phase Delay Register
146    pub SMPHASEDLY: RWRegister<u16>,
147
148    _reserved2: [u16; 3],
149}
150
151const _: () = assert!(core::mem::size_of::<RegisterBlock>() == 0x60);
152
153/// A PWM submodule.
154///
155/// `Submodule`s implement PWM timers. Comparisons in `Submodule` value
156/// registers generate PWM outputs.
157///
158/// The PWM submodule `FlexPWM2_3` is represented as
159///
160/// ```
161/// # use imxrt_hal::flexpwm::Submodule;
162/// type PWM2_3 = Submodule<2, 3>;
163/// ```
164pub struct Submodule<const N: u8, const M: u8>(*const RegisterBlock);
165
166impl<const N: u8, const M: u8> ::core::ops::Deref for Submodule<N, M> {
167    type Target = RegisterBlock;
168    #[inline]
169    fn deref(&self) -> &Self::Target {
170        // Safety: Pointer is valid per `submodules` implementation, below.
171        // Layout of RegisterBlock is checked against the reference manual.
172        // The size of RegisterBlock is correct, meaning that we never access
173        // beyond the memory of the original pointer.
174        unsafe { &*self.0 }
175    }
176}
177
178// Safety: The pointer wrapped by Submodule points into static MMIO registers;
179// see `submodules` for specifics. That owned pointer can be sent across execution
180// contexts.
181unsafe impl<const N: u8, const M: u8> Send for Submodule<N, M> {}
182
183/// Four submodules for the `N`th PWM instance.
184pub type Submodules<const N: u8> = (
185    Submodule<N, 0>,
186    Submodule<N, 1>,
187    Submodule<N, 2>,
188    Submodule<N, 3>,
189);
190
191/// Shorthand to allocate four submodules for PWM `N`.
192pub(crate) fn submodules<const N: u8>(pwm: &crate::ral::pwm::Instance<N>) -> Submodules<N> {
193    (
194        Submodule(core::ptr::addr_of!(pwm.SM[0]) as *const _),
195        Submodule(core::ptr::addr_of!(pwm.SM[1]) as *const _),
196        Submodule(core::ptr::addr_of!(pwm.SM[2]) as *const _),
197        Submodule(core::ptr::addr_of!(pwm.SM[3]) as *const _),
198    )
199}
200
201// Export all submodule fields.
202pub use crate::ral::pwm::sm::*;