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