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::*;