stm32h7xx_hal/rcc/
rec.rs

1//! Peripheral Reset and Enable Control (REC)
2//!
3//! This module contains safe accessors to the RCC functionality for each
4//! peripheral.
5//!
6//! At a minimum each peripheral implements
7//! [ResetEnable](trait.ResetEnable.html). Peripherals that have an
8//! individual clock multiplexer in the PKSU also have methods
9//! `kernel_clk_mux` and `get_kernel_clk_mux`. These set and get the state
10//! of the kernel clock multiplexer respectively.
11//!
12//! Peripherals that share a clock multiplexer in the PKSU with other
13//! peripherals implement a trait with a `get_kernel_clk_mux` method that
14//! returns the current kernel clock state. Because the kernel_clk_mux is shared
15//! between multiple peripherals, it cannot be set by any individual one of
16//! them. Instead it can only be set by methods on the
17//! [`PeripheralRec`](struct.PeripheralREC.html) itself. These methods are named
18//! `kernel_xxxx_clk_mux()`.
19//!
20//! # Reset/Enable Example
21//!
22//! ```
23//! // Constrain and Freeze power
24//! ...
25//! let rcc = dp.RCC.constrain();
26//! let ccdr = rcc.sys_ck(100.MHz()).freeze(pwrcfg, &dp.SYSCFG);
27//!
28//! // Enable the clock to a peripheral and reset it
29//! ccdr.peripheral.FDCAN.enable().reset();
30//! ```
31//!
32//! # Individual Kernel Clock Example
33//! ```
34//! let ccdr = ...; // Returned by `freeze()`, see example above
35//!
36//! // Set individual kernel clock
37//! let cec_prec = ccdr.peripheral.CEC.kernel_clk_mux(CecClkSel::LSI);
38//!
39//! assert_eq!(cec_prec.get_kernel_clk_mux(), CecClkSel::LSI);
40//! ```
41//!
42//! # Group Kernel Clock Example
43//! ```
44//! let mut ccdr = ...; // Returned by `freeze()`, see example above
45//!
46//! // Set group kernel clock mux
47//! ccdr.peripheral.kernel_i2c123_clk_mux(I2c123ClkSel::PLL3_R);
48//!
49//! // Enable and reset peripheral
50//! let i2c3_prec = ccdr.peripheral.I2C3.enable().reset();
51//!
52//! assert_eq!(i2c3_prec.get_kernel_clk_mux(), I2c123ClkSel::PLL3_R);
53//!
54//! // Some method that consumes the i2c3 prec
55//! init_i2c3(..., i2c3_prec);
56//!
57//! // Can't set group kernel clock (it would also affect I2C3)
58//! // ccdr.peripheral.kernel_i2c123_clk_mux(I2c123ClkSel::HSI_KER);
59//! ```
60//!
61//! # REC object
62//!
63//! There is a REC object for each peripheral. For example:
64//!
65//! ```
66//! let rec_object = ccdr.peripheral.FDCAN;
67//! ```
68//!
69//! If REC object is dropped by user code, then the Reset or Enable state of
70//! this peripheral cannot be modified for the lifetime of the program.
71#![deny(missing_docs)]
72
73use core::marker::PhantomData;
74
75use super::Rcc;
76use crate::stm32::{rcc, RCC};
77use cortex_m::interrupt;
78
79/// A trait for Resetting, Enabling and Disabling a single peripheral
80pub trait ResetEnable {
81    /// Enable this peripheral
82    #[allow(clippy::return_self_not_must_use)]
83    fn enable(self) -> Self;
84    /// Disable this peripheral
85    #[allow(clippy::return_self_not_must_use)]
86    fn disable(self) -> Self;
87    /// Reset this peripheral
88    #[allow(clippy::return_self_not_must_use)]
89    fn reset(self) -> Self;
90}
91
92/// The clock gating state of a peripheral in low-power mode
93///
94/// See RM0433 rev 7. Section 8.5.11
95#[derive(Default, Copy, Clone, PartialEq, Eq)]
96pub enum LowPowerMode {
97    /// Kernel and bus interface clocks are not provided in low-power modes.
98    Off,
99    /// Kernel and bus interface clocks are provided in CSleep mode.
100    #[default]
101    Enabled,
102    /// Kernel and bus interface clocks are provided in both CSleep and CStop
103    /// modes. Only applies to peripherals in the D3 / SRD. If the peripheral is
104    /// not in the D3 / SRD then this has the same effect as `Enabled`.
105    Autonomous,
106}
107
108impl Rcc {
109    /// Returns all the peripherals resets / enables / kernel clocks.
110    ///
111    /// # Use case
112    ///
113    /// Allows peripherals to be reset / enabled before the calling
114    /// freeze. For example, the internal watchdog could be enabled to
115    /// issue a reset if the call to freeze hangs waiting for an external
116    /// clock that is stopped.
117    ///
118    /// # Safety
119    ///
120    /// If this method is called multiple times, or is called before the
121    /// [freeze](struct.Rcc.html#freeze), then multiple accesses to the
122    /// same memory exist.
123    #[inline]
124    pub unsafe fn steal_peripheral_rec(&self) -> PeripheralREC {
125        PeripheralREC::new_singleton()
126    }
127}
128
129// This macro uses the paste::item! macro to create identifiers.
130//
131// https://crates.io/crates/paste
132macro_rules! peripheral_reset_and_enable_control {
133    ($( #[ $tmeta:meta ] $AXBn:ident, $axb_doc:expr => [
134        $(
135            $( #[ $pmeta:meta ] )*
136                $(($Auto:ident))* $p:ident
137                $([ kernel $clk:ident: $pk:ident $(($Variant:ident))* $ccip:ident $clk_doc:expr ])*
138                $([ group clk: $pk_g:ident $( $(($Variant_g:ident))* $ccip_g:ident $clk_doc_g:expr )* ])*
139                $([ fixed clk: $clk_doc_f:expr ])*
140        ),*
141    ];)+) => {
142        paste::item! {
143            /// Peripheral Reset and Enable Control
144            #[allow(non_snake_case)]
145            #[non_exhaustive]
146            pub struct PeripheralREC {
147                $(
148                    $(
149                        #[allow(missing_docs)]
150                        #[ $tmeta ]
151                        $( #[ $pmeta ] )*
152                        pub [< $p:upper >]: $p,
153                    )*
154                )+
155            }
156            impl PeripheralREC {
157                /// Return a new instance of the peripheral resets /
158                /// enables / kernel clocks
159                ///
160                /// # Safety
161                ///
162                /// If this method is called multiple times, then multiple
163                /// accesses to the same memory exist.
164                pub(super) unsafe fn new_singleton() -> PeripheralREC {
165                    PeripheralREC {
166                        $(
167                            $(
168                                #[ $tmeta ]
169                                $( #[ $pmeta ] )*
170                                [< $p:upper >]: $p {
171                                    _marker: PhantomData,
172                                },
173                            )*
174                        )+
175                    }
176                }
177            }
178            $(
179                $(
180                    #[ $tmeta ]
181                    peripheral_reset_and_enable_control_generator! (
182                        $AXBn, $(($Auto))* $p, [< $p:upper >], [< $p:lower >],
183                        $( $pmeta )*
184                        $(
185                            [kernel $clk: $pk $(($Variant))* $ccip $clk_doc]
186                        )*
187                        $(
188                            [group clk: $pk_g [< $pk_g:lower >] $( $(($Variant_g))* $ccip_g $clk_doc_g )* ]
189                        )*
190                        $(
191                            [fixed clk: $clk_doc_f]
192                        )*
193                    );
194                )*
195            )+
196        }
197    }
198}
199
200// This macro uses the paste::item! macro to create identifiers.
201//
202// https://crates.io/crates/paste
203//
204// The macro is intended only to be called from within the
205// peripheral_reset_and_enable_control macro
206macro_rules! peripheral_reset_and_enable_control_generator {
207    (
208        $AXBn:ident,
209        $(($Auto:ident))* $p:ident,
210        $p_upper:ident,         // Lower and upper case $p available for use in
211        $p_lower:ident,         // comments, equivalent to with the paste macro.
212
213        $( $pmeta:meta )*
214        $([ kernel $clk:ident: $pk:ident $(($Variant:ident))* $ccip:ident $clk_doc:expr ])*
215        $([ group clk: $pk_g:ident $pk_g_lower:ident $( $(($Variant_g:ident))* $ccip_g:ident $clk_doc_g:expr )* ])*
216        $([ fixed clk: $clk_doc_f:expr ])*
217    ) => {
218        paste::item! {
219            #[doc = " Reset, Enable and Clock functionality for " $p]
220            ///
221            /// # Reset/Enable Example
222            ///
223            /// ```
224            /// let ccdr = ...; // From RCC
225            ///
226            /// // Enable the clock to the peripheral and reset it
227            #[doc = "ccdr.peripheral." $p_upper ".enable().reset();"]
228            /// ```
229            ///
230            $(                  // Individual kernel clocks
231                /// # Individual Kernel Clock
232                ///
233                /// This peripheral has its own dedicated kernel clock.
234                #[doc = "See [" $pk "ClkSel](crate::rcc::rec::" $pk "ClkSel) "
235                  "for possible clock sources."]
236                ///
237                /// ```
238                /// let ccdr = ...; // From RCC
239                ///
240                /// // Set individual kernel clock
241                #[doc = "let " $p_lower "_prec = ccdr.peripheral." $p_upper
242                  ".kernel_clk_mux(" $pk "ClkSel::XX_clock_soruce_XX);"]
243                ///
244                #[doc = "assert_eq!(" $p_lower "_prec.get_kernel_clk_mux(), "
245                  $pk "ClkSel::XX_clock_source_XX);"]
246                /// ```
247            )*
248            $(                  // Group kernel clocks
249                /// # Group Kernel Clock
250                ///
251                /// This peripheral has a kernel clock that is shared with other
252                /// peripherals.
253                ///
254                #[doc = "Since it is shared, it must be set using the "
255                  "[kernel_" $pk_g_lower "_clk_mux](crate::rcc::rec::PeripheralREC#method"
256                  ".kernel_" $pk_g_lower "_clk_mux) method."]
257                ///
258                /// ```
259                /// let mut ccdr = ...; // From RCC
260                ///
261                /// // Set group kernel clock mux
262                #[doc = " ccdr.peripheral."
263                  "kernel_" $pk_g_lower "_clk_mux("
264                  $pk_g "ClkSel::XX_clock_source_XX);"]
265                ///
266                #[doc = " assert_eq!(ccdr.peripheral." $p_upper
267                  ".get_kernel_clk_mux(), " $pk_g "ClkSel::XX_clock_source_XX);"]
268            )*
269            $(                  // Fixed kernel clocks
270                /// # Fixed Kernel Clock
271                ///
272                /// This peripheral has a kernel clock that is always equal to
273                #[doc= $clk_doc_f "."]
274            )*
275            $( #[ $pmeta ] )*
276            pub struct $p {
277                pub(crate) _marker: PhantomData<*const ()>,
278            }
279            $( #[ $pmeta ] )*
280            impl $p {
281                /// Set Low Power Mode for peripheral
282                #[allow(clippy::return_self_not_must_use)]
283                pub fn low_power(self, lpm: LowPowerMode) -> Self {
284                    // unsafe: Owned exclusive access to this bitfield
285                    interrupt::free(|_| {
286                        // LPEN
287                        let lpenr = unsafe {
288                            &(*RCC::ptr()).[< $AXBn:lower lpenr >]
289                        };
290                        lpenr.modify(|_, w| w.[< $p:lower lpen >]()
291                                     .bit(lpm != LowPowerMode::Off));
292                        // AMEN
293                        $(
294                            let amr = unsafe { autonomous!($Auto) };
295                            amr.modify(|_, w| w.[< $p:lower amen >]()
296                                       .bit(lpm == LowPowerMode::Autonomous));
297                        )*
298                    });
299                    self
300                }
301            }
302            $( #[ $pmeta ] )*
303            unsafe impl Send for $p {}
304            $( #[ $pmeta ] )*
305            impl ResetEnable for $p {
306                #[inline(always)]
307                fn enable(self) -> Self {
308                    // unsafe: Owned exclusive access to this bitfield
309                    interrupt::free(|_| {
310                        let enr = unsafe {
311                            &(*RCC::ptr()).[< $AXBn:lower enr >]
312                        };
313                        enr.modify(|_, w| w.
314                                   [< $p:lower en >]().set_bit());
315                    });
316                    self
317                }
318                #[inline(always)]
319                fn disable(self) -> Self {
320                    // unsafe: Owned exclusive access to this bitfield
321                    interrupt::free(|_| {
322                        let enr = unsafe {
323                            &(*RCC::ptr()).[< $AXBn:lower enr >]
324                        };
325                        enr.modify(|_, w| w.
326                                   [< $p:lower en >]().clear_bit());
327                    });
328                    self
329                }
330                #[inline(always)]
331                fn reset(self) -> Self {
332                    // unsafe: Owned exclusive access to this bitfield
333                    interrupt::free(|_| {
334                        let rstr = unsafe {
335                            &(*RCC::ptr()).[< $AXBn:lower rstr >]
336                        };
337                        rstr.modify(|_, w| w.
338                                    [< $p:lower rst >]().set_bit());
339                        rstr.modify(|_, w| w.
340                                    [< $p:lower rst >]().clear_bit());
341                    });
342                    self
343                }
344            }
345            $( #[ $pmeta ] )*
346            impl $p {
347                $(      // Individual kernel clocks
348                    #[inline(always)]
349                    #[allow(clippy::return_self_not_must_use)]
350                    /// Modify the kernel clock for
351                    #[doc=$clk_doc "."]
352                    /// See RM0433 Rev 7 Section 8.5.8.
353                    ///
354                    /// It is possible to switch this clock dynamically without
355                    /// generating spurs or timing violations. However, the user
356                    /// must ensure that both clocks are running. See RM0433 Rev
357                    /// 7 Section 8.5.10.
358                    pub fn [< kernel_ $clk _mux >](self, sel: [< $pk ClkSel >]) -> Self {
359                        // unsafe: Owned exclusive access to this bitfield
360                        interrupt::free(|_| {
361                            let ccip = unsafe {
362                                &(*RCC::ptr()).[< $ccip r >]
363                            };
364                            ccip.modify(|_, w| w.
365                                        [< $pk:lower sel >]().variant(sel));
366                        });
367                        self
368                    }
369
370                    #[inline(always)]
371                    /// Return the current kernel clock selection
372                    pub fn [< get_kernel_ $clk _mux>](&self) ->
373                        variant_return_type!([< $pk ClkSel >] $(, $Variant)*)
374                    {
375                        // unsafe: We only read from this bitfield
376                        let ccip = unsafe {
377                            &(*RCC::ptr()).[< $ccip r >]
378                        };
379                        ccip.read().[< $pk:lower sel >]().variant()
380                    }
381                )*
382            }
383            $(          // Individual kernel clocks
384                #[doc=$clk_doc]
385                /// kernel clock source selection
386                pub type [< $pk ClkSel >] =
387                    rcc::[< $ccip r >]::[< $pk:upper SEL_A >];
388            )*
389            $(          // Group kernel clocks
390                impl [< $pk_g ClkSelGetter >] for $p {}
391            )*
392            $(          // Group kernel clocks
393                $(
394                    #[doc=$clk_doc_g]
395                    /// kernel clock source selection.
396                    pub type [< $pk_g ClkSel >] =
397                        rcc::[< $ccip_g r >]::[< $pk_g:upper SEL_A >];
398
399                    /// Can return
400                    #[doc=$clk_doc_g]
401                    /// kernel clock source selection
402                    pub trait [< $pk_g ClkSelGetter >] {
403                        #[inline(always)]
404                        #[allow(unused)]
405                        /// Return the
406                        #[doc=$clk_doc_g]
407                        /// kernel clock selection
408                        fn get_kernel_clk_mux(&self) ->
409                            variant_return_type!([< $pk_g ClkSel >] $(, $Variant_g)*)
410                        {
411                            // unsafe: We only read from this bitfield
412                            let ccip = unsafe {
413                                &(*RCC::ptr()).[< $ccip_g r >]
414                            };
415                            ccip.read().[< $pk_g:lower sel >]().variant()
416                        }
417                    }
418                )*
419            )*
420            impl PeripheralREC {
421                $(          // Group kernel clocks
422                    $(
423                        /// Modify the kernel clock for
424                        #[doc=$clk_doc_g "."]
425                        /// See RM0433 Rev 7 Section 8.5.8.
426                        ///
427                        /// It is possible to switch this clock dynamically
428                        /// without generating spurs or timing
429                        /// violations. However, the user must ensure that both
430                        /// clocks are running. See RM0433 Rev 7 Section 8.5.10.
431                        pub fn [< kernel_ $pk_g:lower _clk_mux >](&mut self, sel: [< $pk_g ClkSel >]) -> &mut Self {
432                            // unsafe: Owned exclusive access to this bitfield
433                            interrupt::free(|_| {
434                                let ccip = unsafe {
435                                    &(*RCC::ptr()).[< $ccip_g r >]
436                                };
437                                ccip.modify(|_, w| w.
438                                            [< $pk_g:lower sel >]().variant(sel));
439                            });
440                            self
441                        }
442                    )*
443                )*
444            }
445        }
446    }
447}
448
449// If the PAC does not fully specify a CCIP field (perhaps because one or
450// more values are reserved), then we use a different return type
451macro_rules! variant_return_type {
452    ($t:ty) => { $t };
453    ($t:ty, $Variant: ident) => {
454        Option<$t>
455    };
456}
457
458// Register for autonomous mode enable bits
459#[cfg(not(feature = "rm0455"))]
460macro_rules! autonomous {
461    ($Auto:ident) => {
462        &(*RCC::ptr()).d3amr
463    };
464}
465#[cfg(feature = "rm0455")]
466macro_rules! autonomous {
467    ($Auto:ident) => {
468        &(*RCC::ptr()).srdamr
469    };
470}
471
472// Enumerate all peripherals and optional clock multiplexers
473//
474// Peripherals are grouped by bus for convenience. Each bus is specified like:
475// #[attribute] name, "description" => [..];
476//
477// The attribute is mandatory for the bus grouping, but can just be
478// #[cfg(all())]. The description is not used. Each bus grouping can be repeated
479// multiple times if needed.
480//
481// As well as busses, peripherals can optionally be preceeded by a conditional
482// compilation attribute. However, this only works for peripherals without
483// kernel clock multiplexers.
484//
485// Peripherals with an individual kernel clock must be marked "kernel clk". If a
486// kernel clock multiplexer is shared between multiple peripherals, all those
487// peripherals must instead be marked with a common "group clk".
488peripheral_reset_and_enable_control! {
489    #[cfg(all())]
490    AHB1, "AMBA High-performance Bus (AHB1) peripherals" => [
491        Dma2, Dma1
492    ];
493    #[cfg(not(feature = "rm0455"))]
494    AHB1, "" => [
495        Eth1Mac,
496        #[cfg(any(feature = "rm0399"))] Art,
497        Adc12 [group clk: Adc(Variant) d3ccip "ADC"],
498        Usb1Otg [group clk: Usb d2ccip2 "USB"]
499    ];
500    #[cfg(any(feature = "rm0433", feature = "rm0399"))]
501    AHB1, "" => [
502        Usb2Otg [group clk: Usb]
503    ];
504    #[cfg(feature = "rm0455")]
505    AHB1, "" => [
506        Crc,
507        Usb1Otg [group clk: Usb cdccip2 "USB"],
508        Adc12 [group clk: Adc(Variant) srdccip "ADC"]
509    ];
510
511
512    #[cfg(all())]
513    AHB2, "AMBA High-performance Bus (AHB2) peripherals" => [
514        Hash, Crypt,
515        Sdmmc2 [group clk: Sdmmc]
516    ];
517    #[cfg(not(feature = "rm0455"))]
518    AHB2, "" => [
519        Rng [kernel clk: Rng d2ccip2 "RNG"]
520    ];
521    #[cfg(feature = "rm0455")]
522    AHB2, "" => [
523        Rng [kernel clk: Rng cdccip2 "RNG"]
524    ];
525    #[cfg(feature = "rm0468")]
526    AHB2, "" => [
527        Cordic, Fmac
528    ];
529
530
531    #[cfg(all())]
532    AHB3, "AMBA High-performance Bus (AHB3) peripherals" => [
533        Dma2d, Mdma
534    ];
535    #[cfg(not(feature = "rm0455"))]
536    AHB3, "" => [
537        Sdmmc1 [group clk: Sdmmc d1ccip "SDMMC"],
538        Fmc [kernel clk: Fmc d1ccip "FMC"]
539    ];
540    #[cfg(any(feature = "rm0433", feature = "rm0399"))]
541    AHB3, "" => [
542        Jpgdec,
543        Qspi [kernel clk: Qspi d1ccip "QUADSPI"]
544    ];
545    #[cfg(feature = "rm0455")]
546    AHB3, "" => [
547        Jpgdec,
548        Sdmmc1 [group clk: Sdmmc cdccip "SDMMC"],
549        Fmc [kernel clk: Fmc cdccip "FMC"],
550        Octospi1 [group clk: Octospi cdccip "OCTOSPI"],
551        Octospi2 [group clk: Octospi]
552    ];
553    #[cfg(feature = "rm0468")]
554    AHB3, "" => [
555        Octospi1 [group clk: Octospi d1ccip "OCTOSPI"],
556        Octospi2 [group clk: Octospi]
557    ];
558
559
560    #[cfg(all())]
561    AHB4, "AMBA High-performance Bus (AHB4) peripherals" => [
562        Gpioa, Gpiob, Gpioc, Gpiod, Gpioe, Gpiof, Gpiog, Gpioh, Gpioi, Gpioj, Gpiok
563    ];
564    #[cfg(not(feature = "rm0455"))]
565    AHB4, "" => [
566        (Auto) Crc,
567        (Auto) Bdma,
568        (Auto) Adc3 [group clk: Adc]
569    ];
570    #[cfg(feature = "rm0455")]
571    AHB4, "" => [
572        (Auto) Bdma2
573    ];
574
575
576    #[cfg(all())]
577    APB1L, "Advanced Peripheral Bus 1L (APB1L) peripherals" => [
578        Spi2 [group clk: Spi123],
579        Spi3 [group clk: Spi123],
580
581        Tim2, Tim3, Tim4, Tim5, Tim6, Tim7, Tim12, Tim13, Tim14,
582
583        Usart3 [group clk: Usart234578],
584        Uart4 [group clk: Usart234578],
585        Uart5 [group clk: Usart234578],
586        Uart7 [group clk: Usart234578],
587        Uart8 [group clk: Usart234578]
588    ];
589    #[cfg(not(feature = "rm0455"))]
590    APB1L, "" => [
591        Dac12,
592
593        Cec [kernel clk: Cec(Variant) d2ccip2 "CEC"],
594        Lptim1 [kernel clk: Lptim1(Variant) d2ccip2 "LPTIM1"],
595        Usart2 [group clk: Usart234578(Variant) d2ccip2 "USART2/3/4/5/7/8"]
596    ];
597    #[cfg(any(feature = "rm0433", feature = "rm0399"))]
598    APB1L, "" => [
599        I2c1 [group clk: I2c123 d2ccip2 "I2C1/2/3"],
600        I2c2 [group clk: I2c123],
601        I2c3 [group clk: I2c123]
602    ];
603    #[cfg(feature = "rm0455")]
604    APB1L, "" => [
605        Dac1,
606
607        I2c1 [group clk: I2c123 cdccip2 "I2C1/2/3"],
608        I2c2 [group clk: I2c123],
609        I2c3 [group clk: I2c123],
610        Cec [kernel clk: Cec(Variant) cdccip2 "CEC"],
611        Lptim1 [kernel clk: Lptim1(Variant) cdccip2 "LPTIM1"],
612        Usart2 [group clk: Usart234578(Variant) cdccip2 "USART2/3/4/5/7/8"]
613    ];
614    #[cfg(feature = "rm0468")]
615    APB1L, "" => [
616        I2c1 [group clk: I2c1235 d2ccip2 "I2C1/2/3/5"],
617        I2c2 [group clk: I2c1235],
618        I2c3 [group clk: I2c1235],
619        I2c5 [group clk: I2c1235]
620    ];
621
622
623    #[cfg(all())]
624    APB1H, "Advanced Peripheral Bus 1H (APB1H) peripherals" => [
625        Crs, Mdios, Opamp
626    ];
627    #[cfg(not(feature = "rm0455"))]
628    APB1H, "" => [
629        Fdcan [kernel clk: Fdcan(Variant) d2ccip1 "FDCAN"]
630    ];
631    #[cfg(any(feature = "rm0433", feature = "rm0399"))]
632    APB1H, "" => [
633        Swp [kernel clk: Swp d2ccip1 "SWPMI"]
634    ];
635    #[cfg(feature = "rm0455")]
636    APB1H, "" => [
637        Fdcan [kernel clk: Fdcan(Variant) cdccip1 "FDCAN"],
638        Swpmi [kernel clk: Swpmi cdccip1 "SWPMI"]
639    ];
640    #[cfg(feature = "rm0468")]
641    APB1H, "" => [
642        Swpmi [kernel clk: Swpmi d2ccip1 "SWPMI"],
643
644        Tim23, Tim24
645    ];
646
647
648    #[cfg(all())]
649    APB2, "Advanced Peripheral Bus 2 (APB2) peripherals" => [
650        Tim1, Tim8, Tim15, Tim16, Tim17
651    ];
652    #[cfg(not(feature = "rm0455"))]
653    APB2, "" => [
654        Dfsdm1 [kernel clk: Dfsdm1 d2ccip1 "DFSDM1"],
655
656        Sai1 [kernel clk: Sai1(Variant) d2ccip1 "SAI1"],
657
658        Spi1 [group clk: Spi123(Variant) d2ccip1 "SPI1/2/3"],
659        Spi4 [group clk: Spi45(Variant) d2ccip1 "SPI4/5"],
660        Spi5 [group clk: Spi45]
661    ];
662    #[cfg(any(feature = "rm0433", feature = "rm0399"))]
663    APB2, "" => [
664        Hrtim,
665
666        Sai2 [group clk: Sai23(Variant) d2ccip1 "SAI2/3"],
667        Sai3 [group clk: Sai23],
668
669        Usart1 [group clk: Usart16(Variant) d2ccip2 "USART1/6"],
670        Usart6 [group clk: Usart16]
671    ];
672    #[cfg(feature = "rm0455")]
673    APB2, "" => [
674        Dfsdm1 [kernel clk: Dfsdm1 cdccip1 "DFSDM1"],
675
676        Sai1 [kernel clk: Sai1(Variant) cdccip1 "SAI1"],
677        Sai2 [kernel clk_a: Sai2A(Variant) cdccip1
678            "Sub-Block A of SAI2"]
679            [kernel clk_b: Sai2B(Variant) cdccip1
680            "Sub-Block B of SAI2"],
681
682        Spi1 [group clk: Spi123(Variant) cdccip1 "SPI1/2/3"],
683        Spi4 [group clk: Spi45(Variant) cdccip1 "SPI4/5"],
684        Spi5 [group clk: Spi45],
685
686        Usart1 [group clk: Usart16910(Variant) cdccip2 "USART1/6/9/10"],
687        Usart6 [group clk: Usart16910],
688        Uart9 [group clk: Usart16910],
689        Usart10 [group clk: Usart16910]
690    ];
691    #[cfg(feature = "rm0468")]
692    APB2, "" => [
693        Usart1 [group clk: Usart16910(Variant) d2ccip2 "USART1/6/9/10"],
694        Usart6 [group clk: Usart16910],
695        Uart9 [group clk: Usart16910],
696        Usart10 [group clk: Usart16910]
697    ];
698
699
700    #[cfg(all())]
701    APB3, "Advanced Peripheral Bus 3 (APB3) peripherals" => [
702        Ltdc [fixed clk: "pll3_r_ck"],
703        #[cfg(any(feature = "rm0399"))] Dsi
704    ];
705
706
707    #[cfg(all())]
708    APB4, "Advanced Peripheral Bus 4 (APB4) peripherals" => [
709        (Auto) Vref,
710        (Auto) Comp12
711    ];
712    #[cfg(not(feature = "rm0455"))]
713    APB4, "" => [
714        (Auto) Lptim2 [kernel clk: Lptim2(Variant) d3ccip "LPTIM2"],
715        (Auto) Lptim3 [group clk: Lptim345(Variant) d3ccip "LPTIM3/4/5"],
716        (Auto) Lptim4 [group clk: Lptim345],
717        (Auto) Lptim5 [group clk: Lptim345],
718
719        (Auto) I2c4 [kernel clk: I2c4 d3ccip "I2C4"],
720        (Auto) Spi6 [kernel clk: Spi6(Variant) d3ccip "SPI6"],
721        (Auto) Sai4 [kernel clk_a: Sai4A(Variant) d3ccip
722            "Sub-Block A of SAI4"]
723            [kernel clk_b: Sai4B(Variant) d3ccip
724            "Sub-Block B of SAI4"]
725    ];
726    #[cfg(feature = "rm0455")]
727    APB4, "" => [
728        (Auto) Dac2,
729
730        (Auto) Lptim2 [kernel clk: Lptim2(Variant) srdccip "LPTIM2"],
731        (Auto) Lptim3,// TODO [group clk: Lptim3(Variant) srdccip "LPTIM3"],
732
733        (Auto) I2c4 [kernel clk: I2c4 srdccip "I2C4"],
734        (Auto) Spi6 [kernel clk: Spi6(Variant) srdccip "SPI6"]
735    ];
736}