nrf52_hal_common/
clocks.rs1use crate::target::CLOCK;
5
6pub struct Internal;
10
11pub struct ExternalOscillator;
13
14pub struct LfOscSynthesized;
16
17pub struct LfOscStarted;
19
20pub struct LfOscStopped;
22
23pub trait ClocksExt {
25 fn constrain(self) -> Clocks<Internal, Internal, LfOscStopped>;
26}
27
28pub const HFCLK_FREQ: u32 = 64_000_000;
30pub const LFCLK_FREQ: u32 = 32_768;
32
33pub struct Clocks<H, L, LSTAT> {
35 hfclk: H,
36 lfclk: L,
37 lfstat: LSTAT,
38 periph: CLOCK,
39}
40
41impl<H, L, LSTAT> Clocks<H, L, LSTAT> {
42 pub fn enable_ext_hfosc(self) -> Clocks<ExternalOscillator, L, LSTAT> {
44 self.periph.tasks_hfclkstart.write(|w| unsafe { w.bits(1) });
45
46 while self.periph.events_hfclkstarted.read().bits() != 1 {}
48 self.periph
49 .events_hfclkstarted
50 .write(|w| unsafe { w.bits(0) });
51
52 Clocks {
53 hfclk: ExternalOscillator,
54 lfclk: self.lfclk,
55 lfstat: self.lfstat,
56 periph: self.periph,
57 }
58 }
59
60 pub fn disable_ext_hfosc(self) -> Clocks<Internal, L, LSTAT> {
62 self.periph.tasks_hfclkstop.write(|w| unsafe { w.bits(1) });
63 Clocks {
64 hfclk: Internal,
65 lfclk: self.lfclk,
66 lfstat: self.lfstat,
67 periph: self.periph,
68 }
69 }
70
71 pub fn start_lfclk(self) -> Clocks<H, L, LfOscStarted> {
73 self.periph.tasks_lfclkstart.write(|w| unsafe { w.bits(1) });
74
75 while self.periph.events_lfclkstarted.read().bits() != 1 {}
78 self.periph
79 .events_lfclkstarted
80 .write(|w| unsafe { w.bits(0) });
81
82 Clocks {
83 hfclk: self.hfclk,
84 lfclk: self.lfclk,
85 lfstat: LfOscStarted,
86 periph: self.periph,
87 }
88 }
89}
90
91pub enum LfOscConfiguration {
94 NoExternalNoBypass,
95 ExternalNoBypass,
96 ExternalAndBypass,
97}
98
99impl<H, L> Clocks<H, L, LfOscStarted> {
100 pub fn stop_lfclk(self) -> Clocks<H, L, LfOscStopped> {
102 self.periph.tasks_lfclkstop.write(|w| unsafe { w.bits(1) });
103 Clocks {
104 hfclk: self.hfclk,
105 lfclk: self.lfclk,
106 lfstat: LfOscStopped,
107 periph: self.periph,
108 }
109 }
110}
111
112impl<H, L> Clocks<H, L, LfOscStopped> {
113 pub fn set_lfclk_src_rc(self) -> Clocks<H, Internal, LfOscStopped> {
115 self.periph
116 .lfclksrc
117 .write(|w| w.src().rc().bypass().disabled().external().disabled());
118 Clocks {
119 hfclk: self.hfclk,
120 lfclk: Internal,
121 lfstat: self.lfstat,
122 periph: self.periph,
123 }
124 }
125
126 pub fn set_lfclk_src_synth(self) -> Clocks<H, LfOscSynthesized, LfOscStopped> {
128 self.periph
129 .lfclksrc
130 .write(|w| w.src().synth().bypass().disabled().external().disabled());
131 Clocks {
132 hfclk: self.hfclk,
133 lfclk: LfOscSynthesized,
134 lfstat: self.lfstat,
135 periph: self.periph,
136 }
137 }
138
139 pub fn set_lfclk_src_external(
141 self,
142 cfg: LfOscConfiguration,
143 ) -> Clocks<H, ExternalOscillator, LfOscStopped> {
144 let (ext, byp) = match cfg {
145 LfOscConfiguration::NoExternalNoBypass => (false, false),
146 LfOscConfiguration::ExternalNoBypass => (true, false),
147 LfOscConfiguration::ExternalAndBypass => (true, true),
148 };
149 self.periph
150 .lfclksrc
151 .write(move |w| w.src().xtal().bypass().bit(byp).external().bit(ext));
152 Clocks {
153 hfclk: self.hfclk,
154 lfclk: ExternalOscillator,
155 lfstat: self.lfstat,
156 periph: self.periph,
157 }
158 }
159}
160
161impl ClocksExt for CLOCK {
162 fn constrain(self) -> Clocks<Internal, Internal, LfOscStopped> {
163 Clocks {
164 hfclk: Internal,
165 lfclk: Internal,
166 lfstat: LfOscStopped,
167 periph: self,
168 }
169 }
170}