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