esp_hal/
system.rs

1//! # System Control
2
3use core::cell::RefCell;
4
5use critical_section::{CriticalSection, Mutex};
6
7use crate::peripherals::SYSTEM;
8
9/// Peripherals which can be enabled via `PeripheralClockControl`.
10///
11/// This enum represents various hardware peripherals that can be enabled
12/// by the system's clock control. Depending on the target device, different
13/// peripherals will be available for enabling.
14// FIXME: This enum needs to be public because it's exposed via a bunch of traits, but it's not
15// useful to users.
16#[doc(hidden)]
17#[derive(Debug, Clone, Copy, PartialEq, Eq)]
18#[repr(u8)]
19#[cfg_attr(feature = "defmt", derive(defmt::Format))]
20pub enum Peripheral {
21    /// SPI2 peripheral.
22    #[cfg(spi2)]
23    Spi2,
24    /// SPI3 peripheral.
25    #[cfg(spi3)]
26    Spi3,
27    /// External I2C0 peripheral.
28    #[cfg(i2c0)]
29    I2cExt0,
30    /// External I2C1 peripheral.
31    #[cfg(i2c1)]
32    I2cExt1,
33    /// RMT peripheral (Remote Control).
34    #[cfg(rmt)]
35    Rmt,
36    /// LEDC peripheral (LED PWM Controller).
37    #[cfg(ledc)]
38    Ledc,
39    /// MCPWM0 peripheral (Motor Control PWM 0).
40    #[cfg(mcpwm0)]
41    Mcpwm0,
42    /// MCPWM1 peripheral (Motor Control PWM 1).
43    #[cfg(mcpwm1)]
44    Mcpwm1,
45    /// PCNT peripheral (Pulse Counter).
46    #[cfg(pcnt)]
47    Pcnt,
48    /// APB SAR ADC peripheral.
49    #[cfg(apb_saradc)]
50    ApbSarAdc,
51    /// General DMA (GDMA) peripheral.
52    #[cfg(gdma)]
53    Gdma,
54    /// Peripheral DMA (PDMA) peripheral.
55    #[cfg(pdma)]
56    Dma,
57    /// I2S0 peripheral (Inter-IC Sound).
58    #[cfg(i2s0)]
59    I2s0,
60    /// I2S1 peripheral (Inter-IC Sound).
61    #[cfg(i2s1)]
62    I2s1,
63    /// USB0 peripheral.
64    #[cfg(usb0)]
65    Usb,
66    /// AES peripheral (Advanced Encryption Standard).
67    #[cfg(aes)]
68    Aes,
69    /// TWAI0 peripheral.
70    #[cfg(twai0)]
71    Twai0,
72    /// TWAI1 peripheral.
73    #[cfg(twai1)]
74    Twai1,
75    /// Timer Group 0 peripheral.
76    #[cfg(timg0)]
77    Timg0,
78    /// Timer Group 1 peripheral.
79    #[cfg(timg1)]
80    Timg1,
81    /// SHA peripheral (Secure Hash Algorithm).
82    #[cfg(sha)]
83    Sha,
84    /// USB Device peripheral.
85    #[cfg(usb_device)]
86    UsbDevice,
87    /// UART0 peripheral.
88    #[cfg(uart0)]
89    Uart0,
90    /// UART1 peripheral.
91    #[cfg(uart1)]
92    Uart1,
93    /// UART2 peripheral.
94    #[cfg(uart2)]
95    Uart2,
96    /// RSA peripheral (Rivest-Shamir-Adleman encryption).
97    #[cfg(rsa)]
98    Rsa,
99    /// Parallel IO peripheral.
100    #[cfg(parl_io)]
101    ParlIo,
102    /// HMAC peripheral (Hash-based Message Authentication Code).
103    #[cfg(hmac)]
104    Hmac,
105    /// ECC peripheral (Elliptic Curve Cryptography).
106    #[cfg(ecc)]
107    Ecc,
108    /// SOC ETM peripheral (Event Task Manager).
109    #[cfg(soc_etm)]
110    Etm,
111    /// TRACE0 peripheral (Debug trace).
112    #[cfg(trace0)]
113    Trace0,
114    /// LCD Camera peripheral.
115    #[cfg(lcd_cam)]
116    LcdCam,
117    /// Systimer peripheral.
118    #[cfg(systimer)]
119    Systimer,
120    /// Temperature sensor peripheral.
121    #[cfg(tsens)]
122    Tsens,
123}
124
125impl Peripheral {
126    const KEEP_ENABLED: &[Peripheral] = &[
127        Peripheral::Uart0,
128        #[cfg(usb_device)]
129        Peripheral::UsbDevice,
130        #[cfg(systimer)]
131        Peripheral::Systimer,
132        Peripheral::Timg0,
133    ];
134
135    const COUNT: usize = Self::ALL.len();
136
137    const ALL: &[Self] = &[
138        #[cfg(spi2)]
139        Self::Spi2,
140        #[cfg(spi3)]
141        Self::Spi3,
142        #[cfg(i2c0)]
143        Self::I2cExt0,
144        #[cfg(i2c1)]
145        Self::I2cExt1,
146        #[cfg(rmt)]
147        Self::Rmt,
148        #[cfg(ledc)]
149        Self::Ledc,
150        #[cfg(mcpwm0)]
151        Self::Mcpwm0,
152        #[cfg(mcpwm1)]
153        Self::Mcpwm1,
154        #[cfg(pcnt)]
155        Self::Pcnt,
156        #[cfg(apb_saradc)]
157        Self::ApbSarAdc,
158        #[cfg(gdma)]
159        Self::Gdma,
160        #[cfg(pdma)]
161        Self::Dma,
162        #[cfg(i2s0)]
163        Self::I2s0,
164        #[cfg(i2s1)]
165        Self::I2s1,
166        #[cfg(usb0)]
167        Self::Usb,
168        #[cfg(aes)]
169        Self::Aes,
170        #[cfg(twai0)]
171        Self::Twai0,
172        #[cfg(twai1)]
173        Self::Twai1,
174        #[cfg(timg0)]
175        Self::Timg0,
176        #[cfg(timg1)]
177        Self::Timg1,
178        #[cfg(sha)]
179        Self::Sha,
180        #[cfg(usb_device)]
181        Self::UsbDevice,
182        #[cfg(uart0)]
183        Self::Uart0,
184        #[cfg(uart1)]
185        Self::Uart1,
186        #[cfg(uart2)]
187        Self::Uart2,
188        #[cfg(rsa)]
189        Self::Rsa,
190        #[cfg(parl_io)]
191        Self::ParlIo,
192        #[cfg(hmac)]
193        Self::Hmac,
194        #[cfg(ecc)]
195        Self::Ecc,
196        #[cfg(soc_etm)]
197        Self::Etm,
198        #[cfg(trace0)]
199        Self::Trace0,
200        #[cfg(lcd_cam)]
201        Self::LcdCam,
202        #[cfg(systimer)]
203        Self::Systimer,
204        #[cfg(tsens)]
205        Self::Tsens,
206    ];
207}
208
209impl Peripheral {
210    pub fn try_from(value: u8) -> Option<Peripheral> {
211        if value >= Peripheral::COUNT as u8 {
212            return None;
213        }
214
215        Some(unsafe { core::mem::transmute::<u8, Peripheral>(value) })
216    }
217}
218
219static PERIPHERAL_REF_COUNT: Mutex<RefCell<[usize; Peripheral::COUNT]>> =
220    Mutex::new(RefCell::new([0; Peripheral::COUNT]));
221
222/// Disable all peripherals.
223///
224/// Peripherals listed in [KEEP_ENABLED] are NOT disabled.
225pub(crate) fn disable_peripherals() {
226    // Take the critical section up front to avoid taking it multiple times.
227    critical_section::with(|cs| {
228        for p in Peripheral::ALL {
229            if Peripheral::KEEP_ENABLED.contains(p) {
230                continue;
231            }
232            PeripheralClockControl::enable_forced_with_cs(*p, false, true, cs);
233        }
234    })
235}
236
237#[derive(Debug, PartialEq, Eq)]
238#[cfg_attr(feature = "defmt", derive(defmt::Format))]
239pub(crate) struct PeripheralGuard {
240    peripheral: Peripheral,
241}
242
243impl PeripheralGuard {
244    pub(crate) fn new_with(p: Peripheral, init: fn()) -> Self {
245        if !Peripheral::KEEP_ENABLED.contains(&p) && PeripheralClockControl::enable(p) {
246            PeripheralClockControl::reset(p);
247            init();
248        }
249
250        Self { peripheral: p }
251    }
252
253    pub(crate) fn new(p: Peripheral) -> Self {
254        Self::new_with(p, || {})
255    }
256}
257
258impl Drop for PeripheralGuard {
259    fn drop(&mut self) {
260        if !Peripheral::KEEP_ENABLED.contains(&self.peripheral) {
261            PeripheralClockControl::disable(self.peripheral);
262        }
263    }
264}
265
266#[derive(Debug)]
267#[cfg_attr(feature = "defmt", derive(defmt::Format))]
268pub(crate) struct GenericPeripheralGuard<const P: u8> {}
269
270impl<const P: u8> GenericPeripheralGuard<P> {
271    pub(crate) fn new_with(init: fn(CriticalSection<'_>)) -> Self {
272        let peripheral = unwrap!(Peripheral::try_from(P));
273        critical_section::with(|cs| {
274            if !Peripheral::KEEP_ENABLED.contains(&peripheral)
275                && PeripheralClockControl::enable_with_cs(peripheral, cs)
276            {
277                PeripheralClockControl::reset(peripheral);
278                init(cs);
279            }
280        });
281
282        Self {}
283    }
284
285    pub(crate) fn new() -> Self {
286        Self::new_with(|_| {})
287    }
288}
289
290impl<const P: u8> Drop for GenericPeripheralGuard<P> {
291    fn drop(&mut self) {
292        let peripheral = unwrap!(Peripheral::try_from(P));
293        if !Peripheral::KEEP_ENABLED.contains(&peripheral) {
294            PeripheralClockControl::disable(peripheral);
295        }
296    }
297}
298
299/// Controls the enablement of peripheral clocks.
300pub(crate) struct PeripheralClockControl;
301
302#[cfg(not(any(esp32c6, esp32h2)))]
303impl PeripheralClockControl {
304    fn enable_internal(peripheral: Peripheral, enable: bool, _cs: CriticalSection<'_>) {
305        debug!("Enable {:?} {}", peripheral, enable);
306
307        let system = SYSTEM::regs();
308
309        #[cfg(esp32)]
310        let (perip_clk_en0, peri_clk_en) = { (&system.perip_clk_en(), &system.peri_clk_en()) };
311        #[cfg(not(esp32))]
312        let perip_clk_en0 = &system.perip_clk_en0();
313
314        #[cfg(any(esp32c2, esp32c3, esp32s2, esp32s3))]
315        let perip_clk_en1 = &system.perip_clk_en1();
316
317        match peripheral {
318            #[cfg(spi2)]
319            Peripheral::Spi2 => {
320                perip_clk_en0.modify(|_, w| w.spi2_clk_en().bit(enable));
321            }
322            #[cfg(spi3)]
323            Peripheral::Spi3 => {
324                perip_clk_en0.modify(|_, w| w.spi3_clk_en().bit(enable));
325            }
326            #[cfg(all(i2c0, esp32))]
327            Peripheral::I2cExt0 => {
328                perip_clk_en0.modify(|_, w| w.i2c0_ext0_clk_en().bit(enable));
329            }
330            #[cfg(all(i2c0, not(esp32)))]
331            Peripheral::I2cExt0 => {
332                perip_clk_en0.modify(|_, w| w.i2c_ext0_clk_en().bit(enable));
333            }
334            #[cfg(i2c1)]
335            Peripheral::I2cExt1 => {
336                perip_clk_en0.modify(|_, w| w.i2c_ext1_clk_en().bit(enable));
337            }
338            #[cfg(rmt)]
339            Peripheral::Rmt => {
340                perip_clk_en0.modify(|_, w| w.rmt_clk_en().bit(enable));
341            }
342            #[cfg(ledc)]
343            Peripheral::Ledc => {
344                perip_clk_en0.modify(|_, w| w.ledc_clk_en().bit(enable));
345            }
346            #[cfg(mcpwm0)]
347            Peripheral::Mcpwm0 => {
348                perip_clk_en0.modify(|_, w| w.pwm0_clk_en().bit(enable));
349            }
350            #[cfg(mcpwm1)]
351            Peripheral::Mcpwm1 => {
352                perip_clk_en0.modify(|_, w| w.pwm1_clk_en().bit(enable));
353            }
354            #[cfg(pcnt)]
355            Peripheral::Pcnt => {
356                perip_clk_en0.modify(|_, w| w.pcnt_clk_en().bit(enable));
357            }
358            #[cfg(apb_saradc)]
359            Peripheral::ApbSarAdc => {
360                perip_clk_en0.modify(|_, w| w.apb_saradc_clk_en().bit(enable));
361            }
362            #[cfg(gdma)]
363            Peripheral::Gdma => {
364                perip_clk_en1.modify(|_, w| w.dma_clk_en().bit(enable));
365            }
366            #[cfg(esp32)]
367            Peripheral::Dma => {
368                perip_clk_en0.modify(|_, w| w.spi_dma_clk_en().bit(enable));
369            }
370            #[cfg(esp32s2)]
371            Peripheral::Dma => {
372                perip_clk_en0.modify(|_, w| w.spi2_dma_clk_en().bit(enable));
373                perip_clk_en0.modify(|_, w| w.spi3_dma_clk_en().bit(enable));
374                perip_clk_en1.modify(|_, w| w.crypto_dma_clk_en().bit(enable));
375            }
376            #[cfg(esp32c3)]
377            Peripheral::I2s0 => {
378                // on ESP32-C3 note that i2s1_clk_en / rst is really I2s0
379                perip_clk_en0.modify(|_, w| w.i2s1_clk_en().bit(enable));
380            }
381            #[cfg(any(esp32s3, esp32, esp32s2))]
382            Peripheral::I2s0 => {
383                perip_clk_en0.modify(|_, w| w.i2s0_clk_en().bit(enable));
384            }
385            #[cfg(any(esp32s3, esp32))]
386            Peripheral::I2s1 => {
387                perip_clk_en0.modify(|_, w| w.i2s1_clk_en().bit(enable));
388            }
389            #[cfg(usb0)]
390            Peripheral::Usb => {
391                perip_clk_en0.modify(|_, w| w.usb_clk_en().bit(enable));
392            }
393            #[cfg(twai0)]
394            Peripheral::Twai0 => {
395                perip_clk_en0.modify(|_, w| w.twai_clk_en().bit(enable));
396            }
397            #[cfg(esp32)]
398            Peripheral::Aes => {
399                peri_clk_en.modify(|r, w| unsafe { w.bits(r.bits() | enable as u32) });
400            }
401            #[cfg(any(esp32c3, esp32s2, esp32s3))]
402            Peripheral::Aes => {
403                perip_clk_en1.modify(|_, w| w.crypto_aes_clk_en().bit(enable));
404            }
405            #[cfg(timg0)]
406            Peripheral::Timg0 => {
407                #[cfg(any(esp32c3, esp32s2, esp32s3))]
408                perip_clk_en0.modify(|_, w| w.timers_clk_en().bit(enable));
409                perip_clk_en0.modify(|_, w| w.timergroup_clk_en().bit(enable));
410            }
411            #[cfg(timg1)]
412            Peripheral::Timg1 => {
413                #[cfg(any(esp32c3, esp32s2, esp32s3))]
414                perip_clk_en0.modify(|_, w| w.timers_clk_en().bit(enable));
415                perip_clk_en0.modify(|_, w| w.timergroup1_clk_en().bit(enable));
416            }
417            #[cfg(sha)]
418            Peripheral::Sha => {
419                #[cfg(not(esp32))]
420                perip_clk_en1.modify(|_, w| w.crypto_sha_clk_en().bit(enable));
421            }
422            #[cfg(esp32c3)]
423            Peripheral::UsbDevice => {
424                perip_clk_en0.modify(|_, w| w.usb_device_clk_en().bit(enable));
425            }
426            #[cfg(esp32s3)]
427            Peripheral::UsbDevice => {
428                perip_clk_en1.modify(|_, w| w.usb_device_clk_en().bit(enable));
429            }
430            #[cfg(uart0)]
431            Peripheral::Uart0 => {
432                perip_clk_en0.modify(|_, w| w.uart_clk_en().bit(enable));
433            }
434            #[cfg(uart1)]
435            Peripheral::Uart1 => {
436                perip_clk_en0.modify(|_, w| w.uart1_clk_en().bit(enable));
437            }
438            #[cfg(all(uart2, esp32s3))]
439            Peripheral::Uart2 => {
440                perip_clk_en1.modify(|_, w| w.uart2_clk_en().set_bit());
441            }
442            #[cfg(all(uart2, esp32))]
443            Peripheral::Uart2 => {
444                perip_clk_en0.modify(|_, w| w.uart2_clk_en().bit(enable));
445            }
446            #[cfg(all(rsa, esp32))]
447            Peripheral::Rsa => {
448                peri_clk_en.modify(|r, w| unsafe { w.bits(r.bits() | ((enable as u32) << 2)) });
449            }
450            #[cfg(all(rsa, any(esp32c3, esp32s2, esp32s3)))]
451            Peripheral::Rsa => {
452                perip_clk_en1.modify(|_, w| w.crypto_rsa_clk_en().bit(enable));
453                system
454                    .rsa_pd_ctrl()
455                    .modify(|_, w| w.rsa_mem_pd().bit(!enable));
456            }
457            #[cfg(hmac)]
458            Peripheral::Hmac => {
459                perip_clk_en1.modify(|_, w| w.crypto_hmac_clk_en().bit(enable));
460            }
461            #[cfg(ecc)]
462            Peripheral::Ecc => {
463                perip_clk_en1.modify(|_, w| w.crypto_ecc_clk_en().bit(enable));
464            }
465            #[cfg(lcd_cam)]
466            Peripheral::LcdCam => {
467                perip_clk_en1.modify(|_, w| w.lcd_cam_clk_en().bit(enable));
468            }
469            #[cfg(systimer)]
470            Peripheral::Systimer => {
471                perip_clk_en0.modify(|_, w| w.systimer_clk_en().bit(enable));
472            }
473            #[cfg(tsens)]
474            Peripheral::Tsens => {
475                perip_clk_en1.modify(|_, w| w.tsens_clk_en().bit(enable));
476            }
477        }
478    }
479
480    /// Resets the given peripheral
481    pub(crate) fn reset(peripheral: Peripheral) {
482        debug!("Reset {:?}", peripheral);
483        let system = SYSTEM::regs();
484
485        #[cfg(esp32)]
486        let (perip_rst_en0, peri_rst_en) = (system.perip_rst_en(), system.peri_rst_en());
487        #[cfg(not(esp32))]
488        let perip_rst_en0 = system.perip_rst_en0();
489
490        #[cfg(any(esp32c2, esp32c3, esp32s2, esp32s3))]
491        let perip_rst_en1 = system.perip_rst_en1();
492
493        critical_section::with(|_cs| match peripheral {
494            #[cfg(spi2)]
495            Peripheral::Spi2 => {
496                perip_rst_en0.modify(|_, w| w.spi2_rst().set_bit());
497                perip_rst_en0.modify(|_, w| w.spi2_rst().clear_bit());
498            }
499            #[cfg(spi3)]
500            Peripheral::Spi3 => {
501                perip_rst_en0.modify(|_, w| w.spi3_rst().set_bit());
502                perip_rst_en0.modify(|_, w| w.spi3_rst().clear_bit());
503            }
504            #[cfg(all(i2c0, esp32))]
505            Peripheral::I2cExt0 => {
506                perip_rst_en0.modify(|_, w| w.i2c0_ext0_rst().set_bit());
507                perip_rst_en0.modify(|_, w| w.i2c0_ext0_rst().clear_bit());
508            }
509            #[cfg(all(i2c0, not(esp32)))]
510            Peripheral::I2cExt0 => {
511                perip_rst_en0.modify(|_, w| w.i2c_ext0_rst().set_bit());
512                perip_rst_en0.modify(|_, w| w.i2c_ext0_rst().clear_bit());
513            }
514            #[cfg(i2c1)]
515            Peripheral::I2cExt1 => {
516                perip_rst_en0.modify(|_, w| w.i2c_ext1_rst().set_bit());
517                perip_rst_en0.modify(|_, w| w.i2c_ext1_rst().clear_bit());
518            }
519            #[cfg(rmt)]
520            Peripheral::Rmt => {
521                perip_rst_en0.modify(|_, w| w.rmt_rst().set_bit());
522                perip_rst_en0.modify(|_, w| w.rmt_rst().clear_bit());
523            }
524            #[cfg(ledc)]
525            Peripheral::Ledc => {
526                perip_rst_en0.modify(|_, w| w.ledc_rst().set_bit());
527                perip_rst_en0.modify(|_, w| w.ledc_rst().clear_bit());
528            }
529            #[cfg(mcpwm0)]
530            Peripheral::Mcpwm0 => {
531                perip_rst_en0.modify(|_, w| w.pwm0_rst().set_bit());
532                perip_rst_en0.modify(|_, w| w.pwm0_rst().clear_bit());
533            }
534            #[cfg(mcpwm1)]
535            Peripheral::Mcpwm1 => {
536                perip_rst_en0.modify(|_, w| w.pwm1_rst().set_bit());
537                perip_rst_en0.modify(|_, w| w.pwm1_rst().clear_bit());
538            }
539            #[cfg(pcnt)]
540            Peripheral::Pcnt => {
541                perip_rst_en0.modify(|_, w| w.pcnt_rst().set_bit());
542                perip_rst_en0.modify(|_, w| w.pcnt_rst().clear_bit());
543            }
544            #[cfg(apb_saradc)]
545            Peripheral::ApbSarAdc => {
546                perip_rst_en0.modify(|_, w| w.apb_saradc_rst().set_bit());
547                perip_rst_en0.modify(|_, w| w.apb_saradc_rst().clear_bit());
548            }
549            #[cfg(gdma)]
550            Peripheral::Gdma => {
551                perip_rst_en1.modify(|_, w| w.dma_rst().set_bit());
552                perip_rst_en1.modify(|_, w| w.dma_rst().clear_bit());
553            }
554            #[cfg(esp32)]
555            Peripheral::Dma => {
556                perip_rst_en0.modify(|_, w| w.spi_dma_rst().set_bit());
557                perip_rst_en0.modify(|_, w| w.spi_dma_rst().clear_bit());
558            }
559            #[cfg(esp32s2)]
560            Peripheral::Dma => {
561                perip_rst_en0.modify(|_, w| w.spi2_dma_rst().set_bit());
562                perip_rst_en0.modify(|_, w| w.spi2_dma_rst().clear_bit());
563                perip_rst_en0.modify(|_, w| w.spi3_dma_rst().set_bit());
564                perip_rst_en0.modify(|_, w| w.spi3_dma_rst().clear_bit());
565                perip_rst_en1.modify(|_, w| w.crypto_dma_rst().set_bit());
566                perip_rst_en1.modify(|_, w| w.crypto_dma_rst().clear_bit());
567            }
568            #[cfg(esp32c3)]
569            Peripheral::I2s0 => {
570                // on ESP32-C3 note that i2s1_clk_en / rst is really I2s0
571                perip_rst_en0.modify(|_, w| w.i2s1_rst().set_bit());
572                perip_rst_en0.modify(|_, w| w.i2s1_rst().clear_bit());
573            }
574            #[cfg(any(esp32s3, esp32, esp32s2))]
575            Peripheral::I2s0 => {
576                perip_rst_en0.modify(|_, w| w.i2s0_rst().set_bit());
577                perip_rst_en0.modify(|_, w| w.i2s0_rst().clear_bit());
578            }
579            #[cfg(any(esp32s3, esp32))]
580            Peripheral::I2s1 => {
581                perip_rst_en0.modify(|_, w| w.i2s1_rst().set_bit());
582                perip_rst_en0.modify(|_, w| w.i2s1_rst().clear_bit());
583            }
584            #[cfg(usb0)]
585            Peripheral::Usb => {
586                perip_rst_en0.modify(|_, w| w.usb_rst().set_bit());
587                perip_rst_en0.modify(|_, w| w.usb_rst().clear_bit());
588            }
589            #[cfg(twai0)]
590            Peripheral::Twai0 => {
591                perip_rst_en0.modify(|_, w| w.twai_rst().set_bit());
592                perip_rst_en0.modify(|_, w| w.twai_rst().clear_bit());
593            }
594            #[cfg(esp32)]
595            Peripheral::Aes => {
596                peri_rst_en.modify(|r, w| unsafe { w.bits(r.bits() | 1) });
597                peri_rst_en.modify(|r, w| unsafe { w.bits(r.bits() & (!1)) });
598            }
599            #[cfg(any(esp32c3, esp32s2, esp32s3))]
600            Peripheral::Aes => {
601                perip_rst_en1.modify(|_, w| w.crypto_aes_rst().set_bit());
602                perip_rst_en1.modify(|_, w| w.crypto_aes_rst().clear_bit());
603            }
604            #[cfg(timg0)]
605            Peripheral::Timg0 => {
606                #[cfg(any(esp32c3, esp32s2, esp32s3))]
607                perip_rst_en0.modify(|_, w| w.timers_rst().set_bit());
608                perip_rst_en0.modify(|_, w| w.timergroup_rst().set_bit());
609                #[cfg(any(esp32c3, esp32s2, esp32s3))]
610                perip_rst_en0.modify(|_, w| w.timers_rst().clear_bit());
611                perip_rst_en0.modify(|_, w| w.timergroup_rst().clear_bit());
612            }
613            #[cfg(timg1)]
614            Peripheral::Timg1 => {
615                #[cfg(any(esp32c3, esp32s2, esp32s3))]
616                perip_rst_en0.modify(|_, w| w.timers_rst().set_bit());
617                perip_rst_en0.modify(|_, w| w.timergroup1_rst().set_bit());
618                #[cfg(any(esp32c3, esp32s2, esp32s3))]
619                perip_rst_en0.modify(|_, w| w.timers_rst().clear_bit());
620                perip_rst_en0.modify(|_, w| w.timergroup1_rst().clear_bit());
621            }
622            #[cfg(sha)]
623            Peripheral::Sha => {
624                #[cfg(not(esp32))]
625                perip_rst_en1.modify(|_, w| w.crypto_sha_rst().set_bit());
626                #[cfg(not(esp32))]
627                perip_rst_en1.modify(|_, w| w.crypto_sha_rst().clear_bit());
628            }
629            #[cfg(esp32c3)]
630            Peripheral::UsbDevice => {
631                perip_rst_en0.modify(|_, w| w.usb_device_rst().set_bit());
632                perip_rst_en0.modify(|_, w| w.usb_device_rst().clear_bit());
633            }
634            #[cfg(esp32s3)]
635            Peripheral::UsbDevice => {
636                perip_rst_en1.modify(|_, w| w.usb_device_rst().set_bit());
637                perip_rst_en1.modify(|_, w| w.usb_device_rst().clear_bit());
638            }
639            #[cfg(uart0)]
640            Peripheral::Uart0 => {
641                perip_rst_en0.modify(|_, w| w.uart_rst().set_bit());
642                perip_rst_en0.modify(|_, w| w.uart_rst().clear_bit());
643            }
644            #[cfg(uart1)]
645            Peripheral::Uart1 => {
646                perip_rst_en0.modify(|_, w| w.uart1_rst().set_bit());
647                perip_rst_en0.modify(|_, w| w.uart1_rst().clear_bit());
648            }
649            #[cfg(all(uart2, esp32s3))]
650            Peripheral::Uart2 => {
651                perip_rst_en1.modify(|_, w| w.uart2_rst().set_bit());
652                perip_rst_en1.modify(|_, w| w.uart2_rst().clear_bit());
653            }
654            #[cfg(all(uart2, esp32))]
655            Peripheral::Uart2 => {
656                perip_rst_en0.modify(|_, w| w.uart2_rst().set_bit());
657                perip_rst_en0.modify(|_, w| w.uart2_rst().clear_bit());
658            }
659            #[cfg(all(rsa, esp32))]
660            Peripheral::Rsa => {
661                peri_rst_en.modify(|r, w| unsafe { w.bits(r.bits() | (1 << 2)) });
662                peri_rst_en.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << 2)) });
663            }
664            #[cfg(all(rsa, any(esp32c3, esp32s2, esp32s3)))]
665            Peripheral::Rsa => {
666                perip_rst_en1.modify(|_, w| w.crypto_rsa_rst().set_bit());
667                perip_rst_en1.modify(|_, w| w.crypto_rsa_rst().clear_bit());
668            }
669            #[cfg(hmac)]
670            Peripheral::Hmac => {
671                perip_rst_en1.modify(|_, w| w.crypto_hmac_rst().set_bit());
672                perip_rst_en1.modify(|_, w| w.crypto_hmac_rst().clear_bit());
673            }
674            #[cfg(ecc)]
675            Peripheral::Ecc => {
676                perip_rst_en1.modify(|_, w| w.crypto_ecc_rst().set_bit());
677                perip_rst_en1.modify(|_, w| w.crypto_ecc_rst().clear_bit());
678            }
679            #[cfg(lcd_cam)]
680            Peripheral::LcdCam => {
681                perip_rst_en1.modify(|_, w| w.lcd_cam_rst().set_bit());
682                perip_rst_en1.modify(|_, w| w.lcd_cam_rst().clear_bit());
683            }
684            #[cfg(systimer)]
685            Peripheral::Systimer => {
686                perip_rst_en0.modify(|_, w| w.systimer_rst().set_bit());
687                perip_rst_en0.modify(|_, w| w.systimer_rst().clear_bit());
688            }
689            #[cfg(all(tsens, esp32c6))]
690            Peripheral::Tsens => {
691                perip_rst_en0.modify(|_, w| w.tsens_rst().set_bit());
692                perip_rst_en0.modify(|_, w| w.tsens_rst().clear_bit());
693            }
694            #[cfg(all(tsens, esp32c3))]
695            Peripheral::Tsens => {
696                perip_rst_en1.modify(|_, w| w.tsens_rst().set_bit());
697                perip_rst_en1.modify(|_, w| w.tsens_rst().clear_bit());
698            }
699        });
700    }
701}
702
703#[cfg(any(esp32c6, esp32h2))]
704impl PeripheralClockControl {
705    fn enable_internal(peripheral: Peripheral, enable: bool, _cs: CriticalSection<'_>) {
706        debug!("Enable {:?} {}", peripheral, enable);
707        let system = SYSTEM::regs();
708
709        match peripheral {
710            #[cfg(spi2)]
711            Peripheral::Spi2 => {
712                system
713                    .spi2_conf()
714                    .modify(|_, w| w.spi2_clk_en().bit(enable));
715            }
716            #[cfg(i2c0)]
717            Peripheral::I2cExt0 => {
718                system
719                    .i2c0_conf()
720                    .modify(|_, w| w.i2c0_clk_en().bit(enable));
721            }
722            #[cfg(i2c1)]
723            Peripheral::I2cExt1 => {
724                system
725                    .i2c1_conf()
726                    .modify(|_, w| w.i2c1_clk_en().bit(enable));
727            }
728            #[cfg(rmt)]
729            Peripheral::Rmt => {
730                system.rmt_conf().modify(|_, w| w.rmt_clk_en().bit(enable));
731            }
732            #[cfg(ledc)]
733            Peripheral::Ledc => {
734                system
735                    .ledc_conf()
736                    .modify(|_, w| w.ledc_clk_en().bit(enable));
737            }
738            #[cfg(mcpwm0)]
739            Peripheral::Mcpwm0 => {
740                system.pwm_conf().modify(|_, w| w.pwm_clk_en().bit(enable));
741            }
742            #[cfg(mcpwm1)]
743            Peripheral::Mcpwm1 => {
744                system.pwm_conf.modify(|_, w| w.pwm_clk_en().bit(enable));
745            }
746            #[cfg(apb_saradc)]
747            Peripheral::ApbSarAdc => {
748                system
749                    .saradc_conf()
750                    .modify(|_, w| w.saradc_reg_clk_en().bit(enable));
751            }
752            #[cfg(gdma)]
753            Peripheral::Gdma => {
754                system
755                    .gdma_conf()
756                    .modify(|_, w| w.gdma_clk_en().bit(enable));
757            }
758            #[cfg(i2s0)]
759            Peripheral::I2s0 => {
760                system.i2s_conf().modify(|_, w| w.i2s_clk_en().bit(enable));
761            }
762            #[cfg(twai0)]
763            Peripheral::Twai0 => {
764                system
765                    .twai0_conf()
766                    .modify(|_, w| w.twai0_clk_en().bit(enable));
767
768                if enable {
769                    // use Xtal clk-src
770                    system.twai0_func_clk_conf().modify(|_, w| {
771                        w.twai0_func_clk_en()
772                            .set_bit()
773                            .twai0_func_clk_sel()
774                            .variant(false)
775                    });
776                }
777            }
778            #[cfg(twai1)]
779            Peripheral::Twai1 => {
780                system
781                    .twai1_conf()
782                    .modify(|_, w| w.twai1_clk_en().bit(enable));
783            }
784            #[cfg(aes)]
785            Peripheral::Aes => {
786                system.aes_conf().modify(|_, w| w.aes_clk_en().bit(enable));
787            }
788            #[cfg(pcnt)]
789            Peripheral::Pcnt => {
790                system
791                    .pcnt_conf()
792                    .modify(|_, w| w.pcnt_clk_en().bit(enable));
793            }
794            #[cfg(timg0)]
795            Peripheral::Timg0 => {
796                system
797                    .timergroup0_timer_clk_conf()
798                    .modify(|_, w| w.tg0_timer_clk_en().bit(enable));
799            }
800            #[cfg(timg1)]
801            Peripheral::Timg1 => {
802                system
803                    .timergroup1_timer_clk_conf()
804                    .modify(|_, w| w.tg1_timer_clk_en().bit(enable));
805            }
806            #[cfg(sha)]
807            Peripheral::Sha => {
808                system.sha_conf().modify(|_, w| w.sha_clk_en().bit(enable));
809            }
810            #[cfg(usb_device)]
811            Peripheral::UsbDevice => {
812                system
813                    .usb_device_conf()
814                    .modify(|_, w| w.usb_device_clk_en().bit(enable));
815            }
816            #[cfg(uart0)]
817            Peripheral::Uart0 => {
818                system.uart(0).conf().modify(|_, w| w.clk_en().bit(enable));
819            }
820            #[cfg(uart1)]
821            Peripheral::Uart1 => {
822                system.uart(1).conf().modify(|_, w| w.clk_en().bit(enable));
823            }
824            #[cfg(rsa)]
825            Peripheral::Rsa => {
826                system.rsa_conf().modify(|_, w| w.rsa_clk_en().bit(enable));
827                system
828                    .rsa_pd_ctrl()
829                    .modify(|_, w| w.rsa_mem_pd().clear_bit());
830            }
831            #[cfg(parl_io)]
832            Peripheral::ParlIo => {
833                system
834                    .parl_io_conf()
835                    .modify(|_, w| w.parl_clk_en().bit(enable));
836            }
837            #[cfg(hmac)]
838            Peripheral::Hmac => {
839                system
840                    .hmac_conf()
841                    .modify(|_, w| w.hmac_clk_en().bit(enable));
842            }
843            #[cfg(ecc)]
844            Peripheral::Ecc => {
845                system.ecc_conf().modify(|_, w| w.ecc_clk_en().bit(enable));
846            }
847            #[cfg(soc_etm)]
848            Peripheral::Etm => {
849                system.etm_conf().modify(|_, w| w.etm_clk_en().bit(enable));
850            }
851            #[cfg(trace0)]
852            Peripheral::Trace0 => {
853                system
854                    .trace_conf()
855                    .modify(|_, w| w.trace_clk_en().bit(enable));
856            }
857            #[cfg(systimer)]
858            Peripheral::Systimer => {
859                system
860                    .systimer_conf()
861                    .modify(|_, w| w.systimer_clk_en().bit(enable));
862            }
863            #[cfg(tsens)]
864            Peripheral::Tsens => {
865                system
866                    .tsens_clk_conf()
867                    .modify(|_, w| w.tsens_clk_en().bit(enable));
868
869                system
870                    .tsens_clk_conf()
871                    .modify(|_, w| w.tsens_clk_sel().bit(enable));
872            }
873        }
874    }
875
876    /// Resets the given peripheral
877    pub(crate) fn reset(peripheral: Peripheral) {
878        debug!("Reset {:?}", peripheral);
879
880        let system = SYSTEM::regs();
881
882        match peripheral {
883            #[cfg(spi2)]
884            Peripheral::Spi2 => {
885                system.spi2_conf().modify(|_, w| w.spi2_rst_en().set_bit());
886                system
887                    .spi2_conf()
888                    .modify(|_, w| w.spi2_rst_en().clear_bit());
889            }
890            #[cfg(i2c0)]
891            Peripheral::I2cExt0 => {
892                #[cfg(any(esp32c6, esp32h2))]
893                {
894                    system.i2c0_conf().modify(|_, w| w.i2c0_rst_en().set_bit());
895                    system
896                        .i2c0_conf()
897                        .modify(|_, w| w.i2c0_rst_en().clear_bit());
898                }
899            }
900            #[cfg(i2c1)]
901            Peripheral::I2cExt1 => {
902                #[cfg(esp32h2)]
903                {
904                    system.i2c1_conf().modify(|_, w| w.i2c1_rst_en().set_bit());
905                    system
906                        .i2c1_conf()
907                        .modify(|_, w| w.i2c1_rst_en().clear_bit());
908                }
909            }
910            #[cfg(rmt)]
911            Peripheral::Rmt => {
912                system.rmt_conf().modify(|_, w| w.rmt_rst_en().set_bit());
913                system.rmt_conf().modify(|_, w| w.rmt_rst_en().clear_bit());
914            }
915            #[cfg(ledc)]
916            Peripheral::Ledc => {
917                system.ledc_conf().modify(|_, w| w.ledc_rst_en().set_bit());
918                system
919                    .ledc_conf()
920                    .modify(|_, w| w.ledc_rst_en().clear_bit());
921            }
922            #[cfg(mcpwm0)]
923            Peripheral::Mcpwm0 => {
924                system.pwm_conf().modify(|_, w| w.pwm_rst_en().set_bit());
925                system.pwm_conf().modify(|_, w| w.pwm_rst_en().clear_bit());
926            }
927            #[cfg(mcpwm1)]
928            Peripheral::Mcpwm1 => {
929                system.pwm_conf.modify(|_, w| w.pwm_rst_en().set_bit());
930                system.pwm_conf.modify(|_, w| w.pwm_rst_en().clear_bit());
931            }
932            #[cfg(apb_saradc)]
933            Peripheral::ApbSarAdc => {
934                system
935                    .saradc_conf()
936                    .modify(|_, w| w.saradc_reg_rst_en().set_bit());
937                system
938                    .saradc_conf()
939                    .modify(|_, w| w.saradc_reg_rst_en().clear_bit());
940            }
941            #[cfg(gdma)]
942            Peripheral::Gdma => {
943                system.gdma_conf().modify(|_, w| w.gdma_rst_en().set_bit());
944                system
945                    .gdma_conf()
946                    .modify(|_, w| w.gdma_rst_en().clear_bit());
947            }
948            #[cfg(i2s0)]
949            Peripheral::I2s0 => {
950                system.i2s_conf().modify(|_, w| w.i2s_rst_en().set_bit());
951                system.i2s_conf().modify(|_, w| w.i2s_rst_en().clear_bit());
952            }
953            #[cfg(twai0)]
954            Peripheral::Twai0 => {
955                system
956                    .twai0_conf()
957                    .modify(|_, w| w.twai0_rst_en().set_bit());
958                system
959                    .twai0_conf()
960                    .modify(|_, w| w.twai0_rst_en().clear_bit());
961            }
962            #[cfg(twai1)]
963            Peripheral::Twai1 => {
964                system
965                    .twai1_conf()
966                    .modify(|_, w| w.twai1_rst_en().set_bit());
967                system
968                    .twai1_conf()
969                    .modify(|_, w| w.twai1_rst_en().clear_bit());
970            }
971            #[cfg(aes)]
972            Peripheral::Aes => {
973                system.aes_conf().modify(|_, w| w.aes_rst_en().set_bit());
974                system.aes_conf().modify(|_, w| w.aes_rst_en().clear_bit());
975            }
976            #[cfg(pcnt)]
977            Peripheral::Pcnt => {
978                system.pcnt_conf().modify(|_, w| w.pcnt_rst_en().set_bit());
979                system
980                    .pcnt_conf()
981                    .modify(|_, w| w.pcnt_rst_en().clear_bit());
982            }
983            #[cfg(timg0)]
984            Peripheral::Timg0 => {
985                // no reset?
986            }
987            #[cfg(timg1)]
988            Peripheral::Timg1 => {
989                // no reset?
990            }
991            #[cfg(sha)]
992            Peripheral::Sha => {
993                system.sha_conf().modify(|_, w| w.sha_rst_en().set_bit());
994                system.sha_conf().modify(|_, w| w.sha_rst_en().clear_bit());
995            }
996            #[cfg(usb_device)]
997            Peripheral::UsbDevice => {
998                system
999                    .usb_device_conf()
1000                    .modify(|_, w| w.usb_device_rst_en().set_bit());
1001                system
1002                    .usb_device_conf()
1003                    .modify(|_, w| w.usb_device_rst_en().clear_bit());
1004            }
1005            #[cfg(uart0)]
1006            Peripheral::Uart0 => {
1007                system.uart(0).conf().modify(|_, w| w.rst_en().set_bit());
1008                system.uart(0).conf().modify(|_, w| w.rst_en().clear_bit());
1009            }
1010            #[cfg(uart1)]
1011            Peripheral::Uart1 => {
1012                system.uart(1).conf().modify(|_, w| w.rst_en().set_bit());
1013                system.uart(1).conf().modify(|_, w| w.rst_en().clear_bit());
1014            }
1015            #[cfg(rsa)]
1016            Peripheral::Rsa => {
1017                system.rsa_conf().modify(|_, w| w.rsa_rst_en().set_bit());
1018                system.rsa_conf().modify(|_, w| w.rsa_rst_en().clear_bit());
1019            }
1020            #[cfg(parl_io)]
1021            Peripheral::ParlIo => {
1022                system
1023                    .parl_io_conf()
1024                    .modify(|_, w| w.parl_rst_en().set_bit());
1025                system
1026                    .parl_io_conf()
1027                    .modify(|_, w| w.parl_rst_en().clear_bit());
1028            }
1029            #[cfg(hmac)]
1030            Peripheral::Hmac => {
1031                system.hmac_conf().modify(|_, w| w.hmac_rst_en().set_bit());
1032                system
1033                    .hmac_conf()
1034                    .modify(|_, w| w.hmac_rst_en().clear_bit());
1035            }
1036            #[cfg(ecc)]
1037            Peripheral::Ecc => {
1038                system.ecc_conf().modify(|_, w| w.ecc_rst_en().set_bit());
1039                system.ecc_conf().modify(|_, w| w.ecc_rst_en().clear_bit());
1040            }
1041            #[cfg(soc_etm)]
1042            Peripheral::Etm => {
1043                system.etm_conf().modify(|_, w| w.etm_rst_en().set_bit());
1044                system.etm_conf().modify(|_, w| w.etm_rst_en().clear_bit());
1045            }
1046            #[cfg(trace0)]
1047            Peripheral::Trace0 => {
1048                system
1049                    .trace_conf()
1050                    .modify(|_, w| w.trace_rst_en().set_bit());
1051                system
1052                    .trace_conf()
1053                    .modify(|_, w| w.trace_rst_en().clear_bit());
1054            }
1055            #[cfg(systimer)]
1056            Peripheral::Systimer => {
1057                system
1058                    .systimer_conf()
1059                    .modify(|_, w| w.systimer_rst_en().set_bit());
1060                system
1061                    .systimer_conf()
1062                    .modify(|_, w| w.systimer_rst_en().clear_bit());
1063            }
1064            #[cfg(tsens)]
1065            Peripheral::Tsens => {
1066                system
1067                    .tsens_clk_conf()
1068                    .modify(|_, w| w.tsens_rst_en().set_bit());
1069                system
1070                    .tsens_clk_conf()
1071                    .modify(|_, w| w.tsens_rst_en().clear_bit());
1072            }
1073        }
1074    }
1075}
1076
1077impl PeripheralClockControl {
1078    /// Enables the given peripheral.
1079    ///
1080    /// This keeps track of enabling a peripheral - i.e. a peripheral
1081    /// is only enabled with the first call attempt to enable it.
1082    ///
1083    /// Returns `true` if it actually enabled the peripheral.
1084    pub(crate) fn enable(peripheral: Peripheral) -> bool {
1085        Self::enable_forced(peripheral, true, false)
1086    }
1087
1088    /// Enables the given peripheral.
1089    ///
1090    /// This keeps track of enabling a peripheral - i.e. a peripheral
1091    /// is only enabled with the first call attempt to enable it.
1092    ///
1093    /// Returns `true` if it actually enabled the peripheral.
1094    pub(crate) fn enable_with_cs(peripheral: Peripheral, cs: CriticalSection<'_>) -> bool {
1095        Self::enable_forced_with_cs(peripheral, true, false, cs)
1096    }
1097
1098    /// Disables the given peripheral.
1099    ///
1100    /// This keeps track of disabling a peripheral - i.e. it only
1101    /// gets disabled when the number of enable/disable attempts is balanced.
1102    ///
1103    /// Returns `true` if it actually disabled the peripheral.
1104    ///
1105    /// Before disabling a peripheral it will also get reset
1106    pub(crate) fn disable(peripheral: Peripheral) -> bool {
1107        Self::enable_forced(peripheral, false, false)
1108    }
1109
1110    pub(crate) fn enable_forced(peripheral: Peripheral, enable: bool, force: bool) -> bool {
1111        critical_section::with(|cs| Self::enable_forced_with_cs(peripheral, enable, force, cs))
1112    }
1113
1114    pub(crate) fn enable_forced_with_cs(
1115        peripheral: Peripheral,
1116        enable: bool,
1117        force: bool,
1118        cs: CriticalSection<'_>,
1119    ) -> bool {
1120        let mut ref_counts = PERIPHERAL_REF_COUNT.borrow_ref_mut(cs);
1121        let ref_count = &mut ref_counts[peripheral as usize];
1122        if !force {
1123            if enable {
1124                let prev = *ref_count;
1125                *ref_count += 1;
1126                trace!("Enable {:?} {} -> {}", peripheral, prev, *ref_count);
1127                if prev > 0 {
1128                    return false;
1129                }
1130            } else {
1131                let prev = *ref_count;
1132                *ref_count -= 1;
1133                trace!("Disable {:?} {} -> {}", peripheral, prev, *ref_count);
1134                if prev > 1 {
1135                    return false;
1136                }
1137                assert!(prev != 0);
1138            };
1139        } else if !enable {
1140            assert!(*ref_count == 0);
1141        }
1142
1143        if !enable {
1144            Self::reset(peripheral);
1145        }
1146
1147        Self::enable_internal(peripheral, enable, cs);
1148
1149        true
1150    }
1151}
1152
1153#[cfg(any(esp32, esp32s3))]
1154#[allow(unused_imports)]
1155pub use crate::soc::cpu_control::*;
1156
1157/// Available CPU cores
1158///
1159/// The actual number of available cores depends on the target.
1160#[derive(Debug, Copy, Clone, PartialEq, Eq, strum::FromRepr)]
1161#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1162#[repr(C)]
1163pub enum Cpu {
1164    /// The first core
1165    ProCpu = 0,
1166    /// The second core
1167    #[cfg(multi_core)]
1168    AppCpu = 1,
1169}
1170
1171impl Cpu {
1172    /// The number of available cores.
1173    pub const COUNT: usize = 1 + cfg!(multi_core) as usize;
1174
1175    /// Returns the core the application is currently executing on
1176    #[inline(always)]
1177    pub fn current() -> Self {
1178        // This works for both RISCV and Xtensa because both
1179        // get_raw_core functions return zero, _or_ something
1180        // greater than zero; 1 in the case of RISCV and 0x2000
1181        // in the case of Xtensa.
1182        match raw_core() {
1183            0 => Cpu::ProCpu,
1184            #[cfg(all(multi_core, riscv))]
1185            1 => Cpu::AppCpu,
1186            #[cfg(all(multi_core, xtensa))]
1187            0x2000 => Cpu::AppCpu,
1188            _ => unreachable!(),
1189        }
1190    }
1191
1192    /// Returns an iterator over the "other" cores.
1193    #[inline(always)]
1194    pub(crate) fn other() -> impl Iterator<Item = Self> {
1195        cfg_if::cfg_if! {
1196            if #[cfg(multi_core)] {
1197                match Self::current() {
1198                    Cpu::ProCpu => [Cpu::AppCpu].into_iter(),
1199                    Cpu::AppCpu => [Cpu::ProCpu].into_iter(),
1200                }
1201            } else {
1202                [].into_iter()
1203            }
1204        }
1205    }
1206
1207    /// Returns an iterator over all cores.
1208    #[inline(always)]
1209    pub(crate) fn all() -> impl Iterator<Item = Self> {
1210        cfg_if::cfg_if! {
1211            if #[cfg(multi_core)] {
1212                [Cpu::ProCpu, Cpu::AppCpu].into_iter()
1213            } else {
1214                [Cpu::ProCpu].into_iter()
1215            }
1216        }
1217    }
1218}
1219
1220/// Returns the raw value of the mhartid register.
1221///
1222/// On RISC-V, this is the hardware thread ID.
1223///
1224/// On Xtensa, this returns the result of reading the PRID register logically
1225/// ANDed with 0x2000, the 13th bit in the register. Espressif Xtensa chips use
1226/// this bit to determine the core id.
1227#[inline(always)]
1228pub(crate) fn raw_core() -> usize {
1229    // This method must never return UNUSED_THREAD_ID_VALUE
1230    cfg_if::cfg_if! {
1231        if #[cfg(all(multi_core, riscv))] {
1232            riscv::register::mhartid::read()
1233        } else if #[cfg(all(multi_core, xtensa))] {
1234            (xtensa_lx::get_processor_id() & 0x2000) as usize
1235        } else {
1236            0
1237        }
1238    }
1239}
1240
1241use crate::rtc_cntl::SocResetReason;
1242
1243/// Source of the wakeup event
1244#[derive(Debug, Copy, Clone)]
1245#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1246#[instability::unstable]
1247pub enum SleepSource {
1248    /// In case of deep sleep, reset was not caused by exit from deep sleep
1249    Undefined = 0,
1250    /// Not a wakeup cause, used to disable all wakeup sources with
1251    /// esp_sleep_disable_wakeup_source
1252    All,
1253    /// Wakeup caused by external signal using RTC_IO
1254    Ext0,
1255    /// Wakeup caused by external signal using RTC_CNTL
1256    Ext1,
1257    /// Wakeup caused by timer
1258    Timer,
1259    /// Wakeup caused by touchpad
1260    TouchPad,
1261    /// Wakeup caused by ULP program
1262    Ulp,
1263    /// Wakeup caused by GPIO (light sleep only on ESP32, S2 and S3)
1264    Gpio,
1265    /// Wakeup caused by UART (light sleep only)
1266    Uart,
1267    /// Wakeup caused by WIFI (light sleep only)
1268    Wifi,
1269    /// Wakeup caused by COCPU int
1270    Cocpu,
1271    /// Wakeup caused by COCPU crash
1272    CocpuTrapTrig,
1273    /// Wakeup caused by BT (light sleep only)
1274    BT,
1275}
1276
1277/// Performs a software reset on the chip.
1278#[inline]
1279pub fn software_reset() -> ! {
1280    crate::rom::software_reset()
1281}
1282
1283/// Resets the given CPU, leaving peripherals unchanged.
1284#[instability::unstable]
1285#[inline]
1286pub fn software_reset_cpu(cpu: Cpu) {
1287    crate::rom::software_reset_cpu(cpu as u32)
1288}
1289
1290/// Retrieves the reason for the last reset as a SocResetReason enum value.
1291/// Returns `None` if the reset reason cannot be determined.
1292#[instability::unstable]
1293#[inline]
1294pub fn reset_reason() -> Option<SocResetReason> {
1295    crate::rtc_cntl::reset_reason(Cpu::current())
1296}
1297
1298/// Retrieves the cause of the last wakeup event as a SleepSource enum value.
1299#[instability::unstable]
1300#[inline]
1301pub fn wakeup_cause() -> SleepSource {
1302    crate::rtc_cntl::wakeup_cause()
1303}