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}