lpc55s6x_hal/peripherals/
flexcomm.rs

1use core::ops::Deref;
2
3use crate::{
4    raw,
5    typestates::{
6        init_state,
7        ClocksSupportFlexcommToken,
8        pin::{
9            flexcomm::{
10                I2c,
11                I2s,
12                Spi,
13                Usart,
14            },
15        },
16    },
17    peripherals::syscon,
18};
19
20
21pub type Flexcomm = (
22    Flexcomm0,
23    Flexcomm1,
24    Flexcomm2,
25    Flexcomm3,
26    Flexcomm4,
27    Flexcomm5,
28    Flexcomm6,
29    Flexcomm7,
30    Flexcomm8,
31);
32
33macro_rules! flexcomm {
34    ($fc_hal:ident, $i2c_hal:ident, $i2s_hal:ident, $spi_hal:ident, $usart_hal:ident,
35     $fc_pac:ident, $i2c_pac:ident, $i2s_pac:ident, $spi_pac:ident, $usart_pac:ident,
36     $register_sel:ident
37    ) => {
38        pub struct $fc_hal<State = init_state::Unknown> {
39            pub(crate) raw_fc: raw::$fc_pac,
40            pub(crate) raw_i2c: raw::$i2c_pac,
41            pub(crate) raw_i2s: raw::$i2s_pac,
42            pub(crate) raw_spi: raw::$spi_pac,
43            pub(crate) raw_usart: raw::$usart_pac,
44            pub _state: State,
45        }
46
47        pub struct $i2c_hal<State = init_state::Enabled> {
48            pub(crate) _raw_fc: raw::$fc_pac,
49            #[allow(dead_code)]
50            pub(crate) raw: raw::$i2c_pac,
51            pub(crate) _raw_i2s: raw::$i2s_pac,
52            pub(crate) _raw_spi: raw::$spi_pac,
53            pub(crate) _raw_usart: raw::$usart_pac,
54            pub _state: State,
55        }
56
57        impl Deref for $i2c_hal {
58            type Target = raw::i2c0::RegisterBlock;
59            fn deref(&self) -> &Self::Target {
60                &self.raw
61            }
62        }
63
64        impl I2c for $i2c_hal {}
65
66        pub struct $i2s_hal<State = init_state::Enabled> {
67            pub(crate) _raw_fc: raw::$fc_pac,
68            pub(crate) _raw_i2c: raw::$i2c_pac,
69            #[allow(dead_code)]
70            pub(crate) raw: raw::$i2s_pac,
71            pub(crate) _raw_spi: raw::$spi_pac,
72            pub(crate) _raw_usart: raw::$usart_pac,
73            pub _state: State,
74        }
75
76        impl I2s for $i2s_hal {}
77
78        pub struct $spi_hal<State = init_state::Enabled> {
79            pub(crate) _raw_fc: raw::$fc_pac,
80            pub(crate) _raw_i2c: raw::$i2c_pac,
81            pub(crate) _raw_i2s: raw::$i2s_pac,
82            #[allow(dead_code)]
83            pub(crate) raw: raw::$spi_pac,
84            pub(crate) _raw_usart: raw::$usart_pac,
85            pub _state: State,
86        }
87
88        impl Deref for $spi_hal {
89            type Target = raw::spi0::RegisterBlock;
90            fn deref(&self) -> &Self::Target {
91                &self.raw
92            }
93        }
94
95        impl Spi for $spi_hal {}
96
97        pub struct $usart_hal<State = init_state::Enabled> {
98            pub(crate) _raw_fc: raw::$fc_pac,
99            pub(crate) _raw_i2c: raw::$i2c_pac,
100            pub(crate) _raw_i2s: raw::$i2s_pac,
101            pub(crate) _raw_spi: raw::$spi_pac,
102            #[allow(dead_code)]
103            pub(crate) raw: raw::$usart_pac,
104            pub _state: State,
105        }
106
107        impl Deref for $usart_hal {
108            type Target = raw::usart0::RegisterBlock;
109            fn deref(&self) -> &Self::Target {
110                &self.raw
111            }
112        }
113
114        impl Usart for $usart_hal {}
115
116        impl core::convert::From<(raw::$fc_pac, raw::$i2c_pac, raw::$i2s_pac, raw::$spi_pac, raw::$usart_pac)> for $fc_hal {
117            fn from(raw: (raw::$fc_pac, raw::$i2c_pac, raw::$i2s_pac, raw::$spi_pac, raw::$usart_pac)) -> Self {
118                $fc_hal::new(raw)
119            }
120        }
121
122        impl $fc_hal {
123            fn new(raw: (raw::$fc_pac, raw::$i2c_pac, raw::$i2s_pac, raw::$spi_pac, raw::$usart_pac)) -> Self {
124                $fc_hal {
125                    raw_fc: raw.0,
126                    raw_i2c: raw.1,
127                    raw_i2s: raw.2,
128                    raw_spi: raw.3,
129                    raw_usart: raw.4,
130                    _state: init_state::Unknown,
131                }
132            }
133
134            // pub unsafe fn steal() -> Self {
135            //     // seems a little wastefule to steal the full peripherals but ok..
136            //     Self::new(raw::Peripherals::steal().$pac_name)
137            // }
138        }
139
140        impl<State> $fc_hal<State> {
141            pub fn release(self) -> (raw::$fc_pac, raw::$i2c_pac, raw::$i2s_pac, raw::$spi_pac, raw::$usart_pac) {
142                (self.raw_fc, self.raw_i2c, self.raw_i2s, self.raw_spi, self.raw_usart)
143            }
144        }
145
146        impl $fc_hal {
147            fn enabled(&mut self, syscon: &mut syscon::Syscon) {
148                syscon.reset(&mut self.raw_fc);
149                syscon.enable_clock(&mut self.raw_fc);
150            }
151
152            pub fn enabled_as_i2c(
153                mut self,
154                syscon: &mut syscon::Syscon,
155                _clocks_token: &ClocksSupportFlexcommToken,
156            ) -> $i2c_hal<init_state::Enabled> {
157
158                // The FRG output frequency must not be higher than 48 MHz for SPI and I2S
159                // and not higher than 44 MHz for USART and I2C.
160                //
161                // Currently, we just use the 12MHz clock
162
163                syscon.raw.$register_sel().modify(|_, w| w.sel().enum_0x2()); // Fro12MHz
164
165                self.enabled(syscon);
166
167                self.raw_fc.pselid.modify(|_, w| w
168                    // select I2C function on corresponding FLEXCOMM
169                    .persel().i2c()
170                    // lock it
171                    .lock().locked()
172                );
173                assert!(self.raw_fc.pselid.read().i2cpresent().is_present());
174
175                $i2c_hal {
176                    _raw_fc: self.raw_fc,
177                    raw: self.raw_i2c,
178                    _raw_i2s: self.raw_i2s,
179                    _raw_spi: self.raw_spi,
180                    _raw_usart: self.raw_usart,
181                    _state: init_state::Enabled(()),
182                }
183            }
184
185            pub fn enabled_as_spi(
186                mut self,
187                syscon: &mut syscon::Syscon,
188                _clocks_token: &ClocksSupportFlexcommToken,
189            ) -> $spi_hal<init_state::Enabled> {
190
191                // The FRG output frequency must not be higher than 48 MHz for SPI and I2S
192                // and not higher than 44 MHz for USART and I2C.
193                //
194                // Currently, we just use the 12MHz clock
195
196                syscon.raw.$register_sel().modify(|_, w| w.sel().enum_0x2()); // Fro12MHz
197
198                self.enabled(syscon);
199
200                self.raw_fc.pselid.modify(|_, w| w
201                    // select SPI function on corresponding FLEXCOMM
202                    .persel().spi()
203                    // lock it
204                    .lock().locked()
205                );
206                assert!(self.raw_fc.pselid.read().spipresent().is_present());
207
208                $spi_hal {
209                    _raw_fc: self.raw_fc,
210                    _raw_i2c: self.raw_i2c,
211                    _raw_i2s: self.raw_i2s,
212                    raw: self.raw_spi,
213                    _raw_usart: self.raw_usart,
214                    _state: init_state::Enabled(()),
215                }
216            }
217
218            pub fn enabled_as_usart(
219                mut self,
220                syscon: &mut syscon::Syscon,
221                _clocks_token: &ClocksSupportFlexcommToken,
222            ) -> $usart_hal<init_state::Enabled> {
223
224                // The FRG output frequency must not be higher than 48 MHz for SPI and I2S
225                // and not higher than 44 MHz for USART and I2C.
226                //
227                // Currently, we just use the 12MHz clock
228
229                syscon.raw.$register_sel().modify(|_, w| w.sel().enum_0x2()); // Fro12MHz
230
231                self.enabled(syscon);
232
233                self.raw_fc.pselid.modify(|_, w| w
234                    // select USART function on corresponding FLEXCOMM
235                    .persel().usart()
236                    // lock it
237                    .lock().locked()
238                );
239                assert!(self.raw_fc.pselid.read().usartpresent().is_present());
240
241                $usart_hal {
242                    _raw_fc: self.raw_fc,
243                    _raw_i2c: self.raw_i2c,
244                    _raw_i2s: self.raw_i2s,
245                    _raw_spi: self.raw_spi,
246                    raw: self.raw_usart,
247                    _state: init_state::Enabled(()),
248                }
249            }
250        }
251    }
252}
253
254flexcomm!(Flexcomm0, I2c0, I2s0, Spi0, Usart0, FLEXCOMM0, I2C0, I2S0, SPI0, USART0, fcclksel0);
255flexcomm!(Flexcomm1, I2c1, I2s1, Spi1, Usart1, FLEXCOMM1, I2C1, I2S1, SPI1, USART1, fcclksel1);
256flexcomm!(Flexcomm2, I2c2, I2s2, Spi2, Usart2, FLEXCOMM2, I2C2, I2S2, SPI2, USART2, fcclksel2);
257flexcomm!(Flexcomm3, I2c3, I2s3, Spi3, Usart3, FLEXCOMM3, I2C3, I2S3, SPI3, USART3, fcclksel3);
258flexcomm!(Flexcomm4, I2c4, I2s4, Spi4, Usart4, FLEXCOMM4, I2C4, I2S4, SPI4, USART4, fcclksel4);
259flexcomm!(Flexcomm5, I2c5, I2s5, Spi5, Usart5, FLEXCOMM5, I2C5, I2S5, SPI5, USART5, fcclksel5);
260flexcomm!(Flexcomm6, I2c6, I2s6, Spi6, Usart6, FLEXCOMM6, I2C6, I2S6, SPI6, USART6, fcclksel6);
261flexcomm!(Flexcomm7, I2c7, I2s7, Spi7, Usart7, FLEXCOMM7, I2C7, I2S7, SPI7, USART7, fcclksel7);
262
263pub struct Flexcomm8<State = init_state::Unknown> {
264    pub(crate) raw_fc: raw::FLEXCOMM8,
265    pub(crate) raw_spi: raw::SPI8,
266    pub _state: State,
267}
268
269pub struct Spi8<State = init_state::Enabled> {
270    pub(crate) _raw_fc: raw::FLEXCOMM8,
271    #[allow(dead_code)]
272    pub(crate) raw: raw::SPI8,
273    pub _state: State,
274}
275
276impl Deref for Spi8 {
277    type Target = raw::spi0::RegisterBlock;
278    fn deref(&self) -> &Self::Target {
279        &self.raw
280    }
281}
282
283impl Spi for Spi8 {}
284
285impl core::convert::From<(raw::FLEXCOMM8, raw::SPI8)> for Flexcomm8 {
286    fn from(raw: (raw::FLEXCOMM8, raw::SPI8)) -> Self {
287        Flexcomm8::new(raw)
288    }
289}
290
291impl Flexcomm8 {
292    fn new(raw: (raw::FLEXCOMM8, raw::SPI8)) -> Self {
293        Flexcomm8 {
294            raw_fc: raw.0,
295            raw_spi: raw.1,
296            _state: init_state::Unknown,
297        }
298    }
299}
300
301impl<State> Flexcomm8<State> {
302    pub fn release(self) -> (raw::FLEXCOMM8, raw::SPI8) {
303        (self.raw_fc, self.raw_spi)
304    }
305}
306
307impl Flexcomm8 {
308    fn enabled(&mut self, syscon: &mut syscon::Syscon) {
309        syscon.reset(&mut self.raw_fc);
310        syscon.enable_clock(&mut self.raw_fc);
311    }
312
313    pub fn enabled_as_spi(
314        mut self,
315        syscon: &mut syscon::Syscon,
316        _clocks_token: &ClocksSupportFlexcommToken,
317    ) -> Spi8<init_state::Enabled> {
318
319        // NB: This is the high-speed SPI
320
321        // The FRG output frequency must not be higher than 48 MHz for SPI and I2S
322        // and not higher than 44 MHz for USART and I2C.
323        //
324        // Currently, we just use the 12MHz clock
325
326        syscon.raw.hslspiclksel.modify(|_, w| w.sel().enum_0x2()); // Fro12MHz
327
328        self.enabled(syscon);
329
330        self.raw_fc.pselid.modify(|_, w| w
331            // select SPI function on corresponding FLEXCOMM
332            .persel().spi()
333            // lock it
334            .lock().locked()
335        );
336        assert!(self.raw_fc.pselid.read().spipresent().is_present());
337
338        Spi8 {
339            _raw_fc: self.raw_fc,
340            raw: self.raw_spi,
341            _state: init_state::Enabled(()),
342        }
343    }
344
345}