1#[cfg_attr(ra2a1, path = "clock/ra2a1.rs")]
4#[cfg_attr(ra4m1, path = "clock/ra4m1.rs")]
5#[cfg_attr(ra4l1, path = "clock/ra4l1.rs")]
6#[cfg_attr(ra6m5, path = "clock/ra6m5.rs")]
7#[cfg_attr(ra8m1, path = "clock/ra8m1.rs")]
8mod _clock;
9
10pub(crate) use _clock::init;
11use embassy_sync::once_lock::OnceLock;
12use fugit::{HertzU32, KilohertzU32, MegahertzU32};
13
14use crate::pac;
15
16#[cfg(sciclk)]
17use _clock::SciClockSource;
18#[cfg(slcdc)]
19use _clock::SlcdcClockSource;
20#[cfg(spiclk)]
21use _clock::SpiClockSource;
22#[cfg(usbclk)]
23use _clock::UsbClockSource;
24
25static CLOCK_STATUS: OnceLock<ClockStatus> = OnceLock::new();
26const _1MHZ: HertzU32 = MegahertzU32::from_raw(1).convert();
27
28pub struct ClockStatus {
30 pub master: HertzU32,
32
33 pub mosc: Option<HertzU32>,
35
36 pub sosc: bool,
38
39 pub hoco: HertzU32,
41
42 #[cfg(all(pll, not(ra8m1)))]
44 pub pll: Option<HertzU32>,
45 #[cfg(all(pll, ra8m1))]
47 pub pll: Option<(HertzU32, HertzU32, HertzU32)>,
48
49 #[cfg(all(pll2, not(ra8m1)))]
51 pub pll2: Option<HertzU32>,
52 #[cfg(all(pll2, ra8m1))]
54 pub pll2: Option<(HertzU32, HertzU32, HertzU32)>,
55
56 #[cfg(bclk)]
57 pub bus_clock: HertzU32,
58
59 pub system: HertzU32,
61
62 pub flash: HertzU32,
64
65 #[cfg(pclka)]
67 pub peripheral_a: HertzU32,
68
69 #[cfg(pclkb)]
71 pub peripheral_b: HertzU32,
72
73 #[cfg(pclkc)]
75 pub peripheral_c: HertzU32,
76
77 #[cfg(pclkd)]
79 pub peripheral_d: HertzU32,
80
81 #[cfg(pclke)]
83 pub peripheral_e: HertzU32,
84
85 #[cfg(usbclk)]
86 pub usb: Option<HertzU32>,
88
89 #[cfg(sciclk)]
90 pub sci: Option<HertzU32>,
92
93 #[cfg(spiclk)]
94 pub spi: Option<HertzU32>,
96
97 #[cfg(slcdc)]
98 pub slcdc: Option<HertzU32>,
99}
100
101#[cfg_attr(feature = "defmt", derive(defmt::Format))]
106#[derive(Debug, Copy, Clone, PartialEq)]
107pub enum SystemClockSource {
108 Mosc,
110
111 Sosc,
113
114 Hoco,
116
117 Moco,
119
120 #[cfg(not(ra8m1))]
122 Loco,
123
124 #[cfg(all(not(ra8m1), pll))]
125 Pll,
127
128 #[cfg(ra8m1)]
129 Pll1P,
130}
131
132#[cfg_attr(feature = "defmt", derive(defmt::Format))]
134#[derive(Debug, Clone)]
135pub struct ClockConfig {
136 system: SystemClockSource,
137
138 hoco: HocoFrequency,
140
141 mosc: Option<HertzU32>,
143
144 sosc: bool,
146
147 #[cfg(pll)]
149 pll: Option<PllConfig>,
150
151 #[cfg(pll2)]
153 pll2: Option<PllConfig>,
154
155 #[cfg(usbclk)]
156 usb: Option<UsbClockSource>,
157
158 #[cfg(sciclk)]
159 sci: Option<(SciClockSource, HertzU32)>,
160
161 #[cfg(spiclk)]
162 spi: Option<(SpiClockSource, HertzU32)>,
163
164 #[cfg(slcdc)]
165 slcdc: Option<SlcdcClockSource>,
166}
167
168cfg_select! {
169 not(ra8m1) => {
170 #[cfg(all(pll, not(ra4m1)))]
171 pub use _clock::PllInDiv;
172 #[cfg(ra4m1)]
173 pub use _clock::PllOutDiv;
174 #[cfg(any(pll, pll2))]
175 pub use _clock::{PllInput, PllOutMul};
176
177 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
179 #[cfg(any(pll, pll2))]
180 #[derive(Debug, Clone)]
181 pub struct PllConfig {
182 input: PllInput,
183 #[cfg(not(ra4m1))]
184 div: PllInDiv,
185 #[cfg(ra4m1)]
186 div: PllOutDiv,
187 mul: PllOutMul,
188 }
189 },
190 ra8m1 => {
191 pub use _clock::PllInDiv;
192 pub use _clock::{PllInput, PllPDiv, PllQDiv, PllRDiv, PllOutMul};
193
194 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
196 #[derive(Debug, Clone)]
197 pub struct PllConfig {
198 input: PllInput,
200 div: PllInDiv,
202 mul: PllOutMul,
204 div_p: PllPDiv,
206 div_q: PllQDiv,
208 div_r: PllRDiv,
210 }
211 }
212}
213
214pub fn clock_status() -> &'static ClockStatus {
216 CLOCK_STATUS
217 .try_get()
218 .expect("CLOCK_STATUS not initialized")
219}
220
221#[cfg(feature = "defmt")]
222fn print_frequency(fmt: defmt::Formatter, label: &str, frequency: HertzU32) {
223 if frequency < _1MHZ {
224 let pll: KilohertzU32 = frequency.convert();
225 defmt::write!(fmt, ", {}: {}", label, pll);
226 } else {
227 let pll: MegahertzU32 = frequency.convert();
228 defmt::write!(fmt, ", {}: {}", label, pll);
229 }
230}
231
232#[cfg(feature = "defmt")]
233impl defmt::Format for ClockStatus {
234 fn format(&self, fmt: defmt::Formatter) {
235 let system = pac::SYSTEM;
236 let cksel = system.sckscr().read().cksel();
237
238 let &ClockStatus {
239 master: _,
240 system,
241 flash,
242 #[cfg(pclka)]
243 peripheral_a,
244 #[cfg(pclkb)]
245 peripheral_b,
246 #[cfg(pclkc)]
247 peripheral_c,
248 #[cfg(pclkd)]
249 peripheral_d,
250 #[cfg(pclke)]
251 peripheral_e,
252 hoco,
253 #[cfg(pll)]
254 pll,
255 #[cfg(pll2)]
256 pll2,
257 #[cfg(bclk)]
258 bus_clock,
259 sosc,
260 mosc,
261 #[cfg(usbclk)]
262 usb,
263 #[cfg(sciclk)]
264 sci,
265 #[cfg(spiclk)]
266 spi,
267 #[cfg(slcdc)]
268 slcdc,
269 } = clock_status();
270
271 defmt::write!(fmt, "SYSTEM: ");
272
273 if hoco < _1MHZ {
274 let hoco: KilohertzU32 = hoco.convert();
275 defmt::write!(fmt, "HOCO: {}", hoco);
276 } else {
277 let hoco: MegahertzU32 = hoco.convert();
278 defmt::write!(fmt, "HOCO: {}", hoco);
279 }
280 defmt::write!(fmt, ", SOSC: {}", sosc);
281
282 match mosc {
283 Some(mosc) => {
284 print_frequency(fmt, "MOSC", mosc.convert());
285 }
286 None => {
287 defmt::write!(fmt, ", MOSC: None");
288 }
289 }
290
291 #[cfg(pll)]
292 cfg_select! {
293 not(ra8m1) => {
294 match pll {
295 Some(pll) => print_frequency(fmt, "PLL", pll),
296 None => defmt::write!(fmt, ", PLL: OFF"),
297 }
298 }
299 ra8m1 => {
300 match pll {
301 Some((pll_p, pll_q, pll_r)) => {
302 print_frequency(fmt, "PLL.P", pll_p);
303 print_frequency(fmt, "PLL.Q", pll_q);
304 print_frequency(fmt, "PLL.R", pll_r);
305 }
306 None => defmt::write!(fmt, ", PLL: OFF"),
307 }
308 }
309 }
310
311 #[cfg(pll2)]
312 cfg_select! {
313 not(ra8m1) => {
314 match pll2 {
315 Some(pll) => print_frequency(fmt, "PLL2", pll),
316 None => defmt::write!(fmt, ", PLL2: OFF"),
317 }
318 }
319 ra8m1 => {
320 match pll2 {
321 Some((pll_p, pll_q, pll_r)) => {
322 print_frequency(fmt, "PLL2.P", pll_p);
323 print_frequency(fmt, "PLL2.Q", pll_q);
324 print_frequency(fmt, "PLL2.R", pll_r);
325 }
326 None => defmt::write!(fmt, ", PLL2: OFF"),
327 }
328 }
329 }
330
331 defmt::write!(fmt, ", ROOT: {}", cksel);
332
333 print_frequency(fmt, "ICLK", system.convert());
334 print_frequency(fmt, "FCLK", flash.convert());
335
336 #[cfg(bclk)]
337 print_frequency(fmt, "BCLK", bus_clock.convert());
338
339 #[cfg(pclka)]
340 print_frequency(fmt, "PCLKA", peripheral_a.convert());
341
342 #[cfg(pclkb)]
343 print_frequency(fmt, "PCLKB", peripheral_b.convert());
344
345 #[cfg(pclkc)]
346 print_frequency(fmt, "PCLKC", peripheral_c.convert());
347
348 #[cfg(pclkd)]
349 print_frequency(fmt, "PCLKD", peripheral_d.convert());
350
351 #[cfg(pclke)]
352 print_frequency(fmt, "PCLKE", peripheral_e.convert());
353
354 #[cfg(usbclk)]
355 if let Some(usb) = usb {
356 print_frequency(fmt, "USB", usb.convert());
357 } else {
358 defmt::write!(fmt, ", USB: OFF");
359 }
360
361 #[cfg(sciclk)]
362 if let Some(sci) = sci {
363 print_frequency(fmt, "SCI", sci.convert());
364 } else {
365 defmt::write!(fmt, ", SCI: OFF");
366 }
367
368 #[cfg(spiclk)]
369 if let Some(spi) = spi {
370 print_frequency(fmt, "SPI", spi.convert());
371 } else {
372 defmt::write!(fmt, ", SPI: OFF");
373 }
374 }
375}
376
377include!(concat!(env!("OUT_DIR"), "/hoco.rs"));