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