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