stm32_hal2/
util.rs

1//! This is an internal module that contains utility functionality used by other modules.
2
3#[cfg(feature = "l4")]
4use core::ops::Deref;
5
6use cfg_if::cfg_if;
7
8// todo: L5 has a PAC bug on CCR registers past 1.
9#[cfg(any(feature = "f3", feature = "l4"))]
10use crate::dma::{self, Dma, DmaChannel, DmaInput};
11#[cfg(any(feature = "f3", feature = "l4"))]
12use crate::pac::DMA1;
13#[cfg(feature = "l4")]
14use crate::pac::dma1;
15use crate::{
16    clocks::Clocks,
17    pac::{self, rcc::RegisterBlock},
18};
19
20#[cfg(not(any(
21    feature = "f401",
22    feature = "f411",
23    feature = "f412",
24    feature = "l412",
25    feature = "wb",
26    feature = "g0",
27    feature = "c0",
28)))]
29cfg_if! {
30    if #[cfg(any(feature = "f3", feature = "l412", feature = "g4", feature = "h7b3"))] {
31        use crate::pac::DAC1;
32    } else {
33        use crate::pac::DAC as DAC1;
34    }
35}
36
37cfg_if! {
38    if #[cfg(any(feature = "g0", feature = "c0", feature = "wl"))] {
39        use crate::pac::ADC as ADC1;
40
41    } else {
42        use crate::pac::ADC1;
43    }
44}
45
46#[cfg(any(feature = "f3", feature = "l4",))]
47use crate::pac::dma1 as dma_p;
48
49/// Enables and resets peripheral clocks on various RCC registesr.
50/// The first argument is a `apb1`, `ahb2` etc to specify the reg block. The second is something like
51/// `tim1`, and the third is a `pac::RCC`.
52macro_rules! rcc_en_reset {
53    (apb1, $periph:expr, $rcc:expr) => {
54        paste::paste! { cfg_if::cfg_if! {
55            if #[cfg(any(feature = "f3", feature = "f4"))] {
56                $rcc.apb1enr().modify(|_, w| w.[<$periph en>]().bit(true));
57                $rcc.apb1rstr().modify(|_, w| w.[<$periph rst>]().bit(true));
58                $rcc.apb1rstr().modify(|_, w| w.[<$periph rst>]().clear_bit());
59            } else if #[cfg(any(feature = "l4", feature = "l5", feature = "g4", feature = "wb", feature = "wl"))] {
60                $rcc.apb1enr1().modify(|_, w| w.[<$periph en>]().bit(true));
61                $rcc.apb1rstr1().modify(|_, w| w.[<$periph rst>]().bit(true));
62                $rcc.apb1rstr1().modify(|_, w| w.[<$periph rst>]().clear_bit());
63            } else if #[cfg(any(feature = "g0", feature = "c0"))] {
64                $rcc.apbenr1().modify(|_, w| w.[<$periph en>]().bit(true));
65                $rcc.apbrstr1().modify(|_, w| w.[<$periph rst>]().bit(true));
66                $rcc.apbrstr1().modify(|_, w| w.[<$periph rst>]().clear_bit());
67            } else {  // H7
68                $rcc.apb1lenr().modify(|_, w| w.[<$periph en>]().bit(true));
69                $rcc.apb1lrstr().modify(|_, w| w.[<$periph rst>]().bit(true));
70                $rcc.apb1lrstr().modify(|_, w| w.[<$periph rst>]().clear_bit());
71                // todo: apb1h equivs
72            }
73            // todo: apb1enr2 on L5? Currently we only use it with USB, which is handled in
74            // todo `usb.rs`.
75            // todo: apb1enr2
76        }}
77    };
78    (apb2, $periph:expr, $rcc:expr) => {
79        paste::paste! { cfg_if::cfg_if! {
80            if #[cfg(any(feature = "g0", feature = "c0"))] {
81                $rcc.apbenr2().modify(|_, w| w.[<$periph en>]().bit(true));
82                $rcc.apbrstr2().modify(|_, w| w.[<$periph rst>]().bit(true));
83                $rcc.apbrstr2().modify(|_, w| w.[<$periph rst>]().clear_bit());
84            } else {
85                $rcc.apb2enr().modify(|_, w| w.[<$periph en>]().bit(true));
86                $rcc.apb2rstr().modify(|_, w| w.[<$periph rst>]().bit(true));
87                $rcc.apb2rstr().modify(|_, w| w.[<$periph rst>]().clear_bit());
88            }
89        }}
90    };
91    (apb4, $periph:expr, $rcc:expr) => {
92        paste::paste! {
93            $rcc.apb4enr().modify(|_, w| w.[<$periph en>]().bit(true));
94            $rcc.apb4rstr().modify(|_, w| w.[<$periph rst>]().bit(true));
95            $rcc.apb4rstr().modify(|_, w| w.[<$periph rst>]().clear_bit());
96        }
97    };
98    (ahb1, $periph:expr, $rcc:expr) => {
99        paste::paste! { cfg_if::cfg_if! {
100            if #[cfg(feature = "f3")] {
101                $rcc.ahbenr().modify(|_, w| w.[<$periph en>]().bit(true));
102                $rcc.ahbrstr().modify(|_, w| w.[<$periph rst>]().bit(true));
103                $rcc.ahbrstr().modify(|_, w| w.[<$periph rst>]().clear_bit());
104            } else if #[cfg(any(feature = "g0", feature = "c0"))] {
105                $rcc.ahbenr().modify(|_, w| w.[<$periph en>]().bit(true));
106                $rcc.ahbrstr().modify(|_, w| w.[<$periph rst>]().bit(true));
107                $rcc.ahbrstr().modify(|_, w| w.[<$periph rst>]().clear_bit());
108            } else {
109                $rcc.ahb1enr().modify(|_, w| w.[<$periph en>]().bit(true));
110                $rcc.ahb1rstr().modify(|_, w| w.[<$periph rst>]().bit(true));
111                $rcc.ahb1rstr().modify(|_, w| w.[<$periph rst>]().clear_bit());
112            }
113        }}
114    };
115    (ahb2, $periph:expr, $rcc:expr) => {
116        paste::paste! {
117            $rcc.ahb2enr().modify(|_, w| w.[<$periph en>]().bit(true));
118            $rcc.ahb2rstr().modify(|_, w| w.[<$periph rst>]().bit(true));
119            $rcc.ahb2rstr().modify(|_, w| w.[<$periph rst>]().clear_bit());
120        }
121    };
122    (ahb3, $periph:expr, $rcc:expr) => {
123        paste::paste! {
124            $rcc.ahb3enr().modify(|_, w| w.[<$periph en>]().bit(true));
125            $rcc.ahb3rstr().modify(|_, w| w.[<$periph rst>]().bit(true));
126            $rcc.ahb3rstr().modify(|_, w| w.[<$periph rst>]().clear_bit());
127        }
128    };
129    // C0's pac v 0.16 calls it this, although it's actually ahb4.
130    (ahb, $periph:expr, $rcc:expr) => {
131        paste::paste! {
132            $rcc.ahbenr().modify(|_, w| w.[<$periph en>]().bit(true));
133            $rcc.ahbrstr().modify(|_, w| w.[<$periph rst>]().bit(true));
134            $rcc.ahbrstr().modify(|_, w| w.[<$periph rst>]().clear_bit());
135        }
136    };
137}
138
139#[cfg(not(any(feature = "f", feature = "g0", feature = "c0", feature = "l")))]
140macro_rules! rcc_en_reset_apb1enr2 {
141    ($periph:expr, $rcc:expr) => {
142        paste::paste! {
143            $rcc.apb1enr2().modify(|_, w| w.[<$periph en>]().bit(true));
144            $rcc.apb1rstr2().modify(|_, w| w.[<$periph rst>]().bit(true));
145            $rcc.apb1rstr2().modify(|_, w| w.[<$periph rst>]().clear_bit());
146        }
147    };
148}
149
150pub(crate) use rcc_en_reset;
151
152/// Uart only. Important: This assumes we use the default UART clock.
153pub trait BaudPeriph {
154    fn baud(clock_cfg: &Clocks) -> u32;
155}
156
157impl BaudPeriph for pac::USART1 {
158    fn baud(clock_cfg: &Clocks) -> u32 {
159        clock_cfg.apb2()
160    }
161}
162
163#[cfg(not(any(feature = "wb", feature = "wl")))]
164impl BaudPeriph for pac::USART2 {
165    fn baud(clock_cfg: &Clocks) -> u32 {
166        clock_cfg.apb1()
167    }
168}
169
170#[cfg(not(any(
171    feature = "f401",
172    feature = "f410",
173    feature = "f411",
174    feature = "f412",
175    feature = "f413",
176    feature = "l4x1",
177    feature = "g0",
178    feature = "c0",
179    feature = "wb",
180    feature = "wl",
181)))]
182impl BaudPeriph for pac::USART3 {
183    fn baud(clock_cfg: &Clocks) -> u32 {
184        clock_cfg.apb1()
185    }
186}
187
188cfg_if! {
189    if #[cfg(any(feature = "l4x6", feature = "h7", feature = "f401", feature = "f407"))] {
190        #[cfg(not(feature = "f401"))]
191        impl BaudPeriph for pac::UART4 {
192            fn baud(clock_cfg: &Clocks) -> u32 {
193                clock_cfg.apb1()
194            }
195        }
196
197        #[cfg(not(feature = "f401"))]
198        impl BaudPeriph for pac::UART5 {
199            fn baud(clock_cfg: &Clocks) -> u32 {
200                clock_cfg.apb1()
201            }
202        }
203
204        #[cfg(any(feature = "h7", feature = "f401", feature = "f407"))]
205        impl BaudPeriph for pac::USART6 {
206            fn baud(clock_cfg: &Clocks) -> u32 {
207                clock_cfg.apb2()
208            }
209        }
210
211        #[cfg(feature = "h7")]
212        impl BaudPeriph for pac::UART7 {
213            fn baud(clock_cfg: &Clocks) -> u32 {
214                clock_cfg.apb1()
215            }
216        }
217
218        #[cfg(feature = "h7")]
219        impl BaudPeriph for pac::UART8 {
220            fn baud(clock_cfg: &Clocks) -> u32 {
221                clock_cfg.apb1()
222            }
223        }
224
225        #[cfg(feature = "h735")]
226        impl BaudPeriph for pac::UART9 {
227            fn baud(clock_cfg: &Clocks) -> u32 {
228                clock_cfg.apb2()
229            }
230        }
231
232        #[cfg(feature = "h735")]
233        impl BaudPeriph for pac::USART10 {
234            fn baud(clock_cfg: &Clocks) -> u32 {
235                clock_cfg.apb2()
236            }
237        }
238    }
239}
240
241#[cfg(not(any(
242    feature = "f",
243    feature = "g0",
244    feature = "c0",
245    feature = "wl",
246    feature = "l"
247)))]
248impl BaudPeriph for pac::LPUART1 {
249    fn baud(clock_cfg: &Clocks) -> u32 {
250        clock_cfg.apb1()
251    }
252}
253
254// #[cfg(not(any(
255//     feature = "f",
256//     feature = "l",
257//     feature = "g0",
258//     feature = "h7",
259//     feature = "wb",
260//     feature = "wl",
261//     feature = "g431",
262//     // todo: Which families have LPUART2?
263// )))]
264// impl BaudPeriph for pac::LPUART2 {
265//     fn baud(clock_cfg: &Clocks) -> u32 {
266//         // todo: QC this; it's a guess.
267//         clock_cfg.apb1()
268//     }
269// }
270
271// todo: This trait is currently a one-off for adc, and isn't currently used.
272pub trait VrefPeriph {
273    fn vref(clock_cfg: &Clocks) -> u32;
274}
275
276impl VrefPeriph for ADC1 {
277    fn vref(clock_cfg: &Clocks) -> u32 {
278        clock_cfg.apb2()
279    }
280}
281
282#[cfg(any(
283    feature = "l4x1",
284    feature = "l4x2",
285    feature = "l412",
286    feature = "l4x5",
287    feature = "l4x6",
288))]
289impl VrefPeriph for pac::ADC2 {
290    fn vref(clock_cfg: &Clocks) -> u32 {
291        clock_cfg.apb1()
292    }
293}
294
295#[cfg(all(feature = "g4", not(any(feature = "g431", feature = "g441"))))]
296impl VrefPeriph for pac::ADC3 {
297    fn vref(clock_cfg: &Clocks) -> u32 {
298        clock_cfg.apb1()
299    }
300}
301
302#[cfg(any(feature = "g473", feature = "g474", feature = "g483", feature = "g484"))]
303impl VrefPeriph for pac::ADC4 {
304    fn vref(clock_cfg: &Clocks) -> u32 {
305        clock_cfg.apb1()
306    }
307}
308
309#[cfg(any(feature = "g473", feature = "g474", feature = "g483", feature = "g484"))]
310impl VrefPeriph for pac::ADC5 {
311    fn vref(clock_cfg: &Clocks) -> u32 {
312        clock_cfg.apb1()
313    }
314}
315
316/// Used to provide peripheral-specific implementation for RCC enable/reset, and for F3 and L4,
317/// DMA channel assignment.
318pub trait RccPeriph {
319    fn en_reset(rcc: &RegisterBlock);
320
321    #[cfg(any(feature = "f3", feature = "l4"))]
322    fn read_chan() -> DmaChannel;
323    #[cfg(any(feature = "f3", feature = "l4"))]
324    fn write_chan() -> DmaChannel;
325    #[cfg(feature = "l4")]
326    fn read_sel<D: Deref<Target = dma1::RegisterBlock>>(regs: &mut D);
327    #[cfg(feature = "l4")]
328    fn write_sel<D: Deref<Target = dma1::RegisterBlock>>(regs: &mut D);
329}
330
331#[cfg(not(any(
332    feature = "f401",
333    feature = "f410",
334    feature = "f411",
335    feature = "g031",
336    feature = "g041",
337    feature = "g070",
338    feature = "g030",
339    feature = "g051",
340    feature = "g061",
341    feature = "c0",
342    feature = "wb",
343    feature = "wl"
344)))]
345impl RccPeriph for pac::TIM6 {
346    fn en_reset(rcc: &RegisterBlock) {
347        rcc_en_reset!(apb1, tim6, rcc);
348    }
349
350    #[cfg(any(feature = "f3", feature = "l4"))]
351    fn read_chan() -> DmaChannel {
352        unimplemented!()
353    }
354
355    #[cfg(any(feature = "f3", feature = "l4"))]
356    fn write_chan() -> DmaChannel {
357        unimplemented!()
358    }
359
360    #[cfg(feature = "l4")]
361    fn read_sel<D: Deref<Target = dma1::RegisterBlock>>(_regs: &mut D) {
362        unimplemented!()
363    }
364
365    #[cfg(feature = "l4")]
366    fn write_sel<D: Deref<Target = dma1::RegisterBlock>>(_regs: &mut D) {
367        unimplemented!()
368    }
369}
370
371#[cfg(not(any(
372    feature = "f301",
373    feature = "f302",
374    feature = "f401",
375    feature = "f410",
376    feature = "f411",
377    feature = "g031",
378    feature = "g041",
379    feature = "g070",
380    feature = "g030",
381    feature = "g051",
382    feature = "g061",
383    feature = "c0",
384    feature = "wb",
385    feature = "wl",
386    feature = "l412",
387)))]
388impl RccPeriph for pac::TIM7 {
389    fn en_reset(rcc: &RegisterBlock) {
390        rcc_en_reset!(apb1, tim7, rcc);
391    }
392
393    #[cfg(any(feature = "f3", feature = "l4"))]
394    fn read_chan() -> DmaChannel {
395        unimplemented!()
396    }
397
398    #[cfg(any(feature = "f3", feature = "l4"))]
399    fn write_chan() -> DmaChannel {
400        unimplemented!()
401    }
402
403    #[cfg(feature = "l4")]
404    fn read_sel<D: Deref<Target = dma1::RegisterBlock>>(_regs: &mut D) {
405        unimplemented!()
406    }
407
408    #[cfg(feature = "l4")]
409    fn write_sel<D: Deref<Target = dma1::RegisterBlock>>(_regs: &mut D) {
410        unimplemented!()
411    }
412}
413
414impl RccPeriph for pac::I2C1 {
415    fn en_reset(rcc: &RegisterBlock) {
416        rcc_en_reset!(apb1, i2c1, rcc);
417    }
418
419    #[cfg(any(feature = "f3", feature = "l4"))]
420    fn read_chan() -> DmaChannel {
421        DmaInput::I2c1Rx.dma1_channel()
422    }
423
424    #[cfg(any(feature = "f3", feature = "l4"))]
425    fn write_chan() -> DmaChannel {
426        DmaInput::I2c1Tx.dma1_channel()
427    }
428
429    #[cfg(feature = "l4")]
430    fn read_sel<D: Deref<Target = dma1::RegisterBlock>>(regs: &mut D) {
431        dma::channel_select(regs, DmaInput::I2c1Rx);
432    }
433
434    #[cfg(feature = "l4")]
435    fn write_sel<D: Deref<Target = dma1::RegisterBlock>>(regs: &mut D) {
436        dma::channel_select(regs, DmaInput::I2c1Tx);
437    }
438}
439
440#[cfg(not(any(feature = "wb", feature = "f3x4", feature = "c0")))]
441impl RccPeriph for pac::I2C2 {
442    fn en_reset(rcc: &RegisterBlock) {
443        rcc_en_reset!(apb1, i2c2, rcc);
444    }
445
446    #[cfg(any(feature = "f3", feature = "l4"))]
447    fn read_chan() -> DmaChannel {
448        DmaInput::I2c2Rx.dma1_channel()
449    }
450
451    #[cfg(any(feature = "f3", feature = "l4"))]
452    fn write_chan() -> DmaChannel {
453        DmaInput::I2c2Tx.dma1_channel()
454    }
455
456    #[cfg(feature = "l4")]
457    fn read_sel<D: Deref<Target = dma1::RegisterBlock>>(regs: &mut D) {
458        dma::channel_select(regs, DmaInput::I2c2Rx);
459    }
460
461    #[cfg(feature = "l4")]
462    fn write_sel<D: Deref<Target = dma1::RegisterBlock>>(regs: &mut D) {
463        dma::channel_select(regs, DmaInput::I2c2Tx);
464    }
465}
466
467#[cfg(any(feature = "h7", feature = "wb"))]
468impl RccPeriph for pac::I2C3 {
469    fn en_reset(rcc: &RegisterBlock) {
470        rcc_en_reset!(apb1, i2c3, rcc);
471    }
472}
473
474#[cfg(feature = "h7")]
475impl RccPeriph for pac::I2C4 {
476    fn en_reset(rcc: &RegisterBlock) {
477        rcc_en_reset!(apb4, i2c4, rcc);
478    }
479}
480
481#[cfg(not(feature = "f301"))] // todo: Not sure what's going on  here.
482impl RccPeriph for pac::SPI1 {
483    fn en_reset(rcc: &RegisterBlock) {
484        rcc_en_reset!(apb2, spi1, rcc);
485    }
486
487    #[cfg(any(feature = "f3", feature = "l4"))]
488    fn read_chan() -> DmaChannel {
489        DmaInput::Spi1Rx.dma1_channel()
490    }
491
492    #[cfg(any(feature = "f3", feature = "l4"))]
493    fn write_chan() -> DmaChannel {
494        DmaInput::Spi1Tx.dma1_channel()
495    }
496
497    #[cfg(feature = "l4")]
498    fn read_sel<D: Deref<Target = dma1::RegisterBlock>>(regs: &mut D) {
499        dma::channel_select(regs, DmaInput::Spi1Rx);
500    }
501
502    #[cfg(feature = "l4")]
503    fn write_sel<D: Deref<Target = dma1::RegisterBlock>>(regs: &mut D) {
504        dma::channel_select(regs, DmaInput::Spi1Tx);
505    }
506}
507
508#[cfg(not(any(
509    feature = "f3x4",
510    feature = "wb",
511    feature = "wl",
512    feature = "c0",
513    feature = "g061"
514)))]
515impl RccPeriph for pac::SPI2 {
516    fn en_reset(rcc: &RegisterBlock) {
517        rcc_en_reset!(apb1, spi2, rcc);
518    }
519
520    #[cfg(any(feature = "f3", feature = "l4"))]
521    fn read_chan() -> DmaChannel {
522        DmaInput::Spi2Rx.dma1_channel()
523    }
524
525    #[cfg(any(feature = "f3", feature = "l4"))]
526    fn write_chan() -> DmaChannel {
527        DmaInput::Spi2Tx.dma1_channel()
528    }
529
530    #[cfg(feature = "l4")]
531    fn read_sel<D: Deref<Target = dma1::RegisterBlock>>(regs: &mut D) {
532        dma::channel_select(regs, DmaInput::Spi2Rx);
533    }
534
535    #[cfg(feature = "l4")]
536    fn write_sel<D: Deref<Target = dma1::RegisterBlock>>(regs: &mut D) {
537        dma::channel_select(regs, DmaInput::Spi2Tx);
538    }
539}
540
541#[cfg(not(any(
542    feature = "f3x4",
543    feature = "f410",
544    feature = "g0",
545    feature = "c0",
546    feature = "wb",
547    feature = "wl",
548    feature = "l412",
549)))]
550impl RccPeriph for pac::SPI3 {
551    fn en_reset(rcc: &RegisterBlock) {
552        cfg_if! {
553            // Note `sp3en` mixed with `spi3rst`; why we can't use the usual macro.
554            if #[cfg(feature = "l5")] {
555                rcc.apb1enr1().modify(|_, w| w.sp3en().bit(true));
556                rcc.apb1rstr1().modify(|_, w| w.spi3rst().bit(true));
557                rcc.apb1rstr1().modify(|_, w| w.spi3rst().clear_bit());
558            } else {
559                rcc_en_reset!(apb1, spi3, rcc);
560            }
561        }
562    }
563
564    #[cfg(any(feature = "f3", feature = "l4"))]
565    fn read_chan() -> DmaChannel {
566        DmaInput::Spi3Rx.dma1_channel()
567    }
568
569    #[cfg(any(feature = "f3", feature = "l4"))]
570    fn write_chan() -> DmaChannel {
571        DmaInput::Spi3Tx.dma1_channel()
572    }
573
574    #[cfg(feature = "l4")]
575    fn read_sel<D: Deref<Target = dma1::RegisterBlock>>(regs: &mut D) {
576        dma::channel_select(regs, DmaInput::Spi3Rx);
577    }
578
579    #[cfg(feature = "l4")]
580    fn write_sel<D: Deref<Target = dma1::RegisterBlock>>(regs: &mut D) {
581        dma::channel_select(regs, DmaInput::Spi3Tx);
582    }
583}
584
585#[cfg(feature = "h7")]
586impl RccPeriph for pac::SPI4 {
587    fn en_reset(rcc: &RegisterBlock) {
588        cfg_if! {
589            // Note `sp4en` mixed with `spi4rst`; why we can't use the usual macro.
590            if #[cfg(feature = "l5")] {
591                rcc.apb2enr1().modify(|_, w| w.sp4en().bit(true));
592                rcc.apb2rstr1.modify(|_, w| w.spi4rst().bit(true));
593                rcc.apb2rstr1.modify(|_, w| w.spi4rst().clear_bit());
594            } else {
595                rcc_en_reset!(apb2, spi4, rcc);
596            }
597        }
598    }
599}
600
601#[cfg(not(any(
602    feature = "f3",
603    feature = "f4",
604    feature = "g0",
605    feature = "c0",
606    feature = "g4", // todo: G4 PAC issue re getting channel-specific reg blocks.
607    feature = "h7b3",
608    feature = "wl",
609    feature = "l412",
610)))]
611impl RccPeriph for pac::SAI1 {
612    fn en_reset(rcc: &RegisterBlock) {
613        rcc_en_reset!(apb2, sai1, rcc);
614    }
615
616    #[cfg(any(feature = "f3", feature = "l4"))]
617    fn read_chan() -> DmaChannel {
618        unimplemented!()
619    }
620
621    #[cfg(any(feature = "f3", feature = "l4"))]
622    fn write_chan() -> DmaChannel {
623        unimplemented!()
624    }
625
626    #[cfg(feature = "l4")]
627    fn read_sel<D: Deref<Target = dma1::RegisterBlock>>(_regs: &mut D) {
628        unimplemented!()
629    }
630
631    #[cfg(feature = "l4")]
632    fn write_sel<D: Deref<Target = dma1::RegisterBlock>>(_regs: &mut D) {
633        unimplemented!()
634    }
635}
636
637#[cfg(all(feature = "h7", not(feature = "h735")))]
638impl RccPeriph for pac::SAI2 {
639    fn en_reset(rcc: &RegisterBlock) {
640        rcc_en_reset!(apb2, sai2, rcc);
641    }
642
643    #[cfg(any(feature = "f3", feature = "l4"))]
644    fn read_chan() -> DmaChannel {
645        unimplemented!()
646    }
647
648    #[cfg(any(feature = "f3", feature = "l4"))]
649    fn write_chan() -> DmaChannel {
650        unimplemented!()
651    }
652
653    #[cfg(feature = "l4")]
654    fn read_sel<D: Deref<Target = dma1::RegisterBlock>>(_regs: &mut D) {
655        unimplemented!()
656    }
657
658    #[cfg(feature = "l4")]
659    fn write_sel<D: Deref<Target = dma1::RegisterBlock>>(_regs: &mut D) {
660        unimplemented!()
661    }
662}
663
664#[cfg(all(feature = "h7", not(feature = "h735")))]
665impl RccPeriph for pac::SAI3 {
666    fn en_reset(rcc: &RegisterBlock) {
667        rcc_en_reset!(apb2, sai3, rcc);
668    }
669
670    #[cfg(any(feature = "f3", feature = "l4"))]
671    fn read_chan() -> DmaChannel {
672        unimplemented!()
673    }
674
675    #[cfg(any(feature = "f3", feature = "l4"))]
676    fn write_chan() -> DmaChannel {
677        unimplemented!()
678    }
679
680    #[cfg(feature = "l4")]
681    fn read_sel<D: Deref<Target = dma1::RegisterBlock>>(_regs: &mut D) {
682        unimplemented!()
683    }
684
685    #[cfg(feature = "l4")]
686    fn write_sel<D: Deref<Target = dma1::RegisterBlock>>(_regs: &mut D) {
687        unimplemented!()
688    }
689}
690
691#[cfg(feature = "h7")]
692impl RccPeriph for pac::SAI4 {
693    fn en_reset(rcc: &RegisterBlock) {
694        rcc_en_reset!(apb4, sai4, rcc);
695    }
696
697    #[cfg(any(feature = "f3", feature = "l4"))]
698    fn read_chan() -> DmaChannel {
699        unimplemented!()
700    }
701
702    #[cfg(any(feature = "f3", feature = "l4"))]
703    fn write_chan() -> DmaChannel {
704        unimplemented!()
705    }
706
707    #[cfg(feature = "l4")]
708    fn read_sel<D: Deref<Target = dma1::RegisterBlock>>(_regs: &mut D) {
709        unimplemented!()
710    }
711
712    #[cfg(feature = "l4")]
713    fn write_sel<D: Deref<Target = dma1::RegisterBlock>>(_regs: &mut D) {
714        unimplemented!()
715    }
716}
717
718// #[cfg(any(feature = "g0c1", feature = "g4", feature = "h7"))]
719// impl RccPeriph for pac::FDCAN {
720//     #[cfg(feature = "g4")]
721//     fn en_reset(rcc: &RegisterBlock) {
722//         rcc_en_reset!(apb1, fdcan, rcc);
723//     }
724//
725//     #[cfg(not(feature = "g4"))]
726//     fn en_reset(rcc: &RegisterBlock) {
727//         rcc_en_reset!(apb1, fdcan1, rcc);
728//     }
729//
730//     #[cfg(any(feature = "f3", feature = "l4"))]
731//     fn read_chan() -> DmaChannel {
732//         unimplemented!()
733//     }
734//
735//     #[cfg(any(feature = "f3", feature = "l4"))]
736//     fn write_chan() -> DmaChannel {
737//         unimplemented!()
738//     }
739//
740//     #[cfg(feature = "l4")]
741//     fn read_sel<D: Deref<Target = dma1::RegisterBlock>>(_regs: &mut D) {
742//         unimplemented!()
743//     }
744//
745//     #[cfg(feature = "l4")]
746//     fn write_sel<D: Deref<Target = dma1::RegisterBlock>>(_regs: &mut D) {
747//         unimplemented!()
748//     }
749// }
750
751impl RccPeriph for pac::USART1 {
752    fn en_reset(rcc: &RegisterBlock) {
753        rcc_en_reset!(apb2, usart1, rcc);
754    }
755
756    #[cfg(any(feature = "f3", feature = "l4"))]
757    fn read_chan() -> DmaChannel {
758        DmaInput::Usart1Rx.dma1_channel()
759    }
760
761    #[cfg(any(feature = "f3", feature = "l4"))]
762    fn write_chan() -> DmaChannel {
763        DmaInput::Usart1Tx.dma1_channel()
764    }
765
766    #[cfg(feature = "l4")]
767    fn read_sel<D: Deref<Target = dma1::RegisterBlock>>(regs: &mut D) {
768        dma::channel_select(regs, DmaInput::Usart1Rx);
769    }
770
771    #[cfg(feature = "l4")]
772    fn write_sel<D: Deref<Target = dma1::RegisterBlock>>(regs: &mut D) {
773        dma::channel_select(regs, DmaInput::Usart1Tx);
774    }
775}
776
777#[cfg(not(any(feature = "wb", feature = "wl")))]
778impl RccPeriph for pac::USART2 {
779    fn en_reset(rcc: &RegisterBlock) {
780        cfg_if! {
781            if #[cfg(not(feature = "f4"))] {
782                rcc_en_reset!(apb1, usart2, rcc);
783            } else {
784                // `usart` vs `uart`
785                rcc.apb1enr().modify(|_, w| w.usart2en().bit(true));
786                rcc.apb1rstr().modify(|_, w| w.usart2rst().bit(true));
787                rcc.apb1rstr().modify(|_, w| w.usart2rst().clear_bit());
788            }
789        }
790    }
791
792    #[cfg(any(feature = "f3", feature = "l4"))]
793    fn read_chan() -> DmaChannel {
794        DmaInput::Usart2Rx.dma1_channel()
795    }
796
797    #[cfg(any(feature = "f3", feature = "l4"))]
798    fn write_chan() -> DmaChannel {
799        DmaInput::Usart2Tx.dma1_channel()
800    }
801
802    #[cfg(feature = "l4")]
803    fn read_sel<D: Deref<Target = dma1::RegisterBlock>>(regs: &mut D) {
804        dma::channel_select(regs, DmaInput::Usart2Rx);
805    }
806
807    #[cfg(feature = "l4")]
808    fn write_sel<D: Deref<Target = dma1::RegisterBlock>>(regs: &mut D) {
809        dma::channel_select(regs, DmaInput::Usart2Tx);
810    }
811}
812
813#[cfg(not(any(
814    feature = "f401",
815    feature = "f410",
816    feature = "f411",
817    feature = "f412",
818    feature = "f413",
819    feature = "l4x1",
820    feature = "g0",
821    feature = "c0",
822    feature = "wb",
823    feature = "wl",
824)))]
825impl RccPeriph for pac::USART3 {
826    fn en_reset(rcc: &RegisterBlock) {
827        cfg_if! {
828            if #[cfg(not(feature = "f4"))] {
829                rcc_en_reset!(apb1, usart3, rcc);
830            } else {
831                rcc.apb1enr().modify(|_, w| w.usart3en().bit(true));
832                rcc.apb1rstr().modify(|_, w| w.usart3rst().bit(true));
833                rcc.apb1rstr().modify(|_, w| w.usart3rst().clear_bit());
834            }
835        }
836    }
837
838    #[cfg(any(feature = "f3", feature = "l4"))]
839    fn read_chan() -> DmaChannel {
840        DmaInput::Usart3Rx.dma1_channel()
841    }
842
843    #[cfg(any(feature = "f3", feature = "l4"))]
844    fn write_chan() -> DmaChannel {
845        DmaInput::Usart3Tx.dma1_channel()
846    }
847
848    #[cfg(feature = "l4")]
849    fn read_sel<D: Deref<Target = dma1::RegisterBlock>>(regs: &mut D) {
850        dma::channel_select(regs, DmaInput::Usart3Rx);
851    }
852
853    #[cfg(feature = "l4")]
854    fn write_sel<D: Deref<Target = dma1::RegisterBlock>>(regs: &mut D) {
855        dma::channel_select(regs, DmaInput::Usart3Tx);
856    }
857}
858
859cfg_if! {
860    if #[cfg(any(feature = "l4x6", feature = "g473", feature = "g474", feature = "g483", feature = "g484", feature = "h7", feature = "f401", feature = "f407"))] {
861        #[cfg(not(feature = "f401"))]
862        impl RccPeriph for pac::UART4 {
863            fn en_reset(rcc: &RegisterBlock) {
864                rcc_en_reset!(apb1, uart4, rcc);
865            }
866
867             #[cfg(feature = "l4")]
868            fn read_chan() -> DmaChannel {
869                DmaInput::Uart4Rx.dma1_channel()
870            }
871
872            #[cfg(feature = "l4")]
873            fn write_chan() -> DmaChannel {
874                DmaInput::Uart4Tx.dma1_channel()
875            }
876
877            #[cfg(feature = "l4")]
878            fn read_sel<D: Deref<Target = dma1::RegisterBlock>>(regs: &mut D) {
879                dma::channel_select(regs, DmaInput::Uart4Rx);
880            }
881
882            #[cfg(feature = "l4")]
883            fn write_sel<D: Deref<Target = dma1::RegisterBlock>>(regs: &mut D) {
884                dma::channel_select(regs, DmaInput::Uart4Tx);
885            }
886        }
887
888        #[cfg(not(feature = "f401"))]
889        impl RccPeriph for pac::UART5 {
890            fn en_reset(rcc: &RegisterBlock) {
891                rcc_en_reset!(apb1, uart5, rcc);
892            }
893
894            #[cfg(feature = "l4")]
895            fn read_chan() -> DmaChannel {
896                DmaInput::Uart5Rx.dma1_channel()
897            }
898
899            #[cfg(feature = "l4")]
900            fn write_chan() -> DmaChannel {
901                DmaInput::Uart5Tx.dma1_channel()
902            }
903
904            #[cfg(feature = "l4")]
905            fn read_sel<D: Deref<Target = dma1::RegisterBlock>>(regs: &mut D) {
906                dma::channel_select(regs, DmaInput::Uart5Rx);
907            }
908
909            #[cfg(feature = "l4")]
910            fn write_sel<D: Deref<Target = dma1::RegisterBlock>>(regs: &mut D) {
911                dma::channel_select(regs, DmaInput::Uart5Tx);
912            }
913        }
914
915        #[cfg(any(feature = "h7", feature = "f401", feature = "f407"))]
916        impl RccPeriph for pac::USART6 {
917            fn en_reset(rcc: &RegisterBlock) {
918                rcc_en_reset!(apb2, usart6, rcc);
919            }
920        }
921
922        #[cfg(feature = "h7")]
923        impl RccPeriph for pac::UART7 {
924            fn en_reset(rcc: &RegisterBlock) {
925                rcc_en_reset!(apb1, uart7, rcc);
926            }
927        }
928
929        #[cfg(feature = "h7")]
930        impl RccPeriph for pac::UART8 {
931            fn en_reset(rcc: &RegisterBlock) {
932                rcc_en_reset!(apb1, uart8, rcc);
933            }
934        }
935
936        #[cfg(feature = "h735")]
937        impl RccPeriph for pac::UART9 {
938            fn en_reset(rcc: &RegisterBlock) {
939                rcc_en_reset!(apb2, uart9, rcc);
940            }
941        }
942
943        #[cfg(feature = "h735")]
944        impl RccPeriph for pac::USART10 {
945            fn en_reset(rcc: &RegisterBlock) {
946                rcc_en_reset!(apb2, usart10, rcc);
947            }
948        }
949    }
950}
951
952#[cfg(not(any(
953    feature = "f",
954    feature = "g0",
955    feature = "wl",
956    feature = "l",
957    feature = "c0"
958)))]
959impl RccPeriph for pac::LPUART1 {
960    fn en_reset(rcc: &RegisterBlock) {
961        #[cfg(not(feature = "h7"))]
962        rcc_en_reset_apb1enr2!(lpuart1, rcc);
963
964        #[cfg(feature = "h7")]
965        rcc_en_reset!(apb4, lpuart1, rcc);
966    }
967
968    #[cfg(feature = "l4")]
969    fn read_chan() -> DmaChannel {
970        DmaInput::LPuart1Rx.dma1_channel()
971    }
972
973    #[cfg(feature = "l4")]
974    fn write_chan() -> DmaChannel {
975        DmaInput::Lpuart1Tx.dma1_channel()
976    }
977
978    #[cfg(feature = "l4")]
979    fn read_sel<D: Deref<Target = dma1::RegisterBlock>>(regs: &mut D) {
980        dma::channel_select(regs, DmaInput::Lpuart1Rx);
981    }
982
983    #[cfg(feature = "l4")]
984    fn write_sel<D: Deref<Target = dma1::RegisterBlock>>(regs: &mut D) {
985        dma::channel_select(regs, DmaInput::Lpuart1Tx);
986    }
987}
988
989// #[cfg(not(any(
990//     feature = "f",
991//     feature = "l",
992//     feature = "g0",
993//     feature = "h7",
994//     feature = "wb",
995//     feature = "wl",
996//     feature = "g431"
997// )))]
998// impl RccPeriph for pac::LPUART2 {
999//     fn en_reset(rcc: &RegisterBlock) {
1000//         rcc_en_reset_apb1enr2!(lpuart2, rcc);
1001//     }
1002
1003//     #[cfg(feature = "l4")]
1004//     fn read_chan() -> DmaChannel {
1005//         DmaInput::LPuart2Rx.dma1_channel()
1006//     }
1007
1008//     #[cfg(feature = "l4")]
1009//     fn write_chan() -> DmaChannel {
1010//         DmaInput::Lpuart2Tx.dma1_channel()
1011//     }
1012
1013//     #[cfg(feature = "l4")]
1014//     fn read_sel<D: Deref<Target = dma1::RegisterBlock>>(regs: &mut D) {
1015//         dma::channel_select(regs, DmaInput::Lpuart2Rx);
1016//     }
1017
1018//     #[cfg(feature = "l4")]
1019//     fn write_sel<D: Deref<Target = dma1::RegisterBlock>>(regs: &mut D) {
1020//         dma::channel_select(regs, DmaInput::Lpuart2Tx);
1021//     }
1022// }
1023
1024#[cfg(not(any(
1025    feature = "f401",
1026    feature = "f411",
1027    feature = "f412",
1028    feature = "wb",
1029    feature = "g0",
1030    feature = "c0",
1031    feature = "l412",
1032)))]
1033cfg_if! {
1034    if #[cfg(all(feature = "h7", not(feature = "h7b3")))] {
1035        impl RccPeriph for DAC1 {
1036            fn en_reset(rcc: &RegisterBlock) {
1037                rcc_en_reset!(apb1, dac12, rcc);
1038            }
1039        }
1040    } else if #[cfg(feature = "f3")] {
1041        impl RccPeriph for DAC1 {
1042            fn en_reset(rcc: &RegisterBlock) {
1043                rcc_en_reset!(apb1, dac1, rcc);
1044            }
1045            fn read_chan() -> DmaChannel {unimplemented!()}
1046
1047            fn write_chan() -> DmaChannel {unimplemented!()}
1048        }
1049
1050        #[cfg(any(feature = "f303", feature = "f373", feature = "f3x4"))]
1051        impl RccPeriph for pac::DAC2 {
1052            fn en_reset(rcc: &RegisterBlock) {
1053                rcc_en_reset!(apb1, dac2, rcc);
1054            }
1055            fn read_chan() -> DmaChannel {unimplemented!()}
1056
1057            fn write_chan() -> DmaChannel {unimplemented!()}
1058        }
1059    } else if #[cfg(feature = "g4")] {
1060        impl RccPeriph for DAC1 {
1061            fn en_reset(rcc: &RegisterBlock) {
1062                rcc_en_reset!(ahb2, dac1, rcc);
1063            }
1064        }
1065
1066        impl RccPeriph for pac::DAC2 {
1067            fn en_reset(rcc: &RegisterBlock) {
1068                rcc_en_reset!(ahb2, dac2, rcc);
1069            }
1070        }
1071
1072        impl RccPeriph for pac::DAC3 {
1073            fn en_reset(rcc: &RegisterBlock) {
1074                rcc_en_reset!(ahb2, dac3, rcc);
1075            }
1076        }
1077
1078        impl RccPeriph for pac::DAC4 {
1079            fn en_reset(rcc: &RegisterBlock) {
1080                rcc_en_reset!(ahb2, dac4, rcc);
1081            }
1082        }
1083    } else if #[cfg(feature = "h5")] {
1084        impl RccPeriph for DAC1 {
1085            fn en_reset(rcc: &RegisterBlock) {
1086                // todo: Should be DAC1 PAC-side.
1087                rcc_en_reset!(ahb2, dac12, rcc);
1088            }
1089        }
1090    } else if #[cfg(feature = "f4")] {
1091        // F4 only uses 1 enable, despite having 2 devices. (each with 1 channel)
1092        impl RccPeriph for DAC1 {
1093            fn en_reset(rcc: &RegisterBlock) {
1094                rcc_en_reset!(apb1, dac, rcc);
1095            }
1096        }
1097    } else {
1098        impl RccPeriph for DAC1 {
1099            fn en_reset(rcc: &RegisterBlock) {
1100                #[cfg(feature = "wl")]
1101                rcc.apb1enr1().modify(|_, w| w.dac1en().bit(true));
1102                #[cfg(not(feature = "wl"))]
1103                rcc_en_reset!(apb1, dac1, rcc);
1104            }
1105
1106            #[cfg(feature = "l4")]
1107            fn read_chan() -> DmaChannel {unimplemented!()}
1108
1109            #[cfg(feature = "l4")]
1110            fn write_chan() -> DmaChannel {unimplemented!()}
1111
1112            #[cfg(feature = "l4")]
1113            fn read_sel<D: Deref<Target = dma1::RegisterBlock>>(_regs: &mut D) {unimplemented!()}
1114
1115            #[cfg(feature = "l4")]
1116            fn write_sel<D: Deref<Target = dma1::RegisterBlock>>(_regs: &mut D) {unimplemented!()}
1117        }
1118    }
1119}
1120
1121// todo: APB1LR2 on L5, and AHB4 on H7. Fix it. (I2C4)
1122// I2cDevice::Four => {
1123
1124// We currently only set up DAC1 DMA, and it's split by channels, not device.
1125
1126// todo: Use thsi approach for USART and SAI. When you un-macro them, ADC and Timer as well.
1127
1128// todo: ADC DMA on F3 and L4. Note that they're not currently set up as `RccPeripheral`,.
1129
1130// #[cfg(any(feature = "f3", feature = "l4"))]
1131// impl DmaPeriph for ADC1 {
1132//     #[cfg(any(feature = "f3", feature = "l4"))]
1133//     fn read_chan() -> DmaChannel {
1134//         DmaInput::Adc1.dma1_channel()
1135//     }
1136//
1137//     #[cfg(any(feature = "f3", feature = "l4"))]
1138//     fn write_chan() -> DmaChannel {
1139//         unimplemented!()
1140//     }
1141//
1142//     #[cfg(feature = "l4")]
1143//     fn read_sel<D: Deref<Target = dma1::RegisterBlock>>(dma: &mut Dma<D>) {
1144//         dma.channel_select(DmaInput::Adc1);
1145//     }
1146//
1147//     #[cfg(feature = "l4")]
1148//     fn write_sel<D: Deref<Target = dma1::RegisterBlock>>(dma: &mut Dma<D>) {
1149//         unimplemented!()
1150//     }
1151// }
1152//
1153// #[cfg(any(
1154//     feature = "l4x1",
1155//     feature = "l4x2",
1156//     feature = "l412",
1157//     feature = "l4x5",
1158//     feature = "l4x6",
1159// ))]
1160// impl DmaPeriph for pac::ADC2 {
1161//     #[cfg(any(feature = "f3", feature = "l4"))]
1162//     fn read_chan() -> DmaChannel {
1163//         DmaInput::Adc2.dma1_channel()
1164//     }
1165//
1166//     #[cfg(any(feature = "f3", feature = "l4"))]
1167//     fn write_chan() -> DmaChannel {
1168//         unimplemented!()
1169//     }
1170//
1171//     #[cfg(feature = "l4")]
1172//     fn read_sel<D: Deref<Target = dma1::RegisterBlock>>(dma: &mut Dma<D>) {
1173//         dma.channel_select(DmaInput::Adc2);
1174//     }
1175//
1176//     #[cfg(feature = "l4")]
1177//     fn write_sel<D: Deref<Target = dma1::RegisterBlock>>(dma: &mut Dma<D>) {
1178//         unimplemented!()
1179//     }
1180// }
1181
1182// L4 and F3 only have DMA on ADC 1 and 2.