lpc8xx_hal/syscon/
clock_source.rs

1//! Clock configuration for the peripherals
2
3use crate::syscon;
4
5/// Internal trait used configure peripheral clock sources
6///
7/// This trait is an internal implementation detail and should neither be
8/// implemented nor used outside of LPC8xx HAL. Any changes to this trait won't
9/// be considered breaking changes.
10pub trait PeripheralClock {
11    /// The variant of FCLKSEL.SEL that selects this clock source
12    ///
13    /// This is not available (or required) on LPC82x.
14    #[cfg(feature = "845")]
15    const CLOCK: crate::pac::syscon::fclksel::SEL_A;
16
17    /// Select the clock
18    ///
19    /// The `selector` argument should not be required to implement this trait,
20    /// but it makes sure that the caller has access to the peripheral they are
21    /// selecting the clock for.
22    fn select<S>(selector: &S, handle: &mut syscon::Handle)
23    where
24        S: PeripheralClockSelector;
25}
26
27/// Internal trait used for defining the fclksel index for a peripheral
28///
29/// This trait is an internal implementation detail and should neither be
30/// implemented nor used outside of LPC8xx HAL. Any changes to this trait won't
31/// be considered breaking changes.
32pub trait PeripheralClockSelector {
33    /// The index of the FCLKSEL register
34    ///
35    /// This is not relevant on LPC82x.
36    const REGISTER_NUM: usize;
37}
38
39/// A struct containing the clock configuration for the ADC peripheral
40pub struct AdcClock {
41    pub(crate) caldiv: u8,
42    pub(crate) div: u8,
43}
44
45impl AdcClock {
46    /// Create the clock config for the ADC peripheral
47    ///
48    /// The system clock is divided by `caldiv` during calibration or `div`
49    /// during normal operation.
50    /// During calibration the frequency of the ADC peripheral has to be 500 kHz
51    /// and during normal operation it can't be higher than 30 MHz.
52    pub unsafe fn new(caldiv: u8, div: u8) -> Self {
53        Self { caldiv, div }
54    }
55    /// Create a new ADC clock config with the maximum sample rate
56    ///
57    /// Assumes the internal oscillator runs at 12 MHz
58    pub fn new_default() -> Self {
59        Self { caldiv: 24, div: 0 }
60    }
61}
62
63#[cfg(feature = "845")]
64mod target {
65    use crate::{
66        pac::syscon::fclksel::SEL_A,
67        syscon::{
68            self,
69            frg::{FRG, FRG0, FRG1},
70            IOSC,
71        },
72    };
73
74    use super::{PeripheralClock, PeripheralClockSelector};
75
76    macro_rules! peripheral_clocks {
77        (
78            $(
79                $clock:ty,
80                $sel:ident;
81            )*
82         ) => {
83            $(
84                impl PeripheralClock for $clock {
85                    const CLOCK: SEL_A = SEL_A::$sel;
86
87                    fn select<S>(_: &S, syscon: &mut syscon::Handle)
88                    where
89                        S: PeripheralClockSelector,
90                    {
91                        syscon.fclksel[S::REGISTER_NUM]
92                            .write(|w| w.sel().variant(Self::CLOCK));
93                    }
94                }
95            )*
96        };
97    }
98
99    peripheral_clocks!(
100        FRG<FRG0>, FRG0CLK;
101        FRG<FRG1>, FRG1CLK;
102        IOSC, FRO;
103    );
104}