Skip to main content

esp_idf_hal/
peripherals.rs

1use crate::adc;
2use crate::can;
3use crate::gpio;
4use crate::i2c;
5#[cfg(esp_idf_soc_i2s_supported)]
6use crate::i2s;
7#[cfg(all(esp32p4, esp_idf_comp_esp_lcd_enabled, feature = "alloc"))]
8use crate::lcd;
9#[cfg(esp32p4)]
10use crate::ldo;
11use crate::ledc;
12#[cfg(any(all(esp32, esp_idf_eth_use_esp32_emac), esp_idf_eth_use_openeth))]
13use crate::mac;
14#[cfg(any(not(esp32p4), esp_idf_comp_espressif__esp_wifi_remote_enabled))]
15use crate::modem;
16#[cfg(not(esp_idf_version_at_least_6_0_0))]
17#[cfg(all(
18    any(esp32, esp32s2, esp32s3, esp32c5, esp32c6, esp32c61),
19    feature = "pcnt-legacy"
20))]
21use crate::pcnt;
22#[cfg(feature = "rmt-legacy")]
23use crate::rmt_legacy;
24#[cfg(esp_idf_soc_sdmmc_host_supported)]
25use crate::sd;
26use crate::spi;
27#[cfg(any(
28    all(
29        not(any(esp_idf_version_major = "4", esp_idf_version = "5.0")),
30        esp_idf_esp_task_wdt_en
31    ),
32    any(esp_idf_version_major = "4", esp_idf_version = "5.0")
33))]
34use crate::task::watchdog;
35#[cfg(all(esp_idf_soc_temp_sensor_supported, esp_idf_version_major = "5"))]
36use crate::temp_sensor;
37#[cfg(all(feature = "timer-legacy", not(esp_idf_version_at_least_6_0_0)))]
38use crate::timer;
39use crate::uart;
40#[cfg(all(
41    any(esp32, esp32s2, esp32s3, esp32c5, esp32c6, esp32p4),
42    esp_idf_comp_ulp_enabled
43))]
44use crate::ulp;
45#[cfg(esp_idf_soc_usb_serial_jtag_supported)]
46use crate::usb_serial;
47
48pub struct Peripherals {
49    pub pins: gpio::Pins,
50    pub uart0: uart::UART0<'static>,
51    pub uart1: uart::UART1<'static>,
52    #[cfg(any(esp32, esp32s3))]
53    pub uart2: uart::UART2<'static>,
54    pub i2c0: i2c::I2C0<'static>,
55    #[cfg(not(any(esp32c3, esp32c2, esp32c5, esp32c6, esp32c61)))]
56    pub i2c1: i2c::I2C1<'static>,
57    #[cfg(esp_idf_soc_i2s_supported)]
58    pub i2s0: i2s::I2S0<'static>,
59    #[cfg(all(esp_idf_soc_i2s_supported, any(esp32, esp32s3)))]
60    pub i2s1: i2s::I2S1<'static>,
61    pub spi1: spi::SPI1<'static>,
62    pub spi2: spi::SPI2<'static>,
63    #[cfg(any(esp32, esp32s2, esp32s3))]
64    pub spi3: spi::SPI3<'static>,
65    pub adc1: adc::ADC1<'static>,
66    #[cfg(any(esp32, esp32s2, esp32s3, esp32c3))]
67    pub adc2: adc::ADC2<'static>,
68    // TODO: Check the pulse counter story for c2, h2, c5, and p4
69    #[cfg(not(esp_idf_version_at_least_6_0_0))]
70    #[cfg(all(
71        any(esp32, esp32s2, esp32s3, esp32c5, esp32c6, esp32c61),
72        feature = "pcnt-legacy"
73    ))]
74    pub pcnt0: pcnt::PCNT0<'static>,
75    #[cfg(not(esp_idf_version_at_least_6_0_0))]
76    #[cfg(all(
77        any(esp32, esp32s2, esp32s3, esp32c5, esp32c6, esp32c61),
78        feature = "pcnt-legacy"
79    ))]
80    pub pcnt1: pcnt::PCNT1<'static>,
81    #[cfg(not(esp_idf_version_at_least_6_0_0))]
82    #[cfg(all(
83        any(esp32, esp32s2, esp32s3, esp32c5, esp32c6, esp32c61),
84        feature = "pcnt-legacy"
85    ))]
86    pub pcnt2: pcnt::PCNT2<'static>,
87    #[cfg(not(esp_idf_version_at_least_6_0_0))]
88    #[cfg(all(
89        any(esp32, esp32s2, esp32s3, esp32c5, esp32c6, esp32c61),
90        feature = "pcnt-legacy"
91    ))]
92    pub pcnt3: pcnt::PCNT3<'static>,
93    #[cfg(not(esp_idf_version_at_least_6_0_0))]
94    #[cfg(all(esp32, feature = "pcnt-legacy"))]
95    pub pcnt4: pcnt::PCNT4<'static>,
96    #[cfg(not(esp_idf_version_at_least_6_0_0))]
97    #[cfg(all(esp32, feature = "pcnt-legacy"))]
98    pub pcnt5: pcnt::PCNT5<'static>,
99    #[cfg(not(esp_idf_version_at_least_6_0_0))]
100    #[cfg(all(esp32, feature = "pcnt-legacy"))]
101    pub pcnt6: pcnt::PCNT6<'static>,
102    #[cfg(not(esp_idf_version_at_least_6_0_0))]
103    #[cfg(all(esp32, feature = "pcnt-legacy"))]
104    pub pcnt7: pcnt::PCNT7<'static>,
105    pub can: can::CAN<'static>,
106    pub ledc: ledc::LEDC,
107    #[cfg(esp32p4)]
108    pub ldo1: ldo::LDO1<'static, ldo::Fixed>,
109    #[cfg(esp32p4)]
110    pub ldo2: ldo::LDO2<'static, ldo::Fixed>,
111    #[cfg(esp32p4)]
112    pub ldo3: ldo::LDO3<'static, ldo::Adjustable>,
113    #[cfg(esp32p4)]
114    pub ldo4: ldo::LDO4<'static, ldo::Adjustable>,
115    #[cfg(all(esp32p4, esp_idf_comp_esp_lcd_enabled, feature = "alloc"))]
116    pub dsi: lcd::DSI<'static>,
117    #[cfg(esp32)]
118    pub hledc: ledc::HLEDC,
119    #[cfg(feature = "rmt-legacy")]
120    pub rmt: rmt_legacy::RMT,
121    #[cfg(all(
122        any(esp32, esp32s2, esp32s3, esp32c5, esp32c6, esp32p4),
123        esp_idf_comp_ulp_enabled
124    ))]
125    pub ulp: ulp::ULP<'static>,
126    #[cfg(any(all(esp32, esp_idf_eth_use_esp32_emac), esp_idf_eth_use_openeth))]
127    pub mac: mac::MAC<'static>,
128    #[cfg(any(not(esp32p4), esp_idf_comp_espressif__esp_wifi_remote_enabled))]
129    pub modem: modem::Modem<'static>,
130    #[cfg(esp_idf_soc_sdmmc_host_supported)]
131    pub sdmmc0: sd::mmc::SDMMC0<'static>,
132    #[cfg(esp_idf_soc_sdmmc_host_supported)]
133    pub sdmmc1: sd::mmc::SDMMC1<'static>,
134    #[cfg(all(esp_idf_soc_temp_sensor_supported, esp_idf_version_major = "5"))]
135    pub temp_sensor: temp_sensor::TempSensor<'static>,
136    // TODO: Check the timer story for c2, h2, c5, c6, and p4
137    #[cfg(all(feature = "timer-legacy", not(esp_idf_version_at_least_6_0_0)))]
138    pub timer00: timer::TIMER00<'static>,
139    #[cfg(all(feature = "timer-legacy", not(esp_idf_version_at_least_6_0_0)))]
140    #[cfg(any(esp32, esp32s2, esp32s3))]
141    pub timer01: timer::TIMER01<'static>,
142    #[cfg(all(feature = "timer-legacy", not(esp_idf_version_at_least_6_0_0)))]
143    #[cfg(not(esp32c2))]
144    pub timer10: timer::TIMER10<'static>,
145    #[cfg(all(feature = "timer-legacy", not(esp_idf_version_at_least_6_0_0)))]
146    #[cfg(any(esp32, esp32s2, esp32s3))]
147    pub timer11: timer::TIMER11<'static>,
148    #[cfg(any(
149        all(
150            not(any(esp_idf_version_major = "4", esp_idf_version = "5.0")),
151            esp_idf_esp_task_wdt_en
152        ),
153        any(esp_idf_version_major = "4", esp_idf_version = "5.0")
154    ))]
155    pub twdt: watchdog::TWDT<'static>,
156    #[cfg(esp_idf_soc_usb_serial_jtag_supported)]
157    pub usb_serial: usb_serial::USB_SERIAL<'static>,
158}
159
160static TAKEN: core::sync::atomic::AtomicBool = core::sync::atomic::AtomicBool::new(false);
161static TAKEN_CS: crate::task::CriticalSection = crate::task::CriticalSection::new();
162
163impl Peripherals {
164    pub fn take() -> Result<Self, crate::sys::EspError> {
165        if TAKEN.load(core::sync::atomic::Ordering::SeqCst) {
166            Err(crate::sys::EspError::from_infallible::<
167                { crate::sys::ESP_ERR_INVALID_STATE },
168            >())
169        } else {
170            let _guard = TAKEN_CS.enter();
171
172            if !TAKEN.load(core::sync::atomic::Ordering::SeqCst) {
173                TAKEN.store(true, core::sync::atomic::Ordering::SeqCst);
174
175                Ok(unsafe { Peripherals::steal() })
176            } else {
177                Err(crate::sys::EspError::from_infallible::<
178                    { crate::sys::ESP_ERR_INVALID_STATE },
179                >())
180            }
181        }
182    }
183
184    /// # Safety
185    ///
186    /// Care should be taken not to instantiate the Peripherals structure, if it is already instantiated and used elsewhere
187    pub unsafe fn steal() -> Self {
188        Self {
189            pins: gpio::Pins::new(),
190            uart0: uart::UART0::steal(),
191            uart1: uart::UART1::steal(),
192            #[cfg(any(esp32, esp32s3))]
193            uart2: uart::UART2::steal(),
194            i2c0: i2c::I2C0::steal(),
195            #[cfg(not(any(esp32c3, esp32c2, esp32c5, esp32c6, esp32c61)))]
196            i2c1: i2c::I2C1::steal(),
197            #[cfg(esp_idf_soc_i2s_supported)]
198            i2s0: i2s::I2S0::steal(),
199            #[cfg(all(esp_idf_soc_i2s_supported, any(esp32, esp32s3)))]
200            i2s1: i2s::I2S1::steal(),
201            spi1: spi::SPI1::steal(),
202            spi2: spi::SPI2::steal(),
203            #[cfg(any(esp32, esp32s2, esp32s3))]
204            spi3: spi::SPI3::steal(),
205            adc1: adc::ADC1::steal(),
206            #[cfg(any(esp32, esp32s2, esp32s3, esp32c3))]
207            adc2: adc::ADC2::steal(),
208            #[cfg(not(esp_idf_version_at_least_6_0_0))]
209            #[cfg(all(
210                any(esp32, esp32s2, esp32s3, esp32c5, esp32c6, esp32c61),
211                feature = "pcnt-legacy"
212            ))]
213            pcnt0: pcnt::PCNT0::steal(),
214            #[cfg(not(esp_idf_version_at_least_6_0_0))]
215            #[cfg(all(
216                any(esp32, esp32s2, esp32s3, esp32c5, esp32c6, esp32c61),
217                feature = "pcnt-legacy"
218            ))]
219            pcnt1: pcnt::PCNT1::steal(),
220            #[cfg(not(esp_idf_version_at_least_6_0_0))]
221            #[cfg(all(
222                any(esp32, esp32s2, esp32s3, esp32c5, esp32c6, esp32c61),
223                feature = "pcnt-legacy"
224            ))]
225            pcnt2: pcnt::PCNT2::steal(),
226            #[cfg(not(esp_idf_version_at_least_6_0_0))]
227            #[cfg(all(
228                any(esp32, esp32s2, esp32s3, esp32c5, esp32c6, esp32c61),
229                feature = "pcnt-legacy"
230            ))]
231            pcnt3: pcnt::PCNT3::steal(),
232            #[cfg(not(esp_idf_version_at_least_6_0_0))]
233            #[cfg(all(esp32, feature = "pcnt-legacy"))]
234            pcnt4: pcnt::PCNT4::steal(),
235            #[cfg(not(esp_idf_version_at_least_6_0_0))]
236            #[cfg(all(esp32, feature = "pcnt-legacy"))]
237            pcnt5: pcnt::PCNT5::steal(),
238            #[cfg(not(esp_idf_version_at_least_6_0_0))]
239            #[cfg(all(esp32, feature = "pcnt-legacy"))]
240            pcnt6: pcnt::PCNT6::steal(),
241            #[cfg(not(esp_idf_version_at_least_6_0_0))]
242            #[cfg(all(esp32, feature = "pcnt-legacy"))]
243            pcnt7: pcnt::PCNT7::steal(),
244            can: can::CAN::steal(),
245            ledc: ledc::LEDC::new(),
246            #[cfg(esp32p4)]
247            ldo1: ldo::LDO1::steal(),
248            #[cfg(esp32p4)]
249            ldo2: ldo::LDO2::steal(),
250            #[cfg(esp32p4)]
251            ldo3: ldo::LDO3::steal(),
252            #[cfg(esp32p4)]
253            ldo4: ldo::LDO4::steal(),
254            #[cfg(all(esp32p4, esp_idf_comp_esp_lcd_enabled, feature = "alloc"))]
255            dsi: lcd::DSI::steal(),
256            #[cfg(esp32)]
257            hledc: ledc::HLEDC::new(),
258            #[cfg(feature = "rmt-legacy")]
259            rmt: rmt_legacy::RMT::new(),
260            #[cfg(all(
261                any(esp32, esp32s2, esp32s3, esp32c5, esp32c6, esp32p4),
262                esp_idf_comp_ulp_enabled
263            ))]
264            ulp: ulp::ULP::steal(),
265            #[cfg(any(all(esp32, esp_idf_eth_use_esp32_emac), esp_idf_eth_use_openeth))]
266            mac: mac::MAC::steal(),
267            #[cfg(any(not(esp32p4), esp_idf_comp_espressif__esp_wifi_remote_enabled))]
268            modem: modem::Modem::steal(),
269            #[cfg(esp_idf_soc_sdmmc_host_supported)]
270            sdmmc0: sd::mmc::SDMMC0::steal(),
271            #[cfg(esp_idf_soc_sdmmc_host_supported)]
272            sdmmc1: sd::mmc::SDMMC1::steal(),
273            #[cfg(all(esp_idf_soc_temp_sensor_supported, esp_idf_version_major = "5"))]
274            temp_sensor: temp_sensor::TempSensor::steal(),
275            #[cfg(all(feature = "timer-legacy", not(esp_idf_version_at_least_6_0_0)))]
276            timer00: timer::TIMER00::steal(),
277            #[cfg(all(feature = "timer-legacy", not(esp_idf_version_at_least_6_0_0)))]
278            #[cfg(any(esp32, esp32s2, esp32s3))]
279            timer01: timer::TIMER01::steal(),
280            #[cfg(all(feature = "timer-legacy", not(esp_idf_version_at_least_6_0_0)))]
281            #[cfg(not(esp32c2))]
282            timer10: timer::TIMER10::steal(),
283            #[cfg(all(feature = "timer-legacy", not(esp_idf_version_at_least_6_0_0)))]
284            #[cfg(any(esp32, esp32s2, esp32s3))]
285            timer11: timer::TIMER11::steal(),
286            #[cfg(any(
287                all(
288                    not(any(esp_idf_version_major = "4", esp_idf_version = "5.0")),
289                    esp_idf_esp_task_wdt_en
290                ),
291                any(esp_idf_version_major = "4", esp_idf_version = "5.0")
292            ))]
293            twdt: watchdog::TWDT::steal(),
294            #[cfg(esp_idf_soc_usb_serial_jtag_supported)]
295            usb_serial: usb_serial::USB_SERIAL::steal(),
296        }
297    }
298}