1#![cfg_attr(not(esp32h2), doc = "* 80MHz")]
24#![cfg_attr(esp32h2, doc = "* 96MHz")]
25#![cfg_attr(esp32c2, doc = "* 120MHz")]
26#![cfg_attr(not(any(esp32c2, esp32h2)), doc = "* 160MHz")]
27#![cfg_attr(xtensa, doc = "* 240MHz")]
28#![doc = crate::before_snippet!()]
38#[cfg(any(esp32, esp32c2))]
48use crate::rtc_cntl::RtcClock;
49use crate::time::Rate;
50
51#[cfg_attr(esp32, path = "clocks_ll/esp32.rs")]
52#[cfg_attr(esp32c2, path = "clocks_ll/esp32c2.rs")]
53#[cfg_attr(esp32c3, path = "clocks_ll/esp32c3.rs")]
54#[cfg_attr(esp32c6, path = "clocks_ll/esp32c6.rs")]
55#[cfg_attr(esp32h2, path = "clocks_ll/esp32h2.rs")]
56#[cfg_attr(esp32s2, path = "clocks_ll/esp32s2.rs")]
57#[cfg_attr(esp32s3, path = "clocks_ll/esp32s3.rs")]
58pub(crate) mod clocks_ll;
59
60#[doc(hidden)]
62pub trait Clock {
63 fn frequency(&self) -> Rate;
65
66 fn mhz(&self) -> u32 {
68 self.frequency().as_mhz()
69 }
70
71 fn hz(&self) -> u32 {
73 self.frequency().as_hz()
74 }
75}
76
77#[derive(Debug, Clone, Copy, PartialEq, Eq)]
79#[cfg_attr(feature = "defmt", derive(defmt::Format))]
80#[allow(
81 clippy::enum_variant_names,
82 reason = "MHz suffix indicates physical unit."
83)]
84#[non_exhaustive]
85pub enum CpuClock {
86 #[cfg(not(esp32h2))]
88 _80MHz = 80,
89
90 #[cfg(esp32h2)]
92 _96MHz = 96,
93
94 #[cfg(esp32c2)]
96 _120MHz = 120,
97
98 #[cfg(not(any(esp32c2, esp32h2)))]
100 _160MHz = 160,
101
102 #[cfg(xtensa)]
104 _240MHz = 240,
105}
106
107impl Default for CpuClock {
108 fn default() -> Self {
109 cfg_if::cfg_if! {
110 if #[cfg(esp32h2)] {
111 Self::_96MHz
112 } else {
113 Self::_80MHz
115 }
116 }
117 }
118}
119
120impl CpuClock {
121 pub const fn max() -> Self {
123 cfg_if::cfg_if! {
124 if #[cfg(esp32c2)] {
125 Self::_120MHz
126 } else if #[cfg(any(esp32c3, esp32c6))] {
127 Self::_160MHz
128 } else if #[cfg(esp32h2)] {
129 Self::_96MHz
130 } else {
131 Self::_240MHz
132 }
133 }
134 }
135}
136
137impl Clock for CpuClock {
138 fn frequency(&self) -> Rate {
139 Rate::from_mhz(*self as u32)
140 }
141}
142
143#[instability::unstable]
145#[derive(Debug, Clone, Copy)]
146#[non_exhaustive]
147pub enum XtalClock {
148 #[cfg(any(esp32, esp32c2))]
150 _26M,
151 #[cfg(any(esp32c3, esp32h2, esp32s3))]
153 _32M,
154 #[cfg(not(esp32h2))]
156 _40M,
157 Other(u32),
159}
160
161impl Clock for XtalClock {
162 fn frequency(&self) -> Rate {
163 match self {
164 #[cfg(any(esp32, esp32c2))]
165 XtalClock::_26M => Rate::from_mhz(26),
166 #[cfg(any(esp32c3, esp32h2, esp32s3))]
167 XtalClock::_32M => Rate::from_mhz(32),
168 #[cfg(not(esp32h2))]
169 XtalClock::_40M => Rate::from_mhz(40),
170 XtalClock::Other(mhz) => Rate::from_mhz(*mhz),
171 }
172 }
173}
174
175#[allow(clippy::enum_variant_names, unused)]
176#[derive(Debug, Clone, Copy, PartialEq)]
177pub(crate) enum PllClock {
178 #[cfg(esp32h2)]
179 Pll8MHz,
180 #[cfg(any(esp32c6, esp32h2))]
181 Pll48MHz,
182 #[cfg(esp32h2)]
183 Pll64MHz,
184 #[cfg(esp32c6)]
185 Pll80MHz,
186 #[cfg(esp32h2)]
187 Pll96MHz,
188 #[cfg(esp32c6)]
189 Pll120MHz,
190 #[cfg(esp32c6)]
191 Pll160MHz,
192 #[cfg(esp32c6)]
193 Pll240MHz,
194 #[cfg(not(any(esp32c2, esp32c6, esp32h2)))]
195 Pll320MHz,
196 #[cfg(not(esp32h2))]
197 Pll480MHz,
198}
199
200impl Clock for PllClock {
201 fn frequency(&self) -> Rate {
202 match self {
203 #[cfg(esp32h2)]
204 Self::Pll8MHz => Rate::from_mhz(8),
205 #[cfg(any(esp32c6, esp32h2))]
206 Self::Pll48MHz => Rate::from_mhz(48),
207 #[cfg(esp32h2)]
208 Self::Pll64MHz => Rate::from_mhz(64),
209 #[cfg(esp32c6)]
210 Self::Pll80MHz => Rate::from_mhz(80),
211 #[cfg(esp32h2)]
212 Self::Pll96MHz => Rate::from_mhz(96),
213 #[cfg(esp32c6)]
214 Self::Pll120MHz => Rate::from_mhz(120),
215 #[cfg(esp32c6)]
216 Self::Pll160MHz => Rate::from_mhz(160),
217 #[cfg(esp32c6)]
218 Self::Pll240MHz => Rate::from_mhz(240),
219 #[cfg(not(any(esp32c2, esp32c6, esp32h2)))]
220 Self::Pll320MHz => Rate::from_mhz(320),
221 #[cfg(not(esp32h2))]
222 Self::Pll480MHz => Rate::from_mhz(480),
223 }
224 }
225}
226
227#[allow(unused)]
228#[derive(Debug, Clone, Copy)]
229pub(crate) enum ApbClock {
230 #[cfg(esp32h2)]
231 ApbFreq32MHz,
232 #[cfg(not(esp32h2))]
233 ApbFreq40MHz,
234 #[cfg(not(esp32h2))]
235 ApbFreq80MHz,
236 ApbFreqOther(u32),
237}
238
239impl Clock for ApbClock {
240 fn frequency(&self) -> Rate {
241 match self {
242 #[cfg(esp32h2)]
243 ApbClock::ApbFreq32MHz => Rate::from_mhz(32),
244 #[cfg(not(esp32h2))]
245 ApbClock::ApbFreq40MHz => Rate::from_mhz(40),
246 #[cfg(not(esp32h2))]
247 ApbClock::ApbFreq80MHz => Rate::from_mhz(80),
248 ApbClock::ApbFreqOther(mhz) => Rate::from_mhz(*mhz),
249 }
250 }
251}
252
253#[derive(Debug, Clone, Copy)]
255#[cfg_attr(feature = "defmt", derive(defmt::Format))]
256#[non_exhaustive]
257#[doc(hidden)]
258pub struct Clocks {
259 pub cpu_clock: Rate,
261
262 pub apb_clock: Rate,
264
265 pub xtal_clock: Rate,
267
268 #[cfg(esp32)]
270 pub i2c_clock: Rate,
271
272 #[cfg(esp32)]
274 pub pwm_clock: Rate,
275
276 #[cfg(esp32s3)]
278 pub crypto_pwm_clock: Rate,
279
280 #[cfg(any(esp32c6, esp32h2))]
282 pub crypto_clock: Rate,
283
284 #[cfg(esp32h2)]
286 pub pll_48m_clock: Rate,
287
288 #[cfg(esp32h2)]
290 pub pll_96m_clock: Rate,
291}
292
293static mut ACTIVE_CLOCKS: Option<Clocks> = None;
294
295impl Clocks {
296 pub(crate) fn init(cpu_clock_speed: CpuClock) {
297 critical_section::with(|_| {
298 unsafe { ACTIVE_CLOCKS = Some(Self::configure(cpu_clock_speed)) };
299 })
300 }
301
302 fn try_get<'a>() -> Option<&'a Clocks> {
303 unsafe {
304 let clocks = &*core::ptr::addr_of!(ACTIVE_CLOCKS);
306 clocks.as_ref()
307 }
308 }
309
310 pub fn get<'a>() -> &'a Clocks {
312 unwrap!(Self::try_get())
313 }
314
315 #[cfg(systimer)]
320 #[inline]
321 pub(crate) fn xtal_freq() -> Rate {
322 if esp_config::esp_config_str!("ESP_HAL_CONFIG_XTAL_FREQUENCY") == "auto" {
323 if let Some(clocks) = Self::try_get() {
324 return clocks.xtal_clock;
325 }
326 }
327
328 Self::measure_xtal_frequency().frequency()
329 }
330}
331
332#[cfg(esp32)]
333impl Clocks {
334 fn measure_xtal_frequency() -> XtalClock {
335 if esp_config::esp_config_str!("ESP_HAL_CONFIG_XTAL_FREQUENCY") == "auto" {
336 if RtcClock::estimate_xtal_frequency() > 33 {
337 XtalClock::_40M
338 } else {
339 XtalClock::_26M
340 }
341 } else {
342 const {
343 let frequency_conf = esp_config::esp_config_str!("ESP_HAL_CONFIG_XTAL_FREQUENCY");
344 match frequency_conf.as_bytes() {
345 b"auto" => XtalClock::Other(0), b"26" => XtalClock::_26M,
347 b"40" => XtalClock::_40M,
348 _ => XtalClock::Other(esp_config::esp_config_int_parse!(u32, frequency_conf)),
349 }
350 }
351 }
352 }
353
354 pub(crate) fn configure(cpu_clock_speed: CpuClock) -> Self {
356 let xtal_freq = Self::measure_xtal_frequency();
357
358 if cpu_clock_speed != CpuClock::default() {
359 let pll_freq = match cpu_clock_speed {
360 CpuClock::_80MHz => PllClock::Pll320MHz,
361 CpuClock::_160MHz => PllClock::Pll320MHz,
362 CpuClock::_240MHz => PllClock::Pll480MHz,
363 };
364
365 clocks_ll::esp32_rtc_update_to_xtal(xtal_freq, 1);
366 clocks_ll::esp32_rtc_bbpll_enable();
367 clocks_ll::esp32_rtc_bbpll_configure(xtal_freq, pll_freq);
368 clocks_ll::set_cpu_freq(cpu_clock_speed);
369 }
370
371 Self {
372 cpu_clock: cpu_clock_speed.frequency(),
373 apb_clock: Rate::from_mhz(80),
374 xtal_clock: Rate::from_mhz(xtal_freq.mhz()),
375 i2c_clock: Rate::from_mhz(80),
376 pwm_clock: Rate::from_mhz(160),
380 }
381 }
382}
383
384#[cfg(esp32c2)]
385impl Clocks {
386 fn measure_xtal_frequency() -> XtalClock {
387 if esp_config::esp_config_str!("ESP_HAL_CONFIG_XTAL_FREQUENCY") == "auto" {
388 if RtcClock::estimate_xtal_frequency() > 33 {
389 XtalClock::_40M
390 } else {
391 XtalClock::_26M
392 }
393 } else {
394 const {
395 let frequency_conf = esp_config::esp_config_str!("ESP_HAL_CONFIG_XTAL_FREQUENCY");
396 match frequency_conf.as_bytes() {
397 b"auto" => XtalClock::Other(0), b"26" => XtalClock::_26M,
399 b"40" => XtalClock::_40M,
400 _ => XtalClock::Other(esp_config::esp_config_int_parse!(u32, frequency_conf)),
401 }
402 }
403 }
404 }
405
406 pub(crate) fn configure(cpu_clock_speed: CpuClock) -> Self {
408 let xtal_freq = Self::measure_xtal_frequency();
409
410 let apb_freq;
411 if cpu_clock_speed != CpuClock::default() {
412 let pll_freq = PllClock::Pll480MHz;
413
414 if cpu_clock_speed.mhz() <= xtal_freq.mhz() {
415 apb_freq = ApbClock::ApbFreqOther(cpu_clock_speed.mhz());
416 clocks_ll::esp32c2_rtc_update_to_xtal(xtal_freq, 1);
417 clocks_ll::esp32c2_rtc_apb_freq_update(apb_freq);
418 } else {
419 apb_freq = ApbClock::ApbFreq40MHz;
420 clocks_ll::esp32c2_rtc_bbpll_enable();
421 clocks_ll::esp32c2_rtc_bbpll_configure(xtal_freq, pll_freq);
422 clocks_ll::esp32c2_rtc_freq_to_pll_mhz(cpu_clock_speed);
423 clocks_ll::esp32c2_rtc_apb_freq_update(apb_freq);
424 }
425 } else {
426 apb_freq = ApbClock::ApbFreq40MHz;
427 }
428
429 Self {
430 cpu_clock: cpu_clock_speed.frequency(),
431 apb_clock: apb_freq.frequency(),
432 xtal_clock: xtal_freq.frequency(),
433 }
434 }
435}
436
437#[cfg(esp32c3)]
438impl Clocks {
439 fn measure_xtal_frequency() -> XtalClock {
440 XtalClock::_40M
441 }
442
443 pub(crate) fn configure(cpu_clock_speed: CpuClock) -> Self {
445 let xtal_freq = Self::measure_xtal_frequency();
446
447 let apb_freq;
448 if cpu_clock_speed != CpuClock::default() {
449 if cpu_clock_speed.mhz() <= xtal_freq.mhz() {
450 apb_freq = ApbClock::ApbFreqOther(cpu_clock_speed.mhz());
451 clocks_ll::esp32c3_rtc_update_to_xtal(xtal_freq, 1);
452 clocks_ll::esp32c3_rtc_apb_freq_update(apb_freq);
453 } else {
454 let pll_freq = PllClock::Pll480MHz;
455 apb_freq = ApbClock::ApbFreq80MHz;
456 clocks_ll::esp32c3_rtc_bbpll_enable();
457 clocks_ll::esp32c3_rtc_bbpll_configure(xtal_freq, pll_freq);
458 clocks_ll::esp32c3_rtc_freq_to_pll_mhz(cpu_clock_speed);
459 clocks_ll::esp32c3_rtc_apb_freq_update(apb_freq);
460 }
461 } else {
462 apb_freq = ApbClock::ApbFreq80MHz;
463 }
464
465 Self {
466 cpu_clock: cpu_clock_speed.frequency(),
467 apb_clock: apb_freq.frequency(),
468 xtal_clock: xtal_freq.frequency(),
469 }
470 }
471}
472
473#[cfg(esp32c6)]
474impl Clocks {
475 fn measure_xtal_frequency() -> XtalClock {
476 XtalClock::_40M
477 }
478
479 pub(crate) fn configure(cpu_clock_speed: CpuClock) -> Self {
481 let xtal_freq = Self::measure_xtal_frequency();
482
483 let apb_freq;
484 if cpu_clock_speed != CpuClock::default() {
485 if cpu_clock_speed.mhz() <= xtal_freq.mhz() {
486 apb_freq = ApbClock::ApbFreqOther(cpu_clock_speed.mhz());
487 clocks_ll::esp32c6_rtc_update_to_xtal(xtal_freq, 1);
488 clocks_ll::esp32c6_rtc_apb_freq_update(apb_freq);
489 } else {
490 let pll_freq = PllClock::Pll480MHz;
491 apb_freq = ApbClock::ApbFreq80MHz;
492 clocks_ll::esp32c6_rtc_bbpll_enable();
493 clocks_ll::esp32c6_rtc_bbpll_configure(xtal_freq, pll_freq);
494 clocks_ll::esp32c6_rtc_freq_to_pll_mhz(cpu_clock_speed);
495 clocks_ll::esp32c6_rtc_apb_freq_update(apb_freq);
496 }
497 } else {
498 apb_freq = ApbClock::ApbFreq80MHz;
499 }
500
501 Self {
502 cpu_clock: cpu_clock_speed.frequency(),
503 apb_clock: apb_freq.frequency(),
504 xtal_clock: xtal_freq.frequency(),
505 crypto_clock: Rate::from_mhz(160),
506 }
507 }
508}
509
510#[cfg(esp32h2)]
511impl Clocks {
512 fn measure_xtal_frequency() -> XtalClock {
513 XtalClock::_32M
514 }
515
516 pub(crate) fn configure(cpu_clock_speed: CpuClock) -> Self {
518 let xtal_freq = Self::measure_xtal_frequency();
519
520 let apb_freq;
521 if cpu_clock_speed != CpuClock::default() {
522 if cpu_clock_speed.mhz() <= xtal_freq.mhz() {
523 apb_freq = ApbClock::ApbFreqOther(cpu_clock_speed.mhz());
524 clocks_ll::esp32h2_rtc_update_to_xtal(xtal_freq, 1);
525 clocks_ll::esp32h2_rtc_apb_freq_update(apb_freq);
526 } else {
527 let pll_freq = PllClock::Pll96MHz;
528 apb_freq = ApbClock::ApbFreq32MHz;
529 clocks_ll::esp32h2_rtc_bbpll_enable();
530 clocks_ll::esp32h2_rtc_bbpll_configure(xtal_freq, pll_freq);
531 clocks_ll::esp32h2_rtc_freq_to_pll_mhz(cpu_clock_speed);
532 clocks_ll::esp32h2_rtc_apb_freq_update(apb_freq);
533 }
534 } else {
535 apb_freq = ApbClock::ApbFreq32MHz;
536 }
537
538 Self {
539 cpu_clock: cpu_clock_speed.frequency(),
540 apb_clock: apb_freq.frequency(),
541 xtal_clock: xtal_freq.frequency(),
542 pll_48m_clock: Rate::from_mhz(48),
543 crypto_clock: Rate::from_mhz(96),
544 pll_96m_clock: Rate::from_mhz(96),
545 }
546 }
547}
548
549#[cfg(esp32s2)]
550impl Clocks {
551 fn measure_xtal_frequency() -> XtalClock {
552 XtalClock::_40M
553 }
554
555 pub(crate) fn configure(cpu_clock_speed: CpuClock) -> Self {
557 let xtal_freq = Self::measure_xtal_frequency();
558
559 if cpu_clock_speed != CpuClock::default() {
560 clocks_ll::set_cpu_clock(cpu_clock_speed);
561 }
562
563 Self {
564 cpu_clock: cpu_clock_speed.frequency(),
565 apb_clock: Rate::from_mhz(80),
566 xtal_clock: xtal_freq.frequency(),
567 }
568 }
569}
570
571#[cfg(esp32s3)]
572impl Clocks {
573 fn measure_xtal_frequency() -> XtalClock {
574 XtalClock::_40M
575 }
576
577 pub(crate) fn configure(cpu_clock_speed: CpuClock) -> Self {
579 let xtal_freq = Self::measure_xtal_frequency();
580
581 if cpu_clock_speed != CpuClock::default() {
582 clocks_ll::set_cpu_clock(cpu_clock_speed);
583 }
584
585 Self {
586 cpu_clock: cpu_clock_speed.frequency(),
587 apb_clock: Rate::from_mhz(80),
588 xtal_clock: xtal_freq.frequency(),
589 crypto_pwm_clock: Rate::from_mhz(160),
590 }
591 }
592}
593
594#[cfg(any(bt, ieee802154, wifi))]
596#[instability::unstable]
597pub struct RadioClockController<'d> {
598 _rcc: crate::peripherals::RADIO_CLK<'d>,
599}
600
601#[cfg(any(bt, ieee802154, wifi))]
602impl<'d> RadioClockController<'d> {
603 #[instability::unstable]
605 pub fn new(rcc: crate::peripherals::RADIO_CLK<'d>) -> Self {
606 Self { _rcc: rcc }
607 }
608
609 #[instability::unstable]
611 #[cfg(phy)]
612 #[inline]
613 pub fn enable_phy(&mut self, enable: bool) {
614 clocks_ll::enable_phy(enable);
615 }
616
617 #[instability::unstable]
619 #[cfg(bt)]
620 #[inline]
621 pub fn enable_bt(&mut self, enable: bool) {
622 clocks_ll::enable_bt(enable);
623 }
624
625 #[instability::unstable]
627 #[cfg(wifi)]
628 #[inline]
629 pub fn enable_wifi(&mut self, enable: bool) {
630 clocks_ll::enable_wifi(enable);
631 }
632
633 #[instability::unstable]
635 #[cfg(ieee802154)]
636 #[inline]
637 pub fn enable_ieee802154(&mut self, enable: bool) {
638 clocks_ll::enable_ieee802154(enable);
639 }
640
641 #[instability::unstable]
643 #[inline]
644 pub fn reset_mac(&mut self) {
645 clocks_ll::reset_mac();
646 }
647
648 #[instability::unstable]
650 #[inline]
651 pub fn init_clocks(&mut self) {
652 clocks_ll::init_clocks();
653 }
654
655 #[instability::unstable]
657 #[inline]
658 pub fn ble_rtc_clk_init(&mut self) {
659 clocks_ll::ble_rtc_clk_init();
660 }
661
662 #[instability::unstable]
664 #[inline]
665 pub fn reset_rpa(&mut self) {
666 clocks_ll::reset_rpa();
667 }
668}