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