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.espressif.com/projects/rust/'>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#![doc = concat!("**", chip_pretty!(), "**")]
9# driver and you
44do not intend to drop the driver, you can pass the peripheral singleton to
45the driver by value:
46
47```rust, ignore
48// Peripheral singletons are returned from the `init` function.
49let peripherals = esp_hal::init(esp_hal::Config::default());
50
51let mut i2c = I2c::new(peripherals.I2C0, /* ... */);
52```
53"#
54)]
55#![cfg_attr(
105 gpio_driver_supported,
109 doc = r#"
110## Blinky
111
112Some minimal code to blink an LED looks like this:
113
114```rust, no_run
115#![no_std]
116#![no_main]
117
118use esp_hal::{
119 clock::CpuClock,
120 gpio::{Io, Level, Output, OutputConfig},
121 main,
122 time::{Duration, Instant},
123};
124
125// You need a panic handler. Usually, you would use esp_backtrace, panic-probe, or
126// something similar, but you can also bring your own like this:
127#[panic_handler]
128fn panic(_: &core::panic::PanicInfo) -> ! {
129 esp_hal::system::software_reset()
130}
131
132#[main]
133fn main() -> ! {
134 let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max());
135 let peripherals = esp_hal::init(config);
136
137 // Set GPIO0 as an output, and set its state high initially.
138 let mut led = Output::new(peripherals.GPIO0, Level::High, OutputConfig::default());
139
140 loop {
141 led.toggle();
142 // Wait for half a second
143 let delay_start = Instant::now();
144 while delay_start.elapsed() < Duration::from_millis(500) {}
145 }
146}
147```
148"#
149)]
150#![doc = ""]
158#![doc = include_str!(concat!(env!("OUT_DIR"), "/esp_hal_config_table.md"))]
159#![doc = ""]
160#![doc = document_features::document_features!(feature_label = r#"<span class="stab portability"><code>{feature}</code></span>"#)]
197#![doc(html_logo_url = "https://docs.espressif.com/projects/rust/esp-rs-grey-bg.svg")]
198#![allow(asm_sub_register, async_fn_in_trait, stable_features)]
199#![cfg_attr(xtensa, feature(asm_experimental_arch))]
200#![deny(missing_docs, rust_2018_idioms, rustdoc::all)]
201#![allow(rustdoc::private_doc_tests)] #![cfg_attr(docsrs, feature(doc_cfg, custom_inner_attributes, proc_macro_hygiene))]
203#![cfg_attr(
205 semver_checks,
206 allow(rustdoc::private_intra_doc_links, rustdoc::broken_intra_doc_links)
207)]
208#![cfg_attr(docsrs, allow(invalid_doc_attributes))] #![cfg_attr(docsrs, doc(auto_cfg = false))]
211#![no_std]
212
213mod fmt;
215
216#[macro_use]
217extern crate esp_metadata_generated;
218
219#[doc(hidden)]
221macro_rules! unstable_module {
222 ($(
223 $(#[$meta:meta])*
224 pub mod $module:ident;
225 )*) => {
226 $(
227 $(#[$meta])*
228 #[cfg(feature = "unstable")]
229 #[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
230 pub mod $module;
231
232 $(#[$meta])*
233 #[cfg(not(feature = "unstable"))]
234 #[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
235 #[allow(unused)]
236 pub(crate) mod $module;
237 )*
238 };
239}
240
241#[doc(hidden)]
244macro_rules! unstable_driver {
245 ($(
246 $(#[$meta:meta])*
247 pub mod $module:ident;
248 )*) => {
249 $(
250 $(#[$meta])*
251 #[cfg(feature = "unstable")]
252 #[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
253 pub mod $module;
254 )*
255 };
256}
257
258use core::marker::PhantomData;
259
260pub use esp_metadata_generated::chip;
261use esp_rom_sys as _;
262#[allow(unused)]
263pub(crate) use unstable_driver;
264pub(crate) use unstable_module;
265
266metadata!("build_info", CHIP_NAME, chip!());
267metadata!(
268 "build_info",
269 MIN_CHIP_REVISION,
270 esp_config::esp_config_str!("ESP_HAL_CONFIG_MIN_CHIP_REVISION")
271);
272
273#[cfg(feature = "rt")]
274cfg_select! {
275 riscv => {
276 #[cfg_attr(docsrs, doc(cfg(all(feature = "unstable", feature = "rt"))))]
277 #[cfg_attr(not(feature = "unstable"), doc(hidden))]
278 pub use esp_riscv_rt::{self, riscv};
279 }
280 xtensa => {
281 #[cfg_attr(docsrs, doc(cfg(all(feature = "unstable", feature = "rt"))))]
282 #[cfg_attr(not(feature = "unstable"), doc(hidden))]
283 pub use xtensa_lx_rt::{self, xtensa_lx};
284 }
285}
286
287pub(crate) use peripherals::pac;
288pub(crate) mod private;
289
290#[cfg(any(soc_has_dport, soc_has_hp_sys, soc_has_pcr, soc_has_system))]
291pub mod clock;
292#[cfg(gpio_driver_supported)]
293pub mod gpio;
294#[cfg(i2c_master_driver_supported)]
295pub mod i2c;
296#[cfg(i2s_driver_supported)]
298#[path = "i2s/clocks/mod.rs"]
299mod i2s_clocks;
300pub mod peripherals;
301#[cfg(all(
302 feature = "unstable",
303 any(
304 hmac_driver_supported,
305 sha_driver_supported,
306 ethernet_driver_supported,
307 mipi_dsi_driver_supported
308 )
309))]
310mod reg_access;
311#[cfg(rng_driver_supported)]
312pub mod rng;
313#[cfg(any(spi_master_driver_supported, spi_slave_driver_supported))]
314pub mod spi;
315pub mod system;
316pub mod time;
317#[cfg(uart_driver_supported)]
318pub mod uart;
319
320mod macros;
321
322#[instability::unstable]
323pub use procmacros::handler;
324#[instability::unstable]
325#[cfg(ulp_riscv_driver_supported)]
326pub use procmacros::load_lp_code;
327#[cfg(feature = "rt")]
328pub use procmacros::main;
329pub use procmacros::ram;
330
331#[instability::unstable]
332#[cfg(ulp_riscv_driver_supported)]
333pub use self::soc::lp_core;
334
335#[cfg(all(feature = "rt", feature = "exception-handler"))]
336mod exception_handler;
337
338pub mod efuse;
339pub mod interrupt;
340
341unstable_module! {
342 pub mod asynch;
343 pub mod debugger;
344 pub mod rom;
345 #[doc(hidden)]
346 pub mod sync;
347 #[cfg(any(adc_driver_supported, dac_driver_supported))]
349 pub mod analog;
350 #[cfg(any(systimer_driver_supported, timergroup_driver_supported))]
351 pub mod timer;
352 #[cfg(temp_sensor_driver_supported)]
353 pub mod tsens;
354 #[cfg(soc_has_lpwr)]
355 pub mod rtc_cntl;
356 #[cfg(dma_driver_supported)]
357 pub mod dma;
358 #[cfg(etm_driver_supported)]
359 pub mod etm;
360 #[cfg(soc_has_psram)] pub mod psram;
362}
363
364#[cfg(any(
365 sha_driver_supported,
366 rsa_driver_supported,
367 aes_driver_supported,
368 ecc_driver_supported
369))]
370mod work_queue;
371
372unstable_driver! {
373 #[cfg(aes_driver_supported)]
374 pub mod aes;
375 #[cfg(assist_debug_driver_supported)]
376 pub mod assist_debug;
377 #[cfg(canfd_driver_supported)]
378 pub mod canfd;
379 pub mod delay;
380 #[cfg(ecc_driver_supported)]
381 pub mod ecc;
382 #[cfg(flash_driver_supported)]
383 pub mod flash;
384 #[cfg(hmac_driver_supported)]
385 pub mod hmac;
386 #[cfg(i2s_driver_supported)]
387 pub mod i2s;
388 #[cfg(soc_has_lcd_cam)]
389 pub mod lcd_cam;
390 #[cfg(ledc_driver_supported)]
391 pub mod ledc;
392 #[cfg(mcpwm_driver_supported)]
393 pub mod mcpwm;
394 #[cfg(parl_io_driver_supported)]
395 pub mod parl_io;
396 #[cfg(pcnt_driver_supported)]
397 pub mod pcnt;
398 #[cfg(rmt_driver_supported)]
399 pub mod rmt;
400 #[cfg(rsa_driver_supported)]
401 pub mod rsa;
402 #[cfg(sdmmc_driver_supported)]
403 pub mod sdmmc;
404 #[cfg(sha_driver_supported)]
405 pub mod sha;
406 #[cfg(sdm_driver_supported)]
407 pub mod sdm;
408 #[cfg(touch_driver_supported)]
409 pub mod touch;
410 #[cfg(soc_has_trace0)]
411 pub mod trace;
412 #[cfg(twai_driver_supported)]
413 pub mod twai;
414 #[cfg(any(
415 usb_otg_driver_supported,
416 usb_otg_hs_driver_supported,
417 usb_serial_jtag_driver_supported,
418 ))]
419 pub mod usb;
420 #[cfg(ethernet_driver_supported)]
421 pub mod ethernet;
422 #[cfg(mipi_dsi_driver_supported)]
423 pub mod mipi_dsi;
424}
425
426#[instability::unstable]
428#[cfg(feature = "rt")]
429#[allow(unused_imports)]
430pub mod trapframe {
431 #[cfg(riscv)]
432 pub use esp_riscv_rt::TrapFrame;
433 #[cfg(xtensa)]
434 pub use xtensa_lx_rt::exception::Context as TrapFrame;
435}
436
437mod soc;
440
441use crate::pac::generic::{Readable, Reg, Resettable, W, Writable};
443
444#[allow(unused)]
445trait RegisterToggle {
446 type Reg: Readable + Resettable + Writable;
447
448 fn toggle(&self, op: impl Fn(&mut W<Self::Reg>, bool) -> &mut W<Self::Reg>);
453}
454
455impl<REG> RegisterToggle for Reg<REG>
456where
457 REG: Readable + Resettable + Writable,
458{
459 type Reg = REG;
460
461 fn toggle(&self, op: impl Fn(&mut W<REG>, bool) -> &mut W<REG>) {
462 let bits = self.modify(|_, w| op(w, true));
463
464 self.write(|w| {
465 unsafe { w.bits(bits) };
466 op(w, false)
467 });
468 }
469}
470
471#[cfg(is_debug_build)]
472procmacros::warning! {"
473WARNING: use --release
474 We *strongly* recommend using release profile when building esp-hal.
475 The dev profile can potentially be one or more orders of magnitude
476 slower than release, and may cause issues with timing-sensitive
477 peripherals or devices.
478"}
479
480pub trait DriverMode: crate::private::Sealed {}
486
487#[procmacros::doc_replace]
488#[cfg_attr(
497 all(uart_driver_supported, gpio_driver_supported),
501 doc = r#"
502```rust, no_run
503# {before_snippet}
504# use esp_hal::uart::{Config, Uart};
505let uart = Uart::new(peripherals.UART0, Config::default())?
506 .with_rx(peripherals.GPIO1)
507 .with_tx(peripherals.GPIO2)
508 .into_async();
509let blocking_uart = uart.into_blocking();
510# {after_snippet}
511```
512"#
513)]
514#[derive(Debug)]
515#[non_exhaustive]
516pub struct Blocking;
517
518#[procmacros::doc_replace]
519#[cfg_attr(
525 all(uart_driver_supported, gpio_driver_supported),
529 doc = r#"
530```rust, no_run
531# {before_snippet}
532# use esp_hal::uart::{Config, Uart};
533let uart = Uart::new(peripherals.UART0, Config::default())?
534 .with_rx(peripherals.GPIO1)
535 .with_tx(peripherals.GPIO2)
536 .into_async();
537///
538# {after_snippet}
539```
540"#
541)]
542#[derive(Debug)]
565#[non_exhaustive]
566pub struct Async(PhantomData<*const ()>);
567
568unsafe impl Sync for Async {}
569
570impl crate::DriverMode for Blocking {}
571impl crate::DriverMode for Async {}
572impl crate::private::Sealed for Blocking {}
573impl crate::private::Sealed for Async {}
574
575#[doc(hidden)]
576pub use private::Internal;
577
578#[instability::unstable]
587pub unsafe trait Persistable: Sized {}
588
589#[doc(hidden)]
595pub unsafe trait Uninit: Sized {}
596
597macro_rules! impl_persistable {
598 ($($t:ty),+) => {$(
599 unsafe impl Persistable for $t {}
600 )+};
601 (atomic $($t:ident),+) => {$(
602 unsafe impl Persistable for portable_atomic::$t {}
603 )+};
604}
605
606impl_persistable!(
607 u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, usize, isize, f32, f64
608);
609impl_persistable!(atomic AtomicU8, AtomicI8, AtomicU16, AtomicI16, AtomicU32, AtomicI32, AtomicUsize, AtomicIsize);
610
611unsafe impl<T: Persistable, const N: usize> Persistable for [T; N] {}
612
613unsafe impl<T> Uninit for core::mem::MaybeUninit<T> {}
614unsafe impl<T, const N: usize> Uninit for [core::mem::MaybeUninit<T>; N] {}
615
616#[doc(hidden)]
617pub mod __macro_implementation {
618 #[instability::unstable]
621 pub const fn assert_is_zeroable<T: bytemuck::Zeroable>() {}
622
623 #[instability::unstable]
624 pub const fn assert_is_persistable<T: super::Persistable>() {}
625
626 pub const fn assert_is_uninit<T: super::Uninit>() {}
627
628 #[cfg(feature = "rt")]
629 #[cfg(riscv)]
630 pub use esp_riscv_rt::entry as __entry;
631 pub use static_cell;
632 #[cfg(feature = "rt")]
633 #[cfg(xtensa)]
634 pub use xtensa_lx_rt::entry as __entry;
635}
636
637use crate::clock::{ClockConfig, CpuClock};
638#[cfg(feature = "rt")]
639use crate::peripherals::Peripherals;
640
641#[cfg(feature = "rt")]
643pub(crate) static ESP_HAL_LOCK: esp_sync::RawMutex = esp_sync::RawMutex::new();
644
645#[procmacros::doc_replace]
646#[non_exhaustive]
672#[derive(Default, Clone, Copy, procmacros::BuilderLite)]
673pub struct Config {
674 #[builder_lite(skip)]
676 cpu_clock: ClockConfig,
677}
678
679impl Config {
680 #[cfg_attr(
682 feature = "unstable",
683 doc = r"
684
685With the `unstable` feature enabled, this function accepts both [`ClockConfig`] and [`CpuClock`].
686"
687 )]
688 #[cfg(feature = "unstable")]
689 pub fn with_cpu_clock(self, cpu_clock: impl Into<ClockConfig>) -> Self {
690 Self {
691 cpu_clock: cpu_clock.into(),
692 ..self
693 }
694 }
695
696 #[cfg(not(feature = "unstable"))]
698 pub fn with_cpu_clock(self, cpu_clock: CpuClock) -> Self {
699 Self {
700 cpu_clock: cpu_clock.into(),
701 ..self
702 }
703 }
704
705 #[cfg_attr(feature = "unstable", deprecated(note = "Use `clock_config` instead."))] pub fn cpu_clock(&self) -> CpuClock {
712 unwrap!(
713 self.cpu_clock.try_get_preset(),
714 "CPU clock configuration is not a preset"
715 )
716 }
717
718 #[instability::unstable]
720 pub fn clock_config(&self) -> ClockConfig {
721 self.cpu_clock
722 }
723}
724
725#[procmacros::doc_replace]
726#[cfg_attr(docsrs, doc(cfg(feature = "rt")))]
739#[cfg(feature = "rt")]
740pub fn init(config: Config) -> Peripherals {
741 crate::soc::pre_init();
742
743 let min_rev = esp_config::esp_config_int!(u16, "ESP_HAL_CONFIG_MIN_CHIP_REVISION");
744 assert!(
745 crate::efuse::chip_revision() >= crate::efuse::ChipRevision::from_combined(min_rev),
746 "This chip's hardware revision is older than the minimum required \
747 v{}.{} (ESP_HAL_CONFIG_MIN_CHIP_REVISION).",
748 min_rev / 100,
749 min_rev % 100,
750 );
751
752 #[cfg(soc_cpu_has_branch_predictor)]
753 crate::soc::branch_predictor::enable();
754
755 #[cfg(init_stack_ptr_range_check)]
757 crate::soc::ensure_stack_pointer_in_range();
758
759 #[cfg(stack_guard_monitoring)]
760 crate::soc::enable_main_stack_guard_monitoring();
761
762 #[cfg(all(feature = "rt", enable_pmp, riscv))]
763 crate::soc::enable_pmp();
764
765 system::disable_peripherals();
766
767 let mut peripherals = Peripherals::take();
768
769 crate::clock::init(config.clock_config());
770
771 let mut rtc = crate::rtc_cntl::Rtc::new(peripherals.RTC_TIMER.reborrow());
773
774 #[cfg(sleep_driver_supported)]
775 crate::rtc_cntl::sleep::init(&rtc);
776
777 #[cfg(soc_has_swd_watchdog)]
779 rtc.swd.disable();
780
781 rtc.rwdt.disable();
782
783 #[cfg(timergroup_timg0)]
784 crate::timer::timg::Wdt::<crate::peripherals::TIMG0<'static>>::new().disable();
785
786 #[cfg(timergroup_timg1)]
787 crate::timer::timg::Wdt::<crate::peripherals::TIMG1<'static>>::new().disable();
788
789 crate::time::implem::time_init();
790
791 #[cfg(gpio_driver_supported)]
792 crate::gpio::interrupt::bind_default_interrupt_handler();
793
794 unsafe {
795 esp_rom_sys::init_syscall_table();
796 }
797
798 #[cfg(all(riscv, write_vec_table_monitoring))]
799 crate::soc::setup_trap_section_protection();
800
801 #[cfg(all(feature = "unstable", multi_core))]
802 crate::interrupt::ipc::install();
803
804 peripherals
805}