esp_hal/clock/
mod.rs

1//! # CPU Clock Control
2//!
3//! ## Overview
4//!
5//! Clocks are mainly sourced from oscillator (OSC), RC, and PLL circuits, and
6//! then processed by the dividers or selectors, which allows most functional
7//! modules to select their working clock according to their power consumption
8//! and performance requirements.
9//!
10//! The clock subsystem  is used to source and distribute system/module clocks
11//! from a range of root clocks. The clock tree driver maintains the basic
12//! functionality of the system clock and the intricate relationship among
13//! module clocks.
14//!
15//! ## Configuration
16//!
17//! During HAL initialization, specify a CPU clock speed to configure the
18//! desired clock frequencies.
19//!
20//! The `CPU clock` is responsible for defining the speed at which the central
21//! processing unit (CPU) operates. This driver provides predefined options for
22//! different CPU clock speeds, such as
23#![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//! ### Frozen Clock Frequencies
29//!
30//! Once the clock configuration is applied, the clock frequencies become
31//! `frozen` and cannot be changed.
32//!
33//! ## Examples
34//!
35//! ### Initialize With Different Clock Frequencies
36//! ```rust, no_run
37#![doc = crate::before_snippet!()]
38//! use esp_hal::clock::CpuClock;
39//!
40//! // Initialize with the highest possible frequency for this chip
41//! let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max());
42//! let peripherals = esp_hal::init(config);
43//! # Ok(())
44//! # }
45//! ```
46
47#[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/// Clock properties
64#[doc(hidden)]
65pub trait Clock {
66    /// Frequency of the clock in [Rate].
67    fn frequency(&self) -> Rate;
68
69    /// Frequency of the clock in Megahertz
70    fn mhz(&self) -> u32 {
71        self.frequency().as_mhz()
72    }
73
74    /// Frequency of the clock in Hertz
75    fn hz(&self) -> u32 {
76        self.frequency().as_hz()
77    }
78}
79
80/// CPU clock speed
81#[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    /// 80MHz CPU clock
90    #[cfg(not(esp32h2))]
91    _80MHz  = 80,
92
93    /// 96MHz CPU clock
94    #[cfg(esp32h2)]
95    _96MHz  = 96,
96
97    /// 120MHz CPU clock
98    #[cfg(esp32c2)]
99    _120MHz = 120,
100
101    /// 160MHz CPU clock
102    #[cfg(not(any(esp32c2, esp32h2)))]
103    _160MHz = 160,
104
105    /// 240MHz CPU clock
106    #[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                // FIXME: I don't think this is correct in general?
117                Self::_80MHz
118            }
119        }
120    }
121}
122
123impl CpuClock {
124    /// Use the highest possible frequency for a particular chip.
125    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/// XTAL clock speed
147#[instability::unstable]
148#[derive(Debug, Clone, Copy)]
149#[non_exhaustive]
150pub enum XtalClock {
151    /// 26MHz XTAL clock
152    #[cfg(any(esp32, esp32c2))]
153    _26M,
154    /// 32MHz XTAL clock
155    #[cfg(any(esp32c3, esp32h2, esp32s3))]
156    _32M,
157    /// 40MHz XTAL clock
158    #[cfg(not(esp32h2))]
159    _40M,
160    /// Other XTAL clock
161    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/// Clock frequencies.
257#[derive(Debug, Clone, Copy)]
258#[cfg_attr(feature = "defmt", derive(defmt::Format))]
259#[non_exhaustive]
260#[doc(hidden)]
261pub struct Clocks {
262    /// CPU clock frequency
263    pub cpu_clock: Rate,
264
265    /// APB clock frequency
266    pub apb_clock: Rate,
267
268    /// XTAL clock frequency
269    pub xtal_clock: Rate,
270
271    /// I2C clock frequency
272    #[cfg(esp32)]
273    pub i2c_clock: Rate,
274
275    /// PWM clock frequency
276    #[cfg(esp32)]
277    pub pwm_clock: Rate,
278
279    /// Crypto PWM  clock frequency
280    #[cfg(esp32s3)]
281    pub crypto_pwm_clock: Rate,
282
283    /// Crypto clock frequency
284    #[cfg(any(esp32c6, esp32h2))]
285    pub crypto_clock: Rate,
286
287    /// PLL 48M clock frequency (fixed)
288    #[cfg(esp32h2)]
289    pub pll_48m_clock: Rate,
290
291    /// PLL 96M clock frequency (fixed)
292    #[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            // Safety: ACTIVE_CLOCKS is only set in `init` and never modified after that.
308            let clocks = &*core::ptr::addr_of!(ACTIVE_CLOCKS);
309            clocks.as_ref()
310        }
311    }
312
313    /// Get the active clock configuration.
314    pub fn get<'a>() -> &'a Clocks {
315        unwrap!(Self::try_get())
316    }
317
318    /// Returns the xtal frequency.
319    ///
320    /// This function will run the frequency estimation if called before
321    /// [`crate::init()`].
322    #[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), // Can't be `unreachable!` due to const eval.
348                    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    /// Configure the CPU clock speed.
357    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            // The docs are unclear here. pwm_clock seems to be tied to clocks.apb_clock
379            // while simultaneously being fixed at 160 MHz.
380            // Testing showed 160 MHz to be correct for current clock configurations.
381            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), // Can't be `unreachable!` due to const eval.
399                    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    /// Configure the CPU clock speed.
408    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    /// Configure the CPU clock speed.
445    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    /// Configure the CPU clock speed.
481    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    /// Configure the CPU clock speed.
518    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    /// Configure the CPU clock speed.
557    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    /// Configure the CPU clock speed.
579    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/// Control the radio peripheral clocks
596#[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    /// Create a new instance of the radio clock controller
605    #[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    /// Enable the PHY clocks
612    #[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    /// Enable the Bluetooth clocks
620    #[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    /// Enable the WiFi clocks
628    #[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    /// Enable the IEEE 802.15.4 peripheral clocks
636    #[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    /// Reset the MAC
644    #[instability::unstable]
645    #[inline]
646    pub fn reset_mac(&mut self) {
647        clocks_ll::reset_mac();
648    }
649
650    /// Do any common initial initialization needed
651    #[instability::unstable]
652    #[inline]
653    pub fn init_clocks(&mut self) {
654        clocks_ll::init_clocks();
655    }
656
657    /// Initialize BLE RTC clocks
658    #[instability::unstable]
659    #[inline]
660    pub fn ble_rtc_clk_init(&mut self) {
661        clocks_ll::ble_rtc_clk_init();
662    }
663
664    /// Reset the Resolvable Private Address (RPA).
665    #[instability::unstable]
666    #[inline]
667    pub fn reset_rpa(&mut self) {
668        clocks_ll::reset_rpa();
669    }
670}