Skip to main content

esp_idf_hal/
lib.rs

1#![no_std]
2#![allow(async_fn_in_trait)]
3#![allow(unknown_lints)]
4#![allow(renamed_and_removed_lints)]
5#![allow(clippy::unused_unit)] // enumset
6#![allow(unexpected_cfgs)]
7#![warn(clippy::large_futures)]
8#![cfg_attr(feature = "nightly", feature(doc_cfg))]
9#![cfg_attr(target_arch = "xtensa", feature(asm_experimental_arch))]
10
11#[cfg(not(esp_idf_comp_driver_enabled))]
12compile_error!("esp-idf-hal requires the `driver` ESP-IDF component to be enabled");
13
14// mutually exclusive features assert
15#[cfg(all(feature = "rmt-legacy", esp_idf_comp_espressif__onewire_bus_enabled))]
16compile_error!("the onewire component cannot be used with the legacy rmt peripheral");
17
18#[cfg(feature = "std")]
19#[allow(unused_imports)]
20#[macro_use]
21extern crate std;
22
23#[cfg(feature = "alloc")]
24#[allow(unused_imports)]
25#[macro_use]
26extern crate alloc;
27
28pub mod adc;
29pub mod can;
30pub mod cpu;
31pub mod delay;
32pub mod gpio;
33pub mod i2c;
34#[cfg_attr(
35    feature = "nightly",
36    doc(cfg(all(esp_idf_soc_i2s_supported, esp_idf_comp_driver_enabled)))
37)]
38pub mod i2s;
39pub mod interrupt;
40pub mod io;
41#[cfg(esp32p4)]
42#[cfg_attr(feature = "nightly", doc(cfg(esp32p4)))]
43pub mod lcd;
44#[cfg(esp32p4)]
45#[cfg_attr(feature = "nightly", doc(cfg(esp32p4)))]
46pub mod ldo;
47pub mod ledc;
48#[cfg(any(all(esp32, esp_idf_eth_use_esp32_emac), esp_idf_eth_use_openeth))]
49pub mod mac;
50#[cfg(any(not(esp32p4), esp_idf_comp_espressif__esp_wifi_remote_enabled))]
51pub mod modem;
52#[cfg(all(
53    esp_idf_soc_rmt_supported,
54    not(feature = "rmt-legacy"),
55    esp_idf_comp_espressif__onewire_bus_enabled,
56))]
57pub mod onewire;
58
59#[cfg(all(not(feature = "pcnt-legacy"), esp_idf_soc_pcnt_supported))]
60#[cfg_attr(feature = "nightly", doc(cfg(esp_idf_soc_pcnt_supported)))]
61pub mod pcnt;
62
63#[cfg(not(esp_idf_version_at_least_6_0_0))]
64#[cfg(all(
65    any(esp32, esp32s2, esp32s3, esp32c5, esp32c6, esp32c61),
66    feature = "pcnt-legacy"
67))]
68#[cfg_attr(
69    all(
70        not(esp_idf_version_at_least_6_0_0),
71        any(esp32, esp32s2, esp32s3, esp32c5, esp32c6, esp32c61),
72        feature = "pcnt-legacy"
73    ),
74    deprecated(
75        since = "0.46.0",
76        note = "use the new `pcnt` api by disabling the `pcnt-legacy` feature"
77    )
78)]
79mod pcnt_legacy;
80
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))]
86pub mod pcnt {
87    pub use crate::pcnt_legacy::*;
88}
89
90pub mod peripherals;
91pub mod reset;
92
93#[cfg(all(
94    esp_idf_soc_rmt_supported,
95    not(feature = "rmt-legacy"),
96    feature = "alloc"
97))]
98#[cfg_attr(
99    feature = "nightly",
100    doc(cfg(all(
101        esp_idf_soc_rmt_supported,
102        not(feature = "rmt-legacy"),
103        feature = "alloc"
104    )))
105)]
106pub mod rmt;
107#[cfg(feature = "rmt-legacy")]
108#[cfg_attr(
109    feature = "rmt-legacy",
110    deprecated(
111        since = "0.46.0",
112        note = "use the new `rmt` api by disabling the `rmt-legacy` feature"
113    )
114)]
115mod rmt_legacy;
116#[cfg(feature = "rmt-legacy")]
117pub mod rmt {
118    pub use crate::rmt_legacy::*;
119}
120pub mod rom;
121pub mod sd;
122pub mod sleep;
123pub mod spi;
124pub mod sys;
125pub mod task;
126#[cfg(all(esp_idf_soc_temp_sensor_supported, esp_idf_version_major = "5"))]
127pub mod temp_sensor;
128
129#[cfg(all(
130    esp_idf_soc_gptimer_supported,
131    not(feature = "timer-legacy"),
132    feature = "alloc"
133))]
134#[cfg_attr(
135    feature = "nightly",
136    doc(cfg(all(
137        esp_idf_soc_gptimer_supported,
138        not(feature = "timer-legacy"),
139        feature = "alloc"
140    )))
141)]
142pub mod timer;
143#[cfg(all(feature = "timer-legacy", not(esp_idf_version_at_least_6_0_0)))]
144#[cfg_attr(
145    all(feature = "timer-legacy", not(esp_idf_version_at_least_6_0_0)),
146    deprecated(
147        since = "0.46.0",
148        note = "use the new `timer` api by disabling the `timer-legacy` feature"
149    )
150)]
151mod timer_legacy;
152#[cfg(all(feature = "timer-legacy", not(esp_idf_version_at_least_6_0_0)))]
153pub mod timer {
154    pub use crate::timer_legacy::*;
155}
156
157pub mod uart;
158#[cfg(all(
159    any(esp32, esp32s2, esp32s3, esp32c5, esp32c6, esp32p4),
160    esp_idf_comp_ulp_enabled
161))]
162pub mod ulp;
163pub mod units;
164#[cfg(esp_idf_soc_usb_serial_jtag_supported)]
165pub mod usb_serial;
166
167// This is used to create `embedded_hal` compatible error structs
168// that preserve original `EspError`.
169//
170// Example:
171// embedded_hal_error!(I2cError, embedded_hal::i2c::Error, embedded_hal::i2c::ErrorKind)
172#[allow(unused_macros)]
173macro_rules! embedded_hal_error {
174    ($error:ident, $errortrait:ty, $kind:ty) => {
175        #[derive(Debug, Copy, Clone, Eq, PartialEq)]
176        pub struct $error {
177            kind: $kind,
178            cause: esp_idf_sys::EspError,
179        }
180
181        impl $error {
182            pub fn new(kind: $kind, cause: esp_idf_sys::EspError) -> Self {
183                Self { kind, cause }
184            }
185            pub fn other(cause: esp_idf_sys::EspError) -> Self {
186                Self::new(<$kind>::Other, cause)
187            }
188            pub fn cause(&self) -> esp_idf_sys::EspError {
189                self.cause
190            }
191        }
192        impl From<esp_idf_sys::EspError> for $error {
193            fn from(e: esp_idf_sys::EspError) -> Self {
194                Self::other(e)
195            }
196        }
197
198        impl $errortrait for $error {
199            fn kind(&self) -> $kind {
200                self.kind
201            }
202        }
203
204        impl core::fmt::Display for $error {
205            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
206                write!(
207                    f,
208                    "{} {{ kind: {}, cause: {} }}",
209                    stringify!($error),
210                    self.kind,
211                    self.cause()
212                )
213            }
214        }
215
216        #[cfg(feature = "std")]
217        impl std::error::Error for $error {}
218    };
219}
220
221#[allow(unused_macros)]
222macro_rules! impl_peripheral {
223    ($name:ident) => {
224        pub struct $name<'a>(::core::marker::PhantomData<&'a mut ()>);
225
226        impl $name<'_> {
227            /// Unsafely create an instance of this peripheral out of thin air.
228            ///
229            /// # Safety
230            ///
231            /// You must ensure that you're only using one instance of this type at a time.
232            #[inline(always)]
233            pub unsafe fn steal() -> Self {
234                Self(::core::marker::PhantomData)
235            }
236
237            /// Creates a new peripheral reference with a shorter lifetime.
238            ///
239            /// Use this method if you would like to keep working with the peripheral after
240            /// you dropped the driver that consumes this.
241            ///
242            /// # Safety
243            ///
244            /// You must ensure that you are not using reborrowed peripherals in drivers which are
245            /// forgotten via `core::mem::forget`.
246            #[inline]
247            #[allow(dead_code)]
248            pub unsafe fn reborrow(&mut self) -> $name<'_> {
249                Self(::core::marker::PhantomData)
250            }
251        }
252
253        unsafe impl Send for $name<'_> {}
254    };
255}
256
257#[allow(unused_imports)]
258pub(crate) use embedded_hal_error;
259#[allow(unused_imports)]
260pub(crate) use impl_peripheral;
261
262#[cfg(test)]
263fn main() {}