1#![cfg_attr(
2 all(docsrs, not(not_really_docsrs)),
3 doc = "<div style='padding:30px;background:#810;color:#fff;text-align:center;'><p>You might want to <a href='https://docs.esp-rs.org/esp-hal/'>browse the <code>esp-hal</code> documentation on the esp-rs website</a> instead.</p><p>The documentation here on <a href='https://docs.rs'>docs.rs</a> is built for a single chip only (ESP32-C6, in particular), while on the esp-rs website you can select your exact chip from the list of supported devices. Available peripherals and their APIs change depending on the chip.</p></div>\n\n<br/>\n\n"
4)]
5#![cfg_attr(esp32, doc = "**ESP32**")]
14#![cfg_attr(esp32s2, doc = "**ESP32-S2**")]
15#![cfg_attr(esp32s3, doc = "**ESP32-S3**")]
16#![cfg_attr(esp32c2, doc = "**ESP32-C2**")]
17#![cfg_attr(esp32c3, doc = "**ESP32-C3**")]
18#![cfg_attr(esp32c6, doc = "**ESP32-C6**")]
19#![cfg_attr(esp32h2, doc = "**ESP32-H2**")]
20#![doc = ""]
103#![doc = include_str!(concat!(env!("OUT_DIR"), "/esp_hal_config_table.md"))]
104#![doc = ""]
105#![doc = document_features::document_features!(feature_label = r#"<span class="stab portability"><code>{feature}</code></span>"#)]
138#![doc(html_logo_url = "https://avatars.githubusercontent.com/u/46717278")]
139#![allow(asm_sub_register, async_fn_in_trait, stable_features)]
140#![cfg_attr(xtensa, feature(asm_experimental_arch))]
141#![deny(missing_docs, rust_2018_idioms, rustdoc::all)]
142#![cfg_attr(docsrs, feature(doc_cfg))]
143#![no_std]
144
145mod fmt;
147
148use core::marker::PhantomData;
149
150#[cfg(riscv)]
151#[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
152#[cfg_attr(not(feature = "unstable"), doc(hidden))]
153pub use esp_riscv_rt::{self, riscv};
154#[cfg(xtensa)]
155#[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
156#[cfg_attr(not(feature = "unstable"), doc(hidden))]
157pub use xtensa_lx_rt::{self, xtensa_lx};
158
159#[cfg(efuse)]
160#[instability::unstable]
161#[cfg_attr(not(feature = "unstable"), allow(unused))]
162pub use self::soc::efuse;
163#[cfg(lp_core)]
164#[instability::unstable]
165#[cfg_attr(not(feature = "unstable"), allow(unused))]
166pub use self::soc::lp_core;
167pub use self::soc::peripherals;
168pub(crate) use self::soc::peripherals::pac;
169#[instability::unstable]
170#[cfg(feature = "psram")]
171pub use self::soc::psram;
172#[cfg(ulp_riscv_core)]
173#[instability::unstable]
174#[cfg_attr(not(feature = "unstable"), allow(unused))]
175pub use self::soc::ulp_core;
176
177#[cfg(any(dport, hp_sys, pcr, system))]
178pub mod clock;
179#[cfg(gpio)]
180pub mod gpio;
181#[cfg(any(i2c0, i2c1))]
182pub mod i2c;
183pub mod peripheral;
184#[cfg(any(hmac, sha))]
185mod reg_access;
186#[cfg(any(spi0, spi1, spi2, spi3))]
187pub mod spi;
188pub mod system;
189pub mod time;
190#[cfg(any(uart0, uart1, uart2))]
191pub mod uart;
192
193mod macros;
194
195pub use procmacros::blocking_main as main;
196#[cfg(any(lp_core, ulp_riscv_core))]
197#[cfg(feature = "unstable")]
198#[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
199pub use procmacros::load_lp_code;
200#[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
201#[instability::unstable]
202#[cfg_attr(not(feature = "unstable"), allow(unused))]
203pub use procmacros::{handler, ram};
204
205#[doc(hidden)]
207macro_rules! unstable_module {
208 ($(
209 $(#[$meta:meta])*
210 pub mod $module:ident;
211 )*) => {
212 $(
213 $(#[$meta])*
214 #[cfg(feature = "unstable")]
215 #[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
216 pub mod $module;
217
218 $(#[$meta])*
219 #[cfg(not(feature = "unstable"))]
220 #[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
221 #[allow(unused)]
222 pub(crate) mod $module;
223 )*
224 };
225}
226
227pub(crate) use unstable_module;
228
229unstable_module! {
230 #[cfg(aes)]
231 pub mod aes;
232 #[cfg(any(adc1, adc2, dac))]
233 pub mod analog;
234 pub mod asynch;
235 #[cfg(assist_debug)]
236 pub mod assist_debug;
237 pub mod config;
238 pub mod debugger;
239 #[cfg(any(xtensa, all(riscv, systimer)))]
240 pub mod delay;
241 #[cfg(any(gdma, pdma))]
242 pub mod dma;
243 #[cfg(ecc)]
244 pub mod ecc;
245 #[cfg(soc_etm)]
246 pub mod etm;
247 #[cfg(hmac)]
248 pub mod hmac;
249 #[cfg(any(i2s0, i2s1))]
250 pub mod i2s;
251 #[cfg(any(dport, interrupt_core0, interrupt_core1))]
252 pub mod interrupt;
253 #[cfg(lcd_cam)]
254 pub mod lcd_cam;
255 #[cfg(ledc)]
256 pub mod ledc;
257 #[cfg(any(mcpwm0, mcpwm1))]
258 pub mod mcpwm;
259 #[cfg(usb0)]
260 pub mod otg_fs;
261 #[cfg(parl_io)]
262 pub mod parl_io;
263 #[cfg(pcnt)]
264 pub mod pcnt;
265 #[cfg(rmt)]
266 pub mod rmt;
267 #[cfg(rng)]
268 pub mod rng;
269 pub mod rom;
270 #[cfg(rsa)]
271 pub mod rsa;
272 #[cfg(any(lp_clkrst, rtc_cntl))]
273 pub mod rtc_cntl;
274 #[cfg(sha)]
275 pub mod sha;
276 #[doc(hidden)]
277 pub mod sync;
278 #[cfg(any(systimer, timg0, timg1))]
279 pub mod timer;
280 #[cfg(touch)]
281 pub mod touch;
282 #[cfg(trace0)]
283 pub mod trace;
284 #[cfg(tsens)]
285 pub mod tsens;
286 #[cfg(any(twai0, twai1))]
287 pub mod twai;
288 #[cfg(usb_device)]
289 pub mod usb_serial_jtag;
290}
291
292#[instability::unstable]
294#[allow(unused_imports)]
295pub mod trapframe {
296 #[cfg(riscv)]
297 pub use esp_riscv_rt::TrapFrame;
298 #[cfg(xtensa)]
299 pub use xtensa_lx_rt::exception::Context as TrapFrame;
300}
301
302mod soc;
305
306#[cfg(is_debug_build)]
307esp_build::warning! {"
308WARNING: use --release
309 We *strongly* recommend using release profile when building esp-hal.
310 The dev profile can potentially be one or more orders of magnitude
311 slower than release, and may cause issues with timing-senstive
312 peripherals and/or devices.
313"}
314
315pub trait DriverMode: crate::private::Sealed {}
317
318#[derive(Debug)]
320pub struct Blocking;
321
322#[derive(Debug)]
324pub struct Async(PhantomData<*const ()>);
325
326unsafe impl Sync for Async {}
327
328impl crate::DriverMode for Blocking {}
329impl crate::DriverMode for Async {}
330impl crate::private::Sealed for Blocking {}
331impl crate::private::Sealed for Async {}
332
333pub(crate) mod private {
334 pub trait Sealed {}
335
336 #[non_exhaustive]
337 #[doc(hidden)]
338 pub struct Internal;
340
341 impl Internal {
342 pub unsafe fn conjure() -> Self {
354 Self
355 }
356 }
357}
358
359#[cfg(feature = "unstable")]
360#[doc(hidden)]
361pub use private::Internal;
362
363#[instability::unstable]
373pub unsafe trait Persistable: Sized {}
374
375macro_rules! impl_persistable {
376 ($($t:ty),+) => {$(
377 unsafe impl Persistable for $t {}
378 )+};
379 (atomic $($t:ident),+) => {$(
380 unsafe impl Persistable for portable_atomic::$t {}
381 )+};
382}
383
384impl_persistable!(u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, usize, isize, f32, f64);
385impl_persistable!(atomic AtomicU8, AtomicI8, AtomicU16, AtomicI16, AtomicU32, AtomicI32, AtomicUsize, AtomicIsize);
386
387unsafe impl<T: Persistable, const N: usize> Persistable for [T; N] {}
388
389#[doc(hidden)]
390pub mod __macro_implementation {
391 #[instability::unstable]
394 pub const fn assert_is_zeroable<T: bytemuck::Zeroable>() {}
395
396 #[instability::unstable]
397 pub const fn assert_is_persistable<T: super::Persistable>() {}
398
399 #[cfg(riscv)]
400 pub use esp_riscv_rt::entry as __entry;
401 #[cfg(xtensa)]
402 pub use xtensa_lx_rt::entry as __entry;
403}
404
405#[cfg(riscv)]
406#[export_name = "hal_main"]
407fn hal_main(a0: usize, a1: usize, a2: usize) -> ! {
408 extern "Rust" {
409 fn main(a0: usize, a1: usize, a2: usize) -> !;
411 }
412
413 extern "C" {
414 static mut __stack_chk_guard: u32;
415 }
416
417 unsafe {
418 let stack_chk_guard = core::ptr::addr_of_mut!(__stack_chk_guard);
419 stack_chk_guard.write_volatile(0xdeadbabe);
422
423 main(a0, a1, a2);
424 }
425}
426
427#[export_name = "__stack_chk_fail"]
428unsafe extern "C" fn stack_chk_fail() {
429 panic!("Stack corruption detected");
430}
431
432#[cfg(feature = "unstable")]
433use crate::config::{WatchdogConfig, WatchdogStatus};
434use crate::{
435 clock::{Clocks, CpuClock},
436 peripherals::Peripherals,
437};
438
439#[non_exhaustive]
448#[derive(Default, Clone, Copy, procmacros::BuilderLite)]
449pub struct Config {
450 cpu_clock: CpuClock,
452
453 #[cfg(any(doc, feature = "unstable"))]
455 #[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
456 watchdog: WatchdogConfig,
457
458 #[cfg(any(doc, feature = "unstable"))]
460 #[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
461 #[cfg(feature = "psram")]
462 psram: psram::PsramConfig,
463}
464
465pub fn init(config: Config) -> Peripherals {
470 crate::soc::pre_init();
471
472 system::disable_peripherals();
473
474 let mut peripherals = Peripherals::take();
475
476 let mut rtc = crate::rtc_cntl::Rtc::new(&mut peripherals.LPWR);
478
479 cfg_if::cfg_if! {
481 if #[cfg(feature = "unstable")]
482 {
483 #[cfg(not(any(esp32, esp32s2)))]
484 if config.watchdog.swd() {
485 rtc.swd.enable();
486 } else {
487 rtc.swd.disable();
488 }
489
490 match config.watchdog.rwdt() {
491 WatchdogStatus::Enabled(duration) => {
492 rtc.rwdt.enable();
493 rtc.rwdt
494 .set_timeout(crate::rtc_cntl::RwdtStage::Stage0, duration);
495 }
496 WatchdogStatus::Disabled => {
497 rtc.rwdt.disable();
498 }
499 }
500
501 match config.watchdog.timg0() {
502 WatchdogStatus::Enabled(duration) => {
503 let mut timg0_wd = crate::timer::timg::Wdt::<crate::peripherals::TIMG0>::new();
504 timg0_wd.enable();
505 timg0_wd.set_timeout(crate::timer::timg::MwdtStage::Stage0, duration);
506 }
507 WatchdogStatus::Disabled => {
508 crate::timer::timg::Wdt::<crate::peripherals::TIMG0>::new().disable();
509 }
510 }
511
512 #[cfg(timg1)]
513 match config.watchdog.timg1() {
514 WatchdogStatus::Enabled(duration) => {
515 let mut timg1_wd = crate::timer::timg::Wdt::<crate::peripherals::TIMG1>::new();
516 timg1_wd.enable();
517 timg1_wd.set_timeout(crate::timer::timg::MwdtStage::Stage0, duration);
518 }
519 WatchdogStatus::Disabled => {
520 crate::timer::timg::Wdt::<crate::peripherals::TIMG1>::new().disable();
521 }
522 }
523 }
524 else
525 {
526 #[cfg(not(any(esp32, esp32s2)))]
527 rtc.swd.disable();
528
529 rtc.rwdt.disable();
530
531 crate::timer::timg::Wdt::<crate::peripherals::TIMG0>::new().disable();
532
533 #[cfg(timg1)]
534 crate::timer::timg::Wdt::<crate::peripherals::TIMG1>::new().disable();
535 }
536 }
537
538 Clocks::init(config.cpu_clock);
539
540 #[cfg(esp32)]
541 crate::time::time_init();
542
543 crate::gpio::bind_default_interrupt_handler();
544
545 #[cfg(feature = "psram")]
546 crate::psram::init_psram(config.psram);
547
548 peripherals
549}