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