Documenting a number of peripherals and packages (#680)

* Initial documentation improvements

* More documentation improvements

* More documentation improvements


More modules documented

* Finished SOC documentation for esp32 + TWAI

* Fix: fix incorrect formatting

* Adding more documentation to rom, and soc peripherals for multiple chips

* Adding documentation for multiple peripherals

* Adding SOC module documentation

* Analog and clock modules are documented

* Adding module-level documentation for DMA and INTERRUPT peripherals

* Finishing job + minor fixes

* Fix unopened HTML break

* Rustfmt adjustment 


formatting


Fix typo

* Add CHANGELOG record


Fix typo

* Fix typos, mistakes, improving docs

Co-authored-by: Dániel Buga <bugadani@gmail.com>
Fix typo

Co-authored-by: Dániel Buga <bugadani@gmail.com>
Fix typo

Co-authored-by: Dániel Buga <bugadani@gmail.com>
Fix typo

Co-authored-by: Dániel Buga <bugadani@gmail.com>
fix typo

Co-authored-by: Dániel Buga <bugadani@gmail.com>
Fix typo

Co-authored-by: Dániel Buga <bugadani@gmail.com>
Fix typo

Co-authored-by: Scott Mabin <scott@mabez.dev>
Fixing typos, mistakes, improving docs.

* Fix formatting, mistakes and typos

* Fixing a bunch of logical, grammatical and formatting mistakes
This commit is contained in:
Kirill Mikhailov 2023-08-09 15:33:50 +02:00 committed by GitHub
parent 4baf0b96c6
commit 2bd10526a7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
92 changed files with 2789 additions and 214 deletions

View File

@ -19,6 +19,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Implement sleep with some wakeup methods for `esp32-s3` (#660, #689, #696)
- Add feature enabling directly hooking the interrupt vector table
- Add `ClockControl::max` helper for all chips (#701)
- Added module-level documentation for all peripherals
- Added module-level documentation for all peripherals (#680)
### Changed

View File

@ -1,10 +1,61 @@
//! Advanced Encryption Standard (AES) support.
//! # Advanced Encryption Standard (AES) support.
//!
//! This module provides functions and structs for AES encryption and
//! decryption.
//! ## Overview
//! The AES module provides an interface to interact with the AES peripheral,
//! provides encryption and decryption capabilities for ESP chips using the AES
//! algorithm. We currently support the following AES encryption modes:
//! * AES-128
//! * AES-192
//! * AES-256
//!
//! ## Example
//! ### Initialization
//! ```no_run
//! let mut aes = Aes::new(peripherals.AES, &mut system.peripheral_clock_control);
//! ```
//! ### Creating key and block Buffer
//! ```no_run
//! let keytext = "SUp4SeCp@sSw0rd".as_bytes();
//! let plaintext = "message".as_bytes();
//!
//! // create an array with aes128 key size
//! let mut keybuf = [0_u8; 16];
//! keybuf[..keytext.len()].copy_from_slice(keytext);
//!
//! // create an array with aes block size
//! let mut block_buf = [0_u8; 16];
//! block_buf[..plaintext.len()].copy_from_slice(plaintext);
//! ```
//!
//! ### Encrypting and Decrypting (using hardware)
//! ```no_run
//! let key = Key::<Aes128>::from(&keybuf);
//!
//! let mut cipher = Cipher::new(&mut aes, &key);
//! let mut block = block_buf.clone();
//! cipher.encrypt_block(&mut block);
//!
//! let hw_encrypted = block.clone();
//! cipher.decrypt_block(&mut block);
//! let hw_decrypted = block;
//! ```
//!
//! ### Encrypting and Decrypting (using software)
//! ```no_run
//! let key = GenericArray::from(keybuf);
//!
//! let mut block = GenericArray::from(block_buf);
//! let cipher = Aes128SW::new(&key);
//! cipher.encrypt_block(&mut block);
//!
//! let sw_encrypted = block.clone();
//! cipher.decrypt_block(&mut block);
//!
//! let sw_decrypted = block;
//! ```
//!
//! ### Implementation State
//! * DMA mode is currently not supported.
//! * DMA mode is currently not supported ⚠️
use core::marker::PhantomData;

View File

@ -421,10 +421,15 @@ macro_rules! impl_adc_interface {
pub use impl_adc_interface;
pub mod implementation {
//! Analog to digital (ADC) conversion support.
//! # Analog to digital (ADC) conversion support.
//!
//! This module provides functions for reading analog values from two
//! analog to digital converters available on the ESP32: `ADC1` and `ADC2`.
//! ## Overview
//! The `ADC` module in the `analog` driver enables users to perform
//! analog-to-digital conversions, allowing them to measure real-world
//! analog signals with high accuracy.
//!
//! This module provides functions for reading analog values from the
//! analog to digital converter available on the ESP32: `ADC1` and `ADC2`.
//!
//! The following pins can be configured for analog readout:
//!
@ -440,6 +445,28 @@ pub mod implementation {
//! | 7 | GPIO35 (VDET_2) | GPIO27 |
//! | 8 | | GPIO25 |
//! | 9 | | GPIO26 |
//!
//! ## Example
//! #### ADC on Xtensa architecture
//! ```no_run
//! // Create ADC instances
//! let analog = peripherals.SENS.split();
//!
//! let mut adc1_config = AdcConfig::new();
//!
//! let mut pin3 =
//! adc1_config.enable_pin(io.pins.gpio3.into_analog(), Attenuation::Attenuation11dB);
//!
//! let mut adc1 = ADC::<ADC1>::adc(analog.adc1, adc1_config).unwrap();
//!
//! let mut delay = Delay::new(&clocks);
//!
//! loop {
//! let pin3_value: u16 = nb::block!(adc1.read(&mut pin3)).unwrap();
//! println!("PIN3 ADC reading = {}", pin3_value);
//! delay.delay_ms(1500u32);
//! }
//! ```
use embedded_hal::adc::Channel;

View File

@ -691,10 +691,41 @@ pub use impl_adc_interface;
#[cfg(esp32c2)]
pub mod implementation {
//! Analog to digital (ADC) conversion support.
//! # Analog to digital (ADC) conversion support.
//!
//! ## Overview
//! The `ADC` module in the `analog` driver enables users to perform
//! analog-to-digital conversions, allowing them to measure real-world
//! analog signals with high accuracy.
//!
//! This module provides functions for reading analog values from the
//! analog to digital converter available on the ESP32-C2: `ADC1`.
//!
//! ## Example
//! #### ADC on Risc-V architecture
//! ```no_run
//! // Create ADC instances
//! let analog = peripherals.APB_SARADC.split();
//!
//! let mut adc1_config = AdcConfig::new();
//!
//! let mut pin = adc1_config.enable_pin(io.pins.gpio2.into_analog(), Attenuation::Attenuation11dB);
//!
//! let mut adc1 = ADC::<ADC1>::adc(
//! &mut system.peripheral_clock_control,
//! analog.adc1,
//! adc1_config,
//! )
//! .unwrap();
//!
//! let mut delay = Delay::new(&clocks);
//!
//! loop {
//! let pin_value: u16 = nb::block!(adc1.read(&mut pin)).unwrap();
//! println!("PIN2 ADC reading = {}", pin_value);
//! delay.delay_ms(1500u32);
//! }
//! ```
use embedded_hal::adc::Channel;
@ -714,11 +745,42 @@ pub mod implementation {
#[cfg(esp32c3)]
pub mod implementation {
//! Analog to digital (ADC) conversion support.
//! # Analog to digital (ADC) conversion support.
//!
//! This module provides functions for reading analog values from two
//! analog to digital converters available on the ESP32-C3: `ADC1` and
//! ## Overview
//! The `ADC` module in the `analog` driver enables users to perform
//! analog-to-digital conversions, allowing them to measure real-world
//! analog signals with high accuracy.
//!
//! This module provides functions for reading analog values from the
//! analog to digital converter available on the ESP32-C3: `ADC1` and
//! `ADC2`.
//!
//! ## Example
//! #### ADC on Risc-V architecture
//! ```no_run
//! // Create ADC instances
//! let analog = peripherals.APB_SARADC.split();
//!
//! let mut adc1_config = AdcConfig::new();
//!
//! let mut pin = adc1_config.enable_pin(io.pins.gpio2.into_analog(), Attenuation::Attenuation11dB);
//!
//! let mut adc1 = ADC::<ADC1>::adc(
//! &mut system.peripheral_clock_control,
//! analog.adc1,
//! adc1_config,
//! )
//! .unwrap();
//!
//! let mut delay = Delay::new(&clocks);
//!
//! loop {
//! let pin_value: u16 = nb::block!(adc1.read(&mut pin)).unwrap();
//! println!("PIN2 ADC reading = {}", pin_value);
//! delay.delay_ms(1500u32);
//! }
//! ```
use embedded_hal::adc::Channel;
@ -744,10 +806,41 @@ pub mod implementation {
#[cfg(esp32c6)]
pub mod implementation {
//! Analog to digital (ADC) conversion support.
//! # Analog to digital (ADC) conversion support.
//!
//! This module provides functions for reading analog values from one
//! ## Overview
//! The `ADC` module in the `analog` driver enables users to perform
//! analog-to-digital conversions, allowing them to measure real-world
//! analog signals with high accuracy.
//!
//! This module provides functions for reading analog values from the
//! analog to digital converter available on the ESP32-C6: `ADC1`.
//!
//! ## Example
//! #### ADC on Risc-V architecture
//! ```no_run
//! // Create ADC instances
//! let analog = peripherals.APB_SARADC.split();
//!
//! let mut adc1_config = AdcConfig::new();
//!
//! let mut pin = adc1_config.enable_pin(io.pins.gpio2.into_analog(), Attenuation::Attenuation11dB);
//!
//! let mut adc1 = ADC::<ADC1>::adc(
//! &mut system.peripheral_clock_control,
//! analog.adc1,
//! adc1_config,
//! )
//! .unwrap();
//!
//! let mut delay = Delay::new(&clocks);
//!
//! loop {
//! let pin_value: u16 = nb::block!(adc1.read(&mut pin)).unwrap();
//! println!("PIN2 ADC reading = {}", pin_value);
//! delay.delay_ms(1500u32);
//! }
//! ```
use embedded_hal::adc::Channel;
@ -769,10 +862,41 @@ pub mod implementation {
#[cfg(esp32h2)]
pub mod implementation {
//! Analog to digital (ADC) conversion support.
//! # Analog to digital (ADC) conversion support.
//!
//! This module provides functions for reading analog values from one
//! analog to digital converter available on the ESP32-H2: `ADC1`.
//! ## Overview
//! The `ADC` module in the `analog` driver enables users to perform
//! analog-to-digital conversions, allowing them to measure real-world
//! analog signals with high accuracy.
//!
//! This module provides functions for reading analog values from the
//! analog to digital converter available on the ESP32-H2: `ADC1`.
//!
//! ## Example
//! #### ADC on Risc-V architecture
//! ```no_run
//! // Create ADC instances
//! let analog = peripherals.APB_SARADC.split();
//!
//! let mut adc1_config = AdcConfig::new();
//!
//! let mut pin = adc1_config.enable_pin(io.pins.gpio2.into_analog(), Attenuation::Attenuation11dB);
//!
//! let mut adc1 = ADC::<ADC1>::adc(
//! &mut system.peripheral_clock_control,
//! analog.adc1,
//! adc1_config,
//! )
//! .unwrap();
//!
//! let mut delay = Delay::new(&clocks);
//!
//! loop {
//! let pin_value: u16 = nb::block!(adc1.read(&mut pin)).unwrap();
//! println!("PIN2 ADC reading = {}", pin_value);
//! delay.delay_ms(1500u32);
//! }
//! ```
use embedded_hal::adc::Channel;

View File

@ -753,11 +753,38 @@ pub use impl_adc_interface;
#[cfg(esp32s3)]
pub mod implementation {
//! Analog to digital (ADC) conversion support.
//! # Analog to digital (ADC) conversion support.
//!
//! This module provides functions for reading analog values from two
//! analog to digital converters available on the ESP32-S3: `ADC1` and
//! ## Overview
//! The `ADC` module in the `analog` driver enables users to perform
//! analog-to-digital conversions, allowing them to measure real-world
//! analog signals with high accuracy.
//!
//! This module provides functions for reading analog values from the
//! analog to digital converter available on the ESP32-S3: `ADC1` and
//! `ADC2`.
//!
//! ## Example
//! #### ADC on Xtensa architecture
//! ```no_run
//! // Create ADC instances
//! let analog = peripherals.SENS.split();
//!
//! let mut adc1_config = AdcConfig::new();
//!
//! let mut pin3 =
//! adc1_config.enable_pin(io.pins.gpio3.into_analog(), Attenuation::Attenuation11dB);
//!
//! let mut adc1 = ADC::<ADC1>::adc(analog.adc1, adc1_config).unwrap();
//!
//! let mut delay = Delay::new(&clocks);
//!
//! loop {
//! let pin3_value: u16 = nb::block!(adc1.read(&mut pin3)).unwrap();
//! println!("PIN3 ADC reading = {}", pin3_value);
//! delay.delay_ms(1500u32);
//! }
//! ```
use embedded_hal::adc::Channel;
@ -798,11 +825,38 @@ pub mod implementation {
#[cfg(esp32s2)]
pub mod implementation {
//! Analog to digital (ADC) conversion support.
//! # Analog to digital (ADC) conversion support.
//!
//! This module provides functions for reading analog values from two
//! analog to digital converters available on the ESP32-S2: `ADC1` and
//! ## Overview
//! The `ADC` module in the `analog` driver enables users to perform
//! analog-to-digital conversions, allowing them to measure real-world
//! analog signals with high accuracy.
//!
//! This module provides functions for reading analog values from the
//! analog to digital converter available on the ESP32-S2: `ADC1` and
//! `ADC2`.
//!
//! ## Example
//! #### ADC on Xtensa architecture
//! ```no_run
//! // Create ADC instances
//! let analog = peripherals.SENS.split();
//!
//! let mut adc1_config = AdcConfig::new();
//!
//! let mut pin3 =
//! adc1_config.enable_pin(io.pins.gpio3.into_analog(), Attenuation::Attenuation11dB);
//!
//! let mut adc1 = ADC::<ADC1>::adc(analog.adc1, adc1_config).unwrap();
//!
//! let mut delay = Delay::new(&clocks);
//!
//! loop {
//! let pin3_value: u16 = nb::block!(adc1.read(&mut pin3)).unwrap();
//! println!("PIN3 ADC reading = {}", pin3_value);
//! delay.delay_ms(1500u32);
//! }
//! ```
use embedded_hal::adc::Channel;

View File

@ -1,3 +1,17 @@
//! # Analog peripherals - Digital to Analog Converter
//!
//! ## Overview
//! The `DAC` module is part of the `Analog` driver designed for ESP
//! microcontrollers, providing functionalities for `digital-to-analog`
//! conversion.
//!
//! This module simplifies digital-to-analog conversion on ESP microcontrollers,
//! enabling precise control over analog output signals. Developers can choose
//! the `DAC` channel they want to use based on the GPIO pin assignments for
//! each channel. By providing a unified interface for DAC control, the module
//! makes it easier for users to generate accurate analog voltages in their
//! applications, such as audio generation, sensor calibration, and analog
//! signal synthesis.
use crate::{
peripheral::PeripheralRef,
peripherals::{RTC_IO, SENS},

View File

@ -1,3 +1,87 @@
//! # Analog peripherals
//!
//! ## Overview
//! The `Analog` Driver is a module designed for ESP microcontrollers, that
//! provides an interface to interact with analog peripherals on the chip. The
//! module includes support for `Analog-to-Digital Converters (ADC)` and
//! `Digital-to-Analog Converters (DAC)`, offering functionality for precise
//! analog measurements and generating analog output signals.
//!
//! The `ADC` module in the `analog` driver enables users to perform
//! analog-to-digital conversions, allowing them to measure real-world analog
//! signals with high accuracy. The module provides access to multiple ADC
//! units, such as `ADC1` and `ADC2`, which may differ based on the specific ESP
//! microcontroller being used.
//!
//! The `DAC` module in the `analog` driver enables users to generate
//! analog output signals with precise control over voltage levels. The module
//! supports multiple DAC units, such as `DAC1` and `DAC2`, which may vary
//! depending on the specific ESP microcontroller.
//!
//! #### Xtensa architecture
//! For ESP microcontrollers using the `Xtensa` architecture, the driver
//! provides access to the `SENS` peripheral, allowing users to split it into
//! independent parts using the [`SensExt`] trait. This extension trait provides
//! access to the following analog peripherals:
//! * ADC1
//! * ADC2
//! * DAC1
//! * DAC2
//!
//! #### RISC-V architecture
//! For ESP microcontrollers using the `RISC-V` architecture, the driver
//! provides access to the `APB_SARADC` peripheral. The `SarAdcExt` trait allows
//! users to split this peripheral into independent parts, providing access to
//! the following analog peripheral:
//! * ADC1
//! * ADC2
//!
//! ## Examples
//! #### ADC on Risc-V architecture
//! ```no_run
//! // Create ADC instances
//! let analog = peripherals.APB_SARADC.split();
//!
//! let mut adc1_config = AdcConfig::new();
//!
//! let mut pin = adc1_config.enable_pin(io.pins.gpio2.into_analog(), Attenuation::Attenuation11dB);
//!
//! let mut adc1 = ADC::<ADC1>::adc(
//! &mut system.peripheral_clock_control,
//! analog.adc1,
//! adc1_config,
//! )
//! .unwrap();
//!
//! let mut delay = Delay::new(&clocks);
//!
//! loop {
//! let pin_value: u16 = nb::block!(adc1.read(&mut pin)).unwrap();
//! println!("PIN2 ADC reading = {}", pin_value);
//! delay.delay_ms(1500u32);
//! }
//! ```
//! #### ADC on Xtensa architecture
//! ```no_run
//! // Create ADC instances
//! let analog = peripherals.SENS.split();
//!
//! let mut adc1_config = AdcConfig::new();
//!
//! let mut pin3 =
//! adc1_config.enable_pin(io.pins.gpio3.into_analog(), Attenuation::Attenuation11dB);
//!
//! let mut adc1 = ADC::<ADC1>::adc(analog.adc1, adc1_config).unwrap();
//!
//! let mut delay = Delay::new(&clocks);
//!
//! loop {
//! let pin3_value: u16 = nb::block!(adc1.read(&mut pin3)).unwrap();
//! println!("PIN3 ADC reading = {}", pin3_value);
//! delay.delay_ms(1500u32);
//! }
//! ```
#[cfg_attr(esp32, path = "adc/esp32.rs")]
#[cfg_attr(riscv, path = "adc/riscv.rs")]
#[cfg_attr(any(esp32s2, esp32s3), path = "adc/xtensa.rs")]

View File

@ -1,4 +1,10 @@
//! Debug Assistant
//! # Debug Assistant
//!
//! ## Overview
//! The Assist Debug driver provides functionality for debugging and monitoring
//! features on ESP chips. It includes capabilities such as monitoring stack
//! pointer (SP), monitoring memory regions, and handling interrupts related to
//! debugging.
//!
//! Debug Assistant is an auxiliary module that features a set of functions to
//! help locate bugs and issues during software debugging.
@ -8,9 +14,7 @@
//! (e.g. _Saved PC:0x42002ff2_). Make sure the reset was triggered by a TIMG
//! watchdog. Not an RTC or SWD watchdog.
//!
//! Not all targets support all the features.
//!
//! Bus write access logging is not available via this API.
//! ⚠️ Bus write access logging is not available via this API. ⚠️
use crate::{
peripheral::{Peripheral, PeripheralRef},

View File

@ -1,4 +1,53 @@
//! # Clock Control
//!
//! ## Overview
//! This `Clock` driver provides an interface for configuring and managing
//! various clocks present on the `ESP` microcontrollers.
//!
//! Proper clock configuration is essential for the correct functioning of the
//! microcontroller and its peripherals.
//!
//! The `Clock` driver supports configuring multiple clocks, including:
//! * CPU clock
//! * APB (Advanced Peripheral Bus) clock
//! * XTAL clock
//! * PLL clock
//!
//! and other specific clocks based on the ESP microcontroller's architecture.
//!
//! The `CPU clock` is responsible for defining the speed at which the central
//! processing unit (CPU) operates. This driver provides predefined options for
//! different CPU clock speeds, such
//! * 80 MHz
//! * 96 MHz
//! * 120 MHz
//! * 160 MHz
//! * 240 MHz
//!
//! and others, depending on the microcontroller model.
//!
//! #### Clock Control
//! The `ClockControl` struct allows users to configure the desired clock
//! frequencies before applying them. It offers flexibility in selecting
//! appropriate clock frequencies based on specific application requirements.
//!
//! #### Frozen clock frequencies
//! Once the clock configuration is applied using the `freeze` function of the
//! ClockControl struct, the clock frequencies become `frozen` and cannot be
//! changed. The `Clocks` struct is returned after freezing, providing read-only
//! access to the configured clock frequencies.
//!
//! ## Examples
//!
//! #### Initialize with default clock frequency for this chip
//! ```no_run
//! let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
//! ```
//!
//! #### Initialize with custom clock frequency
//! ```no_run
//! let clocks = ClockControl::configure(system.clock_control, CpuClock::Clock160MHz).freeze();
//! ```
use fugit::HertzU32;
use crate::{

View File

@ -1,10 +1,23 @@
//! Delay driver implement the blocking [DelayMs] and [DelayUs] traits from
//! [embedded-hal].
//! # Delay driver
//!
//! ## Overview
//! The Delay driver provides blocking delay functionalities using the
//! `SYSTIMER` peripheral for RISC-V devices and the built-in Xtensa timer for
//! Xtensa devices. This module implements the blocking [DelayMs] and [DelayUs]
//! traits from [embedded-hal].
//!
//! The delays are implemented in a "best-effort" way, meaning that the CPU will
//! block for at least the amount of time specified, but accuracy can be
//! affected by many factors, including interrupt usage.
//!
//! ## Example
//! ```no_run
//! let mut clocks = ClockControl::boot_defaults(system.clock_control).freeze();
//! let mut delay = Delay::new(&clocks);
//!
//! delay.delay_ms(1000 as u32);
//! ```
//!
//! [DelayMs]: embedded_hal::blocking::delay::DelayMs
//! [DelayUs]: embedded_hal::blocking::delay::DelayUs
//! [embedded-hal]: https://docs.rs/embedded-hal/latest/embedded_hal/

View File

@ -1,4 +1,25 @@
//! Direct Memory Access
//! # Direct Memory Access
//!
//! ## Overview
//! The GDMA (General DMA) module is a part of the DMA (Direct Memory Access)
//! driver for ESP chips. Of the Espressif chip range, every chip except of
//! `ESP32` and `ESP32-S2` uses the `GDMA` type of direct memory access.
//!
//! DMA is a hardware feature that allows data transfer between memory and
//! peripherals without involving the CPU, resulting in efficient data movement
//! and reduced CPU overhead. The `GDMA` module provides multiple DMA channels,
//! each capable of managing data transfer for various peripherals.
//!
//! This module implements DMA channels, such as `channel0`, `channel1` and so
//! on. Each channel struct implements the `ChannelTypes` trait, which provides
//! associated types for peripheral configuration.
//!
//! GDMA peripheral can be initializes using the `new` function, which requires
//! a DMA peripheral instance and a clock control reference. ```no_run
//! let dma = Gdma::new(peripherals.DMA, &mut system.peripheral_clock_control);
//! ```
//!
//! <em>PS: Note that the number of DMA channels is chip-specific.</em>
use crate::{
dma::*,

View File

@ -1,7 +1,72 @@
//! Direct Memory Access Commons
//! # Direct Memory Access Commons
//!
//! Descriptors should be sized as `((BUFFERSIZE + 4091) / 4092) * 3`. I.e., to
//! transfer buffers of size `1..=4092`, you need 3 descriptors.
//! ## Overview
//! The `DMA` driver provides an interface to efficiently transfer data between
//! different memory regions within the ESP microcontroller without involving
//! the CPU. The `Direct Memory Access` (DMA) controller is a hardware
//! block responsible for managing these data transfers.
//!
//! The driver is organized into several components and traits, each responsible
//! for handling specific functionalities of the `DMA` controller. Below is an
//! overview of the main components and their functionalities:
//! * `Tx` and `Rx` traits:
//! - These traits define the behaviors and functionalities required for
//! DMA transmit and receive operations.<br> The `Tx` trait includes
//! functions to start, stop, and check the completion status of an
//! outbound DMA transfer.<br> On the other hand, the Rx trait provides
//! similar functionalities for inbound DMA transfers.
//! * `DmaTransfer` and `DmaTransferRxTx` traits:
//! - The `DmaTransfer` trait and `DmaTransferRxTx` trait are used for
//! in-progress DMA transfers.<br> They allow waiting for the transfer to
//! complete and checking its status. Additionally, the `DmaTransferRxTx`
//! trait extends the functionalities to support both receive and
//! transmit operations in a single trait.
//! * `RegisterAccess` trait:
//! - This trait defines a set of methods that allow low-level access to
//! the DMA controller's registers.<br> It provides functions to
//! initialize DMA channels, configure burst mode, priority, and
//! peripheral for both input and output data transfers.<br>Additionally,
//! it supports clearing interrupts, resetting channels, setting
//! descriptor addresses, and checking for descriptor errors.
//!
//! Notice, that this module is a common version of the DMA driver, `ESP32` and
//! `ESP32-S2` are using older `PDMA` controller, whenever other chips are using
//! newer `GDMA` controller.
//!
//! ## Example
//! #### Initialize and utilize DMA controller in `SPI`
//! ```no_run
//! let dma = Gdma::new(peripherals.DMA, &mut system.peripheral_clock_control);
//! let dma_channel = dma.channel0;
//!
//! // For `ESP32` and `ESP32-S2` chips use `Pdma` controller instead:
//! // let dma = Dma::new(system.dma, &mut system.peripheral_clock_control);
//! // let dma_channel = dma.spi2channel;
//!
//! let mut descriptors = [0u32; 8 * 3];
//! let mut rx_descriptors = [0u32; 8 * 3];
//!
//! let mut spi = Spi::new(
//! peripherals.SPI2,
//! sclk,
//! mosi,
//! miso,
//! cs,
//! 100u32.kHz(),
//! SpiMode::Mode0,
//! &mut system.peripheral_clock_control,
//! &clocks,
//! )
//! .with_dma(dma_channel.configure(
//! false,
//! &mut descriptors,
//! &mut rx_descriptors,
//! DmaPriority::Priority0,
//! ));
//! ```
//!
//! ⚠️ Note: Descriptors should be sized as `((BUFFERSIZE + 4091) / 4092) * 3`.
//! I.e., to transfer buffers of size `1..=4092`, you need 3 descriptors.
use core::{marker::PhantomData, sync::atomic::compiler_fence};
@ -308,6 +373,7 @@ where
fn waker() -> &'static embassy_sync::waitqueue::AtomicWaker;
}
// DMA receive channel
pub struct ChannelRx<'a, T, R>
where
T: RxChannel<R>,
@ -607,6 +673,7 @@ where
fn waker() -> &'static embassy_sync::waitqueue::AtomicWaker;
}
/// DMA transmit channel
pub struct ChannelTx<'a, T, R>
where
T: TxChannel<R>,

View File

@ -1,4 +1,20 @@
//! Direct Memory Access
//! # Direct Memory Access
//!
//! ## Overview
//! The `pdma` module is part of the DMA (Direct Memory Access) driver designed
//! for ESP chips. Of the Espressif chip range, only `ESP32` and `ESP32-S2` use
//! the `PDMA` type of direct memory access.
//!
//! This module provides efficient direct data transfer capabilities between
//! peripherals and memory without involving the CPU. It enables bidirectional
//! data transfers through DMA channels, making it particularly useful for
//! high-speed data transfers, such as [SPI] and
//! [I2S] communication.
//!
//!
//!
//! [SPI]: ../spi/index.html
//! [I2S]: ../i2s/index.html
use crate::{
dma::*,

View File

@ -1,3 +1,72 @@
//! # Embassy driver
//!
//! ## Overview
//! The `embassy` driver for ESP chips is an essential part of the Embassy
//! embedded async/await runtime and is used by applications to perform
//! time-based operations and schedule asynchronous tasks. It provides a
//! high-level API for handling timers and alarms, abstracting the underlying
//! hardware details, and allowing users to focus on application logic rather
//! than low-level timer management.
//!
//! Here are important details about the module:
//! * `time_driver` module (`time_driver_systimer` or `time_driver_timg`,
//! depends on enabled feature)
//! - This module contains the implementations of the timer drivers for
//! different ESP chips.<br> It includes the `EmbassyTimer` struct, which
//! is responsible for handling alarms and timer events.
//! - `EmbassyTimer` struct represents timer driver for ESP chips. It
//! contains `alarms` - an array of `AlarmState` structs, which describe
//! the state of alarms associated with the timer driver.
//! * `AlarmState` struct
//! - This struct represents the state of an alarm. It contains information
//! about the alarm's timestamp, a callback function to be executed when
//! the alarm triggers, and a context pointer for passing user-defined
//! data to the callback.
//!
//! ## Example
//! The following example demonstrates how to use the `embassy` driver to
//! schedule asynchronous tasks.<br> In this example, we use the `embassy`
//! driver to wait for a GPIO 9 pin state to change. ```no_run
//! #[cfg(feature = "embassy-time-systick")]
//! embassy::init(
//! &clocks,
//! esp32c6_hal::systimer::SystemTimer::new(peripherals.SYSTIMER),
//! );
//!
//! #[cfg(feature = "embassy-time-timg0")]
//! embassy::init(&clocks, timer_group0.timer0);
//!
//! let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
//! // GPIO 9 as input
//! let input = io.pins.gpio9.into_pull_down_input();
//!
//! // Async requires the GPIO interrupt to wake futures
//! esp32c6_hal::interrupt::enable(
//! esp32c6_hal::peripherals::Interrupt::GPIO,
//! esp32c6_hal::interrupt::Priority::Priority1,
//! )
//! .unwrap();
//!
//! let executor = EXECUTOR.init(Executor::new());
//! executor.run(|spawner| {
//! spawner.spawn(ping(input)).ok();
//! });
//! ```
//!
//! Where `ping` defined as:
//! ```no_run
//! async fn ping(mut pin: Gpio9<Input<PullDown>>) {
//! loop {
//! esp_println::println!("Waiting...");
//! pin.wait_for_rising_edge().await.unwrap();
//! esp_println::println!("Ping!");
//! Timer::after(Duration::from_millis(100)).await;
//! }
//! }
//! ```
//! For more embassy-related examples check out the [examples repo](https://github.com/esp-rs/esp-hal/tree/main/esp32-hal/examples)
//! for a corresponding board.
use core::{cell::Cell, ptr};
use embassy_time::driver::{AlarmHandle, Driver};

View File

@ -1,12 +1,26 @@
//! General Purpose I/Os
//! # General Purpose I/Os
//!
//! ## Overview
//! The GPIO peripheral provides access to General Purpose Input/Output pins on
//! ESP chips.
//!
//! This driver supports various operations on GPIO pins, including setting the
//! pin mode, direction, and manipulating the pin state (setting high/low,
//! toggling). It provides an interface to interact with GPIO pins on ESP chips,
//! allowing developers to control and read the state of the pins. This module
//! also implements a number of traits from [embedded-hal] to provide a common
//! interface for GPIO pins.
//!
//! To get access to the pins, you first need to convert them into a HAL
//! designed struct from the pac struct `GPIO` and `IO_MUX` using `IO::new`.
//!
//! ## Example
//! ```no_run
//! let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
//! let mut led = io.pins.gpio5.into_push_pull_output();
//! ```
//!
//! [embedded-hal]: https://docs.rs/embedded-hal/latest/embedded_hal/
use core::{convert::Infallible, marker::PhantomData};

View File

@ -1,6 +1,37 @@
//! I2C Driver
//! # I2C Driver
//!
//! Supports multiple I2C peripheral instances
//! ## Overview
//! The I2C Peripheral Driver for ESP chips is a software module that
//! facilitates communication with I2C devices using ESP microcontroller chips.
//! It provides an interface to initialize, configure, and perform read and
//! write operations over the I2C bus.
//!
//! The driver supports features such as handling transmission errors,
//! asynchronous operations, and interrupt-based communication, also supports
//! multiple I2C peripheral instances on `ESP32`, `ESP32H2`, `ESP32S2`, and
//! `ESP32S3` chips
//!
//! ## Example
//! Following code shows how to read data from a BMP180 sensor using I2C.
//!
//! ```no_run
//! // Create a new peripheral object with the described wiring
//! // and standard I2C clock speed
//! let mut i2c = I2C::new(
//! peripherals.I2C0,
//! io.pins.gpio1,
//! io.pins.gpio2,
//! 100u32.kHz(),
//! &mut system.peripheral_clock_control,
//! &clocks,
//! );
//! loop {
//! let mut data = [0u8; 22];
//! i2c.write_read(0x77, &[0xaa], &mut data).ok();
//!
//! println!("{:02x?}", data);
//! }
//! ```
use fugit::HertzU32;

View File

@ -1,4 +1,70 @@
//! I2S Master
//! # I2S Master
//!
//! ## Overview
//!
//! The I2S Master peripheral driver provides support for the I2S (Inter-IC
//! Sound) Master functionality on ESP chips. It enables audio data transmission
//! and reception with external audio devices, such as DACs (Digital-to-Analog
//! Converters) and ADCs (Analog-to-Digital Converters) through the I2S
//! interface. Also this module supports different data formats, including
//! varying data and channel widths, different standards, such as the Philips
//! standard and configurable pin mappings for I2S clock (BCLK), word select
//! (WS), and data input/output (DOUT/DIN).
//!
//! The driver uses DMA (Direct Memory Access) for efficient data transfer and
//! supports various configurations, such as different data formats, standards
//! (e.g., Philips) and pin configurations. It relies on other peripheral
//! modules, such as
//! - `GPIO`
//! - `DMA`
//! - `system` (to configure and enable the I2S peripheral)
//!
//! ## Examples
//!
//! ### initialization
//! ```no_run
//! let i2s = I2s::new(
//! peripherals.I2S0,
//! MclkPin::new(io.pins.gpio4),
//! Standard::Philips,
//! DataFormat::Data16Channel16,
//! 44100u32.Hz(),
//! dma_channel.configure(
//! false,
//! &mut tx_descriptors,
//! &mut rx_descriptors,
//! DmaPriority::Priority0,
//! ),
//! &mut system.peripheral_clock_control,
//! &clocks,
//! );
//! ```
//!
//! ### Reading
//! ```no_run
//! let i2s_rx = i2s.i2s_rx.with_pins(PinsBclkWsDin::new(
//! io.pins.gpio1,
//! io.pins.gpio2,
//! io.pins.gpio5,
//! ));
//!
//! // Creating DMA buffer
//! static mut BUFFER: [u8; 4092 * 4] = [0u8; 4092 * 4];
//! let buffer: &'static mut [u8; 4092 * 4] = unsafe { &mut BUFFER };
//!
//! let mut transfer = i2s_rx.read_dma_circular(buffer).unwrap();
//! println!("Started transfer");
//!
//! loop {
//! let avail = transfer.available();
//!
//! if avail > 0 {
//! let mut rcv = [0u8; 5000];
//! transfer.pop(&mut rcv[..avail]).unwrap();
//! println!("Received {:x?}...", &rcv[..30]);
//! }
//! }
//! ```
use embedded_dma::{ReadBuffer, WriteBuffer};
use private::*;

View File

@ -1,4 +1,56 @@
//! Interrupt support
//! # Interrupt support
//!
//! ## Overview
//! The `interrupt` driver is a crucial module for ESP chips. Its primary
//! purpose is to manage and handle interrupts, which are asynchronous events
//! requiring immediate attention from the CPU. Interrupts are essential in
//! various applications, such as real-time tasks, I/O communications, and
//! handling external events like hardware signals.
//!
//! The core functionality of the `interrupt` driver revolves around the
//! management of interrupts. When an interrupt occurs, it temporarily stops the
//! ongoing CPU operations, saves its current state, and starts executing the
//! corresponding interrupt service routine (ISR). The interrupt service routine
//! is a user-defined function that performs the necessary actions to handle the
//! specific interrupt. Once the ISR is executed, the driver restores the saved
//! CPU state and resumes normal program execution.
//!
//! In scenarios where multiple interrupts may occur simultaneously, the
//! interrupt driver determines the `priority` of each interrupt. This
//! prioritization ensures that critical or high-priority tasks are handled
//! first. It helps prevent delays in time-sensitive applications and allows the
//! system to allocate resources efficiently. This functionality is provided and
//! implemented by the `priority` enum.
//!
//!
//! ## Example
//! ```no_run
//! #[entry]
//! fn main() -> ! {
//! ...
//! critical_section::with(|cs| SWINT.borrow_ref_mut(cs).replace(sw_int));
//!
//! interrupt::enable(
//! peripherals::Interrupt::FROM_CPU_INTR0,
//! interrupt::Priority::Priority1,
//! )
//! .unwrap();
//!
//! loop {}
//! }
//!
//! #[interrupt]
//! fn FROM_CPU_INTR0() {
//! esp_println::println!("SW interrupt0");
//! critical_section::with(|cs| {
//! SWINT
//! .borrow_ref_mut(cs)
//! .as_mut()
//! .unwrap()
//! .reset(SoftwareInterrupt::SoftwareInterrupt0);
//! });
//! }
//! ```
#[cfg(riscv)]
pub use riscv::*;

View File

@ -1,4 +1,4 @@
//! Interrupt handling - RISCV
//! Interrupt handling - RISC-V
//!
//! When the `vectored` feature is enabled, CPU interrupts 1 through 15 are
//! reserved for each of the possible interrupt priorities.

View File

@ -1,3 +1,14 @@
//! # LEDC channel
//!
//! ## Overview
//! The `LEDC Channel` module is a part of the `LED Controller (LEDC)` driver
//! designed for ESP microcontrollers. It provides a high-level interface to
//! configure and control individual PWM channels of the LEDC peripheral.
//!
//! The module allows precise and flexible control over LED lighting and other
//! `Pulse-Width Modulation (PWM)` applications by offering configurable duty
//! cycles and frequencies.
use paste::paste;
#[cfg(esp32)]

View File

@ -1,4 +1,4 @@
//! LEDC (LED PWM Controller) peripheral control
//! # LEDC (LED PWM Controller) peripheral control
//!
//! Currently only supports fixed-frequency output. Interrupts are not currently
//! implemented. High Speed channels are available for the ESP32 only, while Low
@ -9,18 +9,22 @@
//! The following will configure the Low Speed Channel0 to 24kHz output with
//! 10% duty using the ABPClock
//!
//! ```rust,ignore
//! let mut ledc = LEDC::new(peripherals.LEDC, &clock_control, &mut system.peripheral_clock_control);
//! ```no_run
//! let mut ledc = LEDC::new(
//! peripherals.LEDC,
//! &clock_control,
//! &mut system.peripheral_clock_control,
//! );
//! ledc.set_global_slow_clock(LSGlobalClkSource::APBClk);
//!
//! let mut lstimer0 = ledc.get_timer::<LowSpeed>(timer::Number::Timer0);
//! lstimer0
//! .configure(timer::config::Config {
//! duty: timer::config::Duty::Duty5Bit,
//! clock_source: timer::LSClockSource::APBClk,
//! frequency: 24u32.kHz(),
//! })
//! .unwrap();
//! .configure(timer::config::Config {
//! duty: timer::config::Duty::Duty5Bit,
//! clock_source: timer::LSClockSource::APBClk,
//! frequency: 24u32.kHz(),
//! })
//! .unwrap();
//!
//! let mut channel0 = ledc.get_channel(channel::Number::Channel0, led);
//! channel0
@ -36,17 +40,21 @@
//! The following will configure the High Speed Channel0 to 24kHz output with
//! 10% duty using the ABPClock
//!
//! ```rust,ignore
//! let ledc = LEDC::new(peripherals.LEDC, &clock_control, &mut system.peripheral_clock_control);
//! ```no_run
//! let ledc = LEDC::new(
//! peripherals.LEDC,
//! &clock_control,
//! &mut system.peripheral_clock_control,
//! );
//!
//! let mut hstimer0 = ledc.get_timer::<HighSpeed>(timer::Number::Timer0);
//! hstimer0
//! .configure(timer::config::Config {
//! duty: timer::config::Duty::Duty5Bit,
//! clock_source: timer::HSClockSource::APBClk,
//! frequency: 24u32.kHz(),
//! })
//! .unwrap();
//! .configure(timer::config::Config {
//! duty: timer::config::Duty::Duty5Bit,
//! clock_source: timer::HSClockSource::APBClk,
//! frequency: 24u32.kHz(),
//! })
//! .unwrap();
//!
//! let mut channel0 = ledc.get_channel(channel::Number::Channel0, led);
//! channel0

View File

@ -1,3 +1,14 @@
//! # LEDC timer
//!
//! ## Overview
//! The `LEDC Timer` module is a part of the `LED Controller (LEDC)` driver
//! designed for ESP microcontrollers. It provides a high-level interface to
//! configure and control individual timers of the `LEDC` peripheral.
//!
//! The module allows precise and flexible control over timer configurations,
//! duty cycles and frequencies, making it ideal for Pulse-Width Modulation
//! (PWM) applications and LED lighting control.
use fugit::HertzU32;
#[cfg(esp32)]

View File

@ -1,6 +1,7 @@
//! MCPWM (Motor Control Pulse Width Modulator) peripheral
//! # MCPWM (Motor Control Pulse Width Modulator) peripheral
//!
//! # Peripheral capabilities:
//! ## Overview
//! #### Peripheral capabilities
//! * PWM Timers 0, 1 and 2
//! * Every PWM timer has a dedicated 8-bit clock prescaler.
//! * The 16-bit counter in the PWM timer can work in count-up mode,
@ -22,11 +23,11 @@
//! * Fault Detection Module (Not yet implemented)
//! * Capture Module (Not yet implemented)
//!
//! # Example
//! ## Example
//! Uses timer0 and operator0 of the MCPWM0 peripheral to output a 50% duty
//! signal at 20 kHz. The signal will be output to the pin assigned to `pin`.
//!
//! ```
//! ```no_run
//! # use esp_hal_common::{mcpwm, prelude::*};
//! use mcpwm::{operator::PwmPinConfig, timer::PwmWorkingMode, PeripheralClockConfig, MCPWM};
//!

View File

@ -1,3 +1,15 @@
//! # MCPWM peripheral - operator module
//!
//! ## Overview
//! The `operator` module is part of the `MCPWM` peripheral driver for
//! `ESP` chips. It is responsible for
//! generating `PWM (Pulse Width Modulation)` signals and handling various
//! aspects related to `PWM` signal generation.
//!
//! This module provides flexibility in configuring the PWM outputs. Its
//! implementation allows for motor control and other applications that demand
//! accurate pulse timing and sophisticated modulation techniques.
use core::marker::PhantomData;
use crate::{

View File

@ -1,3 +1,11 @@
//! # MCPWM peripheral - timer module
//!
//! ## Overview
//! The `timer` module is a part of the `MCPWM (Motor Control Pulse Width
//! Modulator)` driver for ESP chips. It provides an interface to configure and
//! use timers for generating `PWM` signals used in motor control and other
//! applications.
use core::marker::PhantomData;
use fugit::HertzU32;
@ -27,7 +35,7 @@ impl<const TIM: u8, PWM: PwmPeripheral> Timer<TIM, PWM> {
/// Apply the given timer configuration.
///
/// ### Note:
/// The prescalar and period configuration will be applied immediately and
/// The prescaler and period configuration will be applied immediately and
/// before setting the [`PwmWorkingMode`].
/// If the timer is already running you might want to call [`Timer::stop`]
/// and/or [`Timer::set_counter`] first

View File

@ -1,4 +1,30 @@
//! USB OTG full-speed peripheral
//! # USB OTG full-speed peripheral
//!
//! ## Overview
//! The USB OTG Full-speed peripheral driver provides support for the USB
//! On-The-Go (OTG) full-speed functionality on ESP chips, allows communication
//! with USB devices.
//!
//! The driver uses the `esp_synopsys_usb_otg` crate, which provides the `USB
//! bus` implementation and `USB peripheral traits`. It also relies on other
//! peripheral modules, such as `GPIO`, `system`, and `clock control`, to
//! configure and enable the `USB` peripheral.
//!
//! To use the USB OTG Full-speed peripheral driver, you need to initialize the
//! peripheral and configure its settings. The USB struct represents the USB
//! peripheral and requires the implementation of the `UsbSel`, `UsbDp`, and
//! `UsbDm` traits, which define the specific types used for USB pin selection
//! and data pins.
//!
//! The USB struct provides a `new` function for initialization.
//! Inside the `new` function, the `into_ref!` macro is used to convert the
//! peripheral references into `PeripheralRef` instances.
//!
//! The `USB` struct implements the `UsbPeripheral` trait from the
//! `esp_synopsys_usb_otg` crate, which defines the required constants and
//! functions for `USB peripheral` operation. The trait implementation includes
//! enabling the `USB peripheral`, configuring the `USB` settings and connecting
//! the appropriate `GPIO` pins to the `USB peripheral`.
pub use esp_synopsys_usb_otg::UsbBus;
use esp_synopsys_usb_otg::UsbPeripheral;

View File

@ -1,3 +1,13 @@
//! # PCNT - channel configuration
//!
//! ## Overview
//! The `channel` module is part of the `PCNT` peripheral driver
//! for `ESP` chips.
//!
//! It provides a convenient and efficient way to configure and use
//! individual channels of the `PCNT` peripheral of pulse counting and signal
//! edge detection on ESP chips.
use super::unit;
use crate::{
gpio::{InputPin, InputSignal, ONE_INPUT, ZERO_INPUT},

View File

@ -1,4 +1,136 @@
//! Pulse Counter peripheral driver
//! # Pulse Counter peripheral driver
//!
//! ## Overview
//! The `PCNT (Pulse Counter)` driver for `ESP` chips is a software component
//! that provides an interface for controlling and utilizing the `PCNT`
//! peripheral. The `PCNT` peripheral is a hardware module available in `ESP`
//! chips, which functions as a pulse counter and encoder. It is capable of
//! counting pulses and monitoring changes in signal levels from external
//! sources.
//!
//! The `PCNT` driver is designed to offer convenient and efficient access to
//! the functionalities of the `PCNT` peripheral. It consists of two main
//! modules:
//! * [channel]
//! * [unit]
//!
//! The `channel` module allows users to configure and manage individual
//! channels of the `PCNT` peripheral. It provides methods to set various
//! parameters for each channel, such as control modes for signal edges, action
//! on control level, and configurations for positive and negative edge count
//! modes.
//!
//! The `unit` module is responsible for configuring and handling individual
//! units of the `PCNT` peripheral. Each unit represents a separate instance of
//! the `PCNT` module, identified by unit numbers like `Unit0`, `Unit1`, and so
//! on. Users can interact with these units to configure settings such as low
//! and high limits, thresholds, and optional filtering. The unit module also
//! enables users to pause, resume, and clear the counter, as well as enable or
//! disable interrupts for specific events associated with the unit.
//!
//! ## Example
//! ```no_run
//! let unit_number = unit::Number::Unit1;
//!
//! // setup a pulse couter
//! println!("setup pulse counter unit 0");
//! let pcnt = PCNT::new(peripherals.PCNT, &mut system.peripheral_clock_control);
//! let mut u0 = pcnt.get_unit(unit_number);
//! u0.configure(unit::Config {
//! low_limit: -100,
//! high_limit: 100,
//! filter: Some(min(10u16 * 80, 1023u16)),
//! ..Default::default()
//! })
//! .unwrap();
//!
//! println!("setup channel 0");
//! let mut ch0 = u0.get_channel(channel::Number::Channel0);
//! let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
//! let mut pin_a = io.pins.gpio5.into_pull_up_input();
//! let mut pin_b = io.pins.gpio6.into_pull_up_input();
//!
//! ch0.configure(
//! PcntSource::from_pin(&mut pin_a),
//! PcntSource::from_pin(&mut pin_b),
//! channel::Config {
//! lctrl_mode: channel::CtrlMode::Reverse,
//! hctrl_mode: channel::CtrlMode::Keep,
//! pos_edge: channel::EdgeMode::Decrement,
//! neg_edge: channel::EdgeMode::Increment,
//! invert_ctrl: false,
//! invert_sig: false,
//! },
//! );
//!
//! println!("setup channel 1");
//! let mut ch1 = u0.get_channel(channel::Number::Channel1);
//! ch1.configure(
//! PcntSource::from_pin(&mut pin_b),
//! PcntSource::from_pin(&mut pin_a),
//! channel::Config {
//! lctrl_mode: channel::CtrlMode::Reverse,
//! hctrl_mode: channel::CtrlMode::Keep,
//! pos_edge: channel::EdgeMode::Increment,
//! neg_edge: channel::EdgeMode::Decrement,
//! invert_ctrl: false,
//! invert_sig: false,
//! },
//! );
//! println!("subscribing to events");
//! u0.events(unit::Events {
//! low_limit: true,
//! high_limit: true,
//! thresh0: false,
//! thresh1: false,
//! zero: false,
//! });
//!
//! println!("enabling interrupts");
//! u0.listen();
//! println!("resume pulse counter unit 0");
//! u0.resume();
//!
//! critical_section::with(|cs| UNIT0.borrow_ref_mut(cs).replace(u0));
//!
//! interrupt::enable(peripherals::Interrupt::PCNT, interrupt::Priority::Priority2).unwrap();
//!
//! let mut last_value: i32 = 0;
//! loop {
//! critical_section::with(|cs| {
//! let mut u0 = UNIT0.borrow_ref_mut(cs);
//! let u0 = u0.as_mut().unwrap();
//! let value: i32 = u0.get_value() as i32 + VALUE.load(Ordering::SeqCst);
//! if value != last_value {
//! println!("value: {value}");
//! last_value = value;
//! }
//! });
//! }
//! ```
//!
//! Where the `PCNT` interrupt handler is defined as:
//! ```no_run
//! #[interrupt]
//! fn PCNT() {
//! critical_section::with(|cs| {
//! let mut u0 = UNIT0.borrow_ref_mut(cs);
//! let u0 = u0.as_mut().unwrap();
//! if u0.interrupt_set() {
//! let events = u0.get_events();
//! if events.high_limit {
//! VALUE.fetch_add(100, Ordering::SeqCst);
//! } else if events.low_limit {
//! VALUE.fetch_add(-100, Ordering::SeqCst);
//! }
//! u0.reset_interrupt();
//! }
//! });
//! }
//! ```
//!
//! [channel]: channel/index.html
//! [unit]: unit/index.html
use self::unit::Unit;
use crate::{

View File

@ -1,3 +1,15 @@
//! # PCNT - Unit module
//!
//! ## Overview
//! The `unit` module is a part of the `PCNT` peripheral driver
//! for ESP chips. It offers functionalities for configuring and utilizing
//! specific units of the PCNT peripheral.
//!
//! Each unit is identified by a unit number, such as `Unit0`, `Unit1`, `Unit2`,
//! and so on. This module provides methods to configure a unit with specific
//! settings, like low and high limits, thresholds, and optional filtering.
//! Users can easily configure these units based on their requirements.
use critical_section::CriticalSection;
use super::channel;

View File

@ -1,4 +1,39 @@
//! Exclusive peripheral access
//! # Exclusive peripheral access
//!
//! ## Overview
//! The Peripheral module provides an exclusive access mechanism to peripherals
//! on ESP chips. It includes the `PeripheralRef` struct, which represents an
//! exclusive reference to a peripheral. It offers memory efficiency benefits
//! for zero-sized types.
//!
//! The `PeripheralRef` struct is used to access and interact with peripherals.
//! It implements the `Deref` and `DerefMut` traits, allowing you to dereference
//! it to access the underlying peripheral. It also provides methods for cloning
//! and re-borrowing the peripheral.
//!
//! The module also defines the `Peripheral` trait, which is implemented by
//! types that can be used as peripherals. The trait allows conversion between
//! owned and borrowed peripherals and provides an unsafe method for cloning the
//! peripheral. By implementing this trait, a type can be used with the
//! `PeripheralRef` struct.
//!
//! The module also includes a `peripheral_macros` module, which contains macros
//! for generating peripheral structs and associated traits based on
//! configuration options.
//!
//! ## Examples
//!
//! ### Initialization
//! ```no_run
//! let peripherals = Peripherals::take();
//! ```
//! ### Accessing peripherals
//! ```no_run
//! let mut rtc = Rtc::new(peripherals.RTC_CNTL);
//! ```
//! ```no_run
//! let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
//! ```
use core::{
marker::PhantomData,

View File

@ -1,5 +1,18 @@
//! Wireless communication peripheral implementations
//! # Wireless communication peripheral implementations
//!
//! ## Overview
//! The radio module provides implementations for different wireless
//! communication peripherals, including WiFi, Bluetooth and
//! IEEE 802.15.4 Low Rate wireless personal area radio.
//!
//! In addition to the structures defined in this module, the module also
//! defines the `RadioExt` trait, which provides a `split` method. This method
//! allows splitting the general `Radio` peripheral into its individual
//! components.
//!
//! Additionally, the module includes implementation blocks for each wireless
//! communication peripheral, providing necessary functions and traits for each
//! peripheral.
pub trait RadioExt {
type Components;

View File

@ -1,4 +1,32 @@
//! Hardware and Software Reset
//! # Hardware and Software Reset
//!
//! ## Overview
//! The Hardware and Software Reset module provides functions for performing
//! hardware and software resets on ESP chips. It also includes functions for
//! retrieving the reset reason and the wakeup cause after a reset.
//!
//! The module defines a set of sleep sources (`SleepSource`) that indicate the
//! source of the wakeup event. These sources include:
//! - external signals
//! - timers
//! - touchpads
//! - ULP programs
//! - GPIOs
//! - UART
//! - Wi-Fi
//! - COCPU interrupts
//! - BT (Bluetooth)
//!
//! The module also includes a set of flags (`WakeupReason`) that represent
//! different wakeup sources and enable/disable wakeup triggers for specific
//! events such as:
//! - GPIO
//! - timers
//! - UART
//! - touch sensors
//! - ULP
//! - Wi-Fi
//! - BT
use crate::rtc_cntl::SocResetReason;
@ -70,17 +98,20 @@ bitflags::bitflags! {
}
}
/// Performs a software reset on the chip.
pub fn software_reset() {
unsafe { crate::rtc_cntl::software_reset() }
}
/// Performs a software reset on the CPU.
pub fn software_reset_cpu() {
unsafe { crate::rtc_cntl::software_reset_cpu() }
}
/// Retrieves the reason for the last reset as a SocResetReason enum value.
/// Returns `None` if the reset reason cannot be determined.
pub fn get_reset_reason() -> Option<SocResetReason> {
crate::rtc_cntl::get_reset_reason(crate::get_core())
}
/// Retrieves the cause of the last wakeup event as a SleepSource enum value.
pub fn get_wakeup_cause() -> SleepSource {
crate::rtc_cntl::get_wakeup_cause()
}

View File

@ -1,5 +1,6 @@
//! # Remote Control Peripheral (RMT)
//!
//! ## Overview
//! Some ESP32 variants include a remote control peripheral (RMT) that
//! is designed to handle infrared remote control signals. For that
//! purpose, it can convert bitstreams of data (from the RAM) into
@ -35,9 +36,9 @@
//! For more information, please refer to the ESP-IDF documentation:
//! <https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/rmt.html>
//!
//! # Examples
//! ## Examples
//!
//! ## Initialization
//! ### Initialization
//!
//! ```no_run
//! let rmt = Rmt::new(peripherals.RMT, 80u32.MHz(), &mut clock_control, &clocks).unwrap();
@ -60,7 +61,7 @@
//! (on ESP32 and ESP32-S2 you cannot specify a base frequency other than 80
//! MHz)
//!
//! ## Sending a pulse sequence
//! ### Sending a pulse sequence
//!
//! ```no_run
//! let data = [

View File

@ -1,5 +1,6 @@
//! Random Number Generator
//! # Random Number Generator
//!
//! ## Overview
//! The Random Number Generator (RNG) Driver for ESP chips is a software module
//! that provides an interface to generate random numbers using the RNG
//! peripheral on ESP chips. This driver allows you to generate random numbers

View File

@ -1,10 +1,11 @@
//! Cyclic Redundancy Check
//! # Cyclic Redundancy Check
//!
//! ## Overview
//! These are safe abstractions to the CRC functions in the ESP32 ROM.
//! Some chips may not include all of these functions so they will be compiled
//! into the program binary in those cases.
//!
//! # Parameters
//! ## Parameters
//!
//! The ROM provides the following polynomials for each CRC width:
//!
@ -31,7 +32,7 @@
//! crc = !crc32_be(crc, &data2); // finish
//! ```
//!
//! # Examples
//! ## Examples
//!
//! A catalogue of these parameters can be found at
//! <https://reveng.sourceforge.io/crc-catalogue/all.htm>

View File

@ -1,6 +1,6 @@
//! MD5 Message-Digest Algorithm
//! # MD5 Message-Digest Algorithm
//!
//! # Security Warning
//! ## ⚠️ Security Warning ⚠️
//!
//! MD5 is a **cryptographically broken** message digest. It should **not**
//! be used for data security, for example, to check if data has been
@ -12,7 +12,7 @@
//! flash. This is especially important on microcontrollers where the
//! computational efficiency of MD5 is desired.
//!
//! # Compatibility
//! ## Compatibility
//!
//! The public API exposed by this module tries to *mimic* the public API
//! offered by the [MD5][1] crate in an effort to act as a drop-in replacement.
@ -24,7 +24,7 @@
//! all of them. Usage of this module may help make program binaries smaller
//! than it would be if you included an MD5 implementation in your project.
//!
//! # Example
//! ## Example
//!
//! To compute a full digest from a single buffer, use the following:
//!

View File

@ -1,7 +1,27 @@
//! ESP ROM libraries
//! # ESP ROM libraries
//!
//! ## Overview
//! The `rom` driver provides functionality related to the ROM (Read-Only
//! Memory) on ESP chips. It includes implementations for the [CRC (Cyclic
//! Redundancy Check)] and [MD5 (Message Digest 5)] algorithms.
//!
//! The driver's functionality allows users to perform CRC calculations and MD5
//! hashing using the ROM functions provided by the ESP chip. This can be useful
//! for various applications that require data integrity checks or cryptographic
//! operations.
//!
//! It uses `CRC` error-checking techniques to detect changes in data during
//! transmission or storage.
//!
//! This module also implements the `MD5` algorithm, which is widely used for
//! cryptographic hash function. It's commonly used to verify data integrity and
//! to check whether the data has been modified.
//!
//! Safe abstractions to the additional libraries provided in the ESP's
//! read-only memory.
//! Read-Only Memory.
//!
//! [CRC (Cyclic Redundancy Check)]: ./crc/index.html
//! [MD5 (Message Digest 5)]: ./md5/index.html
pub mod crc;
pub mod md5;

View File

@ -1,7 +1,39 @@
//! RSA Accelerator support.
//! # RSA Accelerator support.
//!
//! This module provides functions and structs for multi precision arithmetic
//! operations used in RSA asym-metric cipher algorithms
//! ## Overview
//! The `RSA` driver provides a set of functions to accelerate `RSA
//! (RivestShamirAdleman)` cryptographic operations on ESP chips. `RSA` is a
//! widely used `public-key` cryptographic algorithm that involves complex
//! mathematical computations, and the `RSA` accelerator on `ESP` chips is
//! designed to optimize these computations for faster performance.
//!
//! Implementation details;
//! * The driver uses low-level peripheral access to read and write data
//! from/to the `RSA` peripheral.
//! * The driver contains `unsafe` code blocks as it directly manipulates
//! memory addresses for data transfer.
//! * The driver supports different sizes of operands based on the generic
//! types provided during instantiation.
//! * The [nb] crate is used to handle non-blocking operations.
//! * The driver provides a set of high-level abstractions to simplify `RSA`
//! cryptographic operations on `ESP` chips, allowing developers to
//! leverage the `RSA accelerator` for improved performance.
//!
//! ## Examples
//! ### Initialization
//! ```no_run
//! let peripherals = Peripherals::take();
//! let mut system = peripherals.PCR.split();
//!
//! let mut rsa = Rsa::new(peripherals.RSA, &mut system.peripheral_clock_control);
//! ```
//!
//! ⚠️: The examples for RSA peripheral are quite extensive, so for a more
//! detailed study of how to use this driver please visit [the repository
//! with corresponding example].
//!
//! [nb]: https://docs.rs/nb/1.1.0/nb/
//! [the repository with corresponding example]: https://github.com/esp-rs/esp-hal/blob/main/esp32-hal/examples/rsa.rs
use core::{convert::Infallible, marker::PhantomData, ptr::copy_nonoverlapping};

View File

@ -1,4 +1,73 @@
//! Low-power Management
//! # RTC_CNTL (Real-Time Clock Control) and Low-power Management
//!
//! ## Overview
//! The `rtc_cntl` module provides a driver for the `RTC_CNTL` peripheral on ESP
//! chips.
//!
//! The `Real-Time Clock Control (RTC_CNTL)` peripheral is responsible for
//! managing the real-time clock and low-power modes on the chip.
//!
//! The `rtc_cntl` driver module contains functions and data structures to
//! interact with the `RTC_CNTL` peripheral on ESP chips. It also includes the
//! necessary configurations and constants for clock sources and low-power
//! management. The driver provides the following features and functionalities:
//! * Clock Configuration
//! * Calibration
//! * Low-Power Management
//! * Real-Time Clock
//! * Handling Watchdog Timers
//!
//! ## Examples
//! ### Print time in milliseconds from the RTC Timer
//! ```no_run
//! let mut delay = Delay::new(&clocks);
//!
//! loop {
//! esp_println::println!("rtc time in milliseconds is {}", rtc.get_time_ms());
//! delay.delay_ms(1000u32);
//! }
//! ```
//!
//! ### RTC Watchdog Timer
//! ```no_run
//! rtc.rwdt.start(2000u64.millis());
//! rtc.rwdt.listen();
//!
//! interrupt::enable(
//! peripherals::Interrupt::LP_WDT,
//! interrupt::Priority::Priority1,
//! )
//! .unwrap();
//!
//! critical_section::with(|cs| RWDT.borrow_ref_mut(cs).replace(rtc.rwdt));
//!
//! unsafe {
//! riscv::interrupt::enable();
//! }
//!
//! loop {}
//! ```
//!
//! Where the `LP_WDT` interrupt handler is defined as:
//! ```no_run
//! // Handle the corresponding interrupt
//! #[interrupt]
//! fn LP_WDT() {
//! critical_section::with(|cs| {
//! esp_println::println!("RWDT Interrupt");
//!
//! let mut rwdt = RWDT.borrow_ref_mut(cs);
//! let rwdt = rwdt.as_mut().unwrap();
//!
//! rwdt.clear_interrupt();
//!
//! esp_println::println!("Restarting in 5 seconds...");
//!
//! rwdt.start(5000u64.millis());
//! rwdt.unlisten();
//! });
//! }
//! ```
use embedded_hal::watchdog::{Watchdog, WatchdogDisable, WatchdogEnable};
#[cfg(not(any(esp32c6, esp32h2)))]

View File

@ -1,3 +1,24 @@
//! # RTC Control Sleep Module
//!
//! ## Overview
//! The `sleep` module in the `RTC CNTL (Real-Time Clock Control)` driver
//! provides functionality to manage sleep and wakeup sources for `ESP` chips.
//! The `RTC_CNTL` is responsible for controlling the power and sleep behavior
//! of the chip.
//!
//! The `sleep` module allows configuring various wakeup sources and setting up
//! the sleep behavior based on those sources. The supported wakeup sources
//! include:
//! * `GPIO` pins - light sleep only
//! * timers
//! * `SDIO (Secure Digital Input/Output) - light sleep only`
//! * `MAC (Media Access Control)` wake - light sleep only
//! * `UART0` - light sleep only
//! * `UART1` - light sleep only
//! * `touch`
//! * `ULP (Ultra-Low Power)` wake
//! * `BT (Bluetooth) wake` - light sleep only
use core::{cell::RefCell, time::Duration};
use crate::{

View File

@ -1,4 +1,64 @@
//! Secure Hash Algorithm peripheral driver
//! # Secure Hash Algorithm peripheral driver
//!
//! ## Overview
//! This SHA (Secure Hash Algorithm) driver for ESP chips is a software module
//! that provides an interface to interact with the SHA peripheral on ESP
//! microcontroller chips. This driver allows you to perform cryptographic hash
//! operations using various hash algorithms supported by the SHA peripheral,
//! such as:
//! * SHA-1
//! * SHA-224
//! * SHA-256
//! * SHA-384
//! * SHA-512
//!
//! The driver supports two working modes:
//! * Typical SHA
//! * DMA-SHA (Direct Memory Access SHA is NOT implemented yet).
//!
//! It provides functions to update the hash calculation with input data, finish
//! the hash calculation and retrieve the resulting hash value. The SHA
//! peripheral on ESP chips can handle large data streams efficiently, making it
//! suitable for cryptographic applications that require secure hashing.
//!
//! To use the SHA Peripheral Driver, you need to initialize it with the desired
//! SHA mode and the corresponding SHA peripheral. Once initialized, you can
//! update the hash calculation by providing input data, finish the calculation
//! to retrieve the hash value and repeat the process for a new hash calculation
//! if needed.
//!
//! ## Example
//! ```no_run
//! let source_data = "HELLO, ESPRESSIF!".as_bytes();
//! let mut remaining = source_data.clone();
//! let mut hasher = Sha::new(
//! peripherals.SHA,
//! ShaMode::SHA256,
//! &mut system.peripheral_clock_control,
//! );
//!
//! // Short hashes can be created by decreasing the output buffer to the desired
//! // length
//! let mut output = [0u8; 32];
//!
//! while remaining.len() > 0 {
//! // All the HW Sha functions are infallible so unwrap is fine to use if you use
//! // block!
//! remaining = block!(hasher.update(remaining)).unwrap();
//! }
//!
//! // Finish can be called as many times as desired to get multiple copies of the
//! // output.
//! block!(hasher.finish(output.as_mut_slice())).unwrap();
//!
//! println!("SHA256 Hash output {:02x?}", output);
//!
//! let mut hasher = Sha256::new();
//! hasher.update(source_data);
//! let soft_result = hasher.finalize();
//!
//! println!("SHA256 Hash output {:02x?}", soft_result);
//! ```
use core::convert::Infallible;

View File

@ -1,4 +1,53 @@
//! Control CPU Cores
//! # Control CPU Cores (ESP32)
//!
//! ## Overview
//!
//! This module provides essential functionality for controlling
//! and managing the CPU cores on the `ESP32` chip, allowing for fine-grained
//! control over their execution and cache behavior. It is used in scenarios
//! where precise control over CPU core operation is required, such as
//! multi-threading or power management.
//!
//! The `CpuControl` struct represents the CPU control module and is responsible
//! for managing the behavior and operation of the CPU cores. It is typically
//! initialized with the `SystemCpuControl` struct, which is provided by the
//! `system` module.
//!
//! ## Example
//! ```no_run
//! let counter = Mutex::new(RefCell::new(0));
//!
//! let mut cpu_control = CpuControl::new(system.cpu_control);
//! let mut cpu1_fnctn = || {
//! cpu1_task(&mut timer1, &counter);
//! };
//! let _guard = cpu_control.start_app_core(&mut cpu1_fnctn).unwrap();
//!
//! loop {
//! block!(timer0.wait()).unwrap();
//!
//! let count = critical_section::with(|cs| *counter.borrow_ref(cs));
//! println!("Hello World - Core 0! Counter is {}", count);
//! }
//! ```
//!
//! Where `cpu1_task()` may be defined as:
//! ```no_run
//! fn cpu1_task(
//! timer: &mut Timer<Timer0<TIMG1>>,
//! counter: &critical_section::Mutex<RefCell<i32>>,
//! ) -> ! {
//! println!("Hello World - Core 1!");
//! loop {
//! block!(timer.wait()).unwrap();
//!
//! critical_section::with(|cs| {
//! let new_val = counter.borrow_ref_mut(cs).wrapping_add(1);
//! *counter.borrow_ref_mut(cs) = new_val;
//! });
//! }
//! }
//! ```
use core::marker::PhantomData;

View File

@ -1,4 +1,37 @@
//! Reading of eFuses
//! # Reading of eFuses (ESP32)
//!
//! ## Overview
//!
//! The `efuse` module provides functionality for reading eFuse data
//! from the `ESP32` chip, allowing access to various chip-specific information
//! such as :
//! * MAC address
//! * core count
//! * CPU frequency
//! * chip type
//!
//! and more. It is useful for retrieving chip-specific configuration and
//! identification data during runtime.
//!
//! The `Efuse` struct represents the eFuse peripheral and is responsible for
//! reading various eFuse fields and values.
//!
//! ## Example
//!
//! ### Read chip's MAC address from the eFuse storage.
//! ```no_run
//! let mac_address = Efuse::get_mac_address();
//! writeln!(
//! serial_tx,
//! "MAC: {:#X}:{:#X}:{:#X}:{:#X}:{:#X}:{:#X}",
//! mac_address[0],
//! mac_address[1],
//! mac_address[2],
//! mac_address[3],
//! mac_address[4],
//! mac_address[5]
//! );
//! ```
use fugit::{HertzU32, RateExtU32};
@ -18,23 +51,6 @@ pub enum ChipType {
}
impl Efuse {
/// Reads chip's MAC address from the eFuse storage.
///
/// # Example
///
/// ```
/// let mac_address = Efuse::get_mac_address();
/// writeln!(
/// serial_tx,
/// "MAC: {:#X}:{:#X}:{:#X}:{:#X}:{:#X}:{:#X}",
/// mac_address[0],
/// mac_address[1],
/// mac_address[2],
/// mac_address[3],
/// mac_address[4],
/// mac_address[5]
/// );
/// ```
pub fn get_mac_address() -> [u8; 6] {
Self::read_field_be(MAC_FACTORY)
}

View File

@ -1,3 +1,50 @@
//! # GPIO configuration module (ESP32)
//!
//! ## Overview
//!
//! The `GPIO` module provides functions and configurations for controlling the
//! `General Purpose Input/Output` pins on the `ESP32` chip. It allows you to
//! configure pins as inputs or outputs, set their state and read their state.
//!
//! Let's get through the functionality and configurations provided by this GPIO
//! module:
//! - `get_io_mux_reg(gpio_num: u8) -> &'static
//! crate::peripherals::io_mux::GPIO0:`:
//! * This function returns a reference to the GPIO register associated
//! with the given GPIO number. It uses unsafe code and transmutation to
//! access the GPIO registers based on the provided GPIO number.
//! - `gpio_intr_enable(int_enable: bool, nmi_enable: bool) -> u8`:
//! * This function enables or disables GPIO interrupts and Non-Maskable
//! Interrupts (NMI). It takes two boolean arguments int_enable and
//! nmi_enable to control the interrupt and NMI enable settings. The
//! function returns an u8 value representing the interrupt enable
//! settings.
//! - `errata36(pin_num: u8, pull_up: bool, pull_down: bool)`:
//! * Handles the configuration of pull-up and pull-down resistors for
//! specific GPIO pins
//! - `gpio` block:
//! * Defines the pin configurations for various GPIO pins. Each line
//! represents a pin and its associated options such as input/output
//! mode, analog capability, and corresponding functions.
//! - `analog` block:
//! * Block defines the analog capabilities of various GPIO pins. Each
//! line represents a pin and its associated options such as mux
//! selection, function selection, and input enable.
//! - `enum InputSignal`:
//! * This enumeration defines input signals for the GPIO mux. Each input
//! signal is assigned a specific value.
//! - `enum OutputSignal`:
//! * This enumeration defines output signals for the GPIO mux. Each
//! output signal is assigned a specific value.
//!
//! This module also implements the `InterruptStatusRegisterAccess` trait for
//! two different banks:
//! * `InterruptStatusRegisterAccessBank0`
//! * `InterruptStatusRegisterAccessBank1`.
//! This trait provides functions to read the interrupt status and NMI status
//! registers for both the `PRO CPU` and `APP CPU`. The implementation uses the
//! `gpio` peripheral to access the appropriate registers.
use crate::{
gpio::{
AlternateFunction,

View File

@ -1,3 +1,10 @@
//! # SOC (System-on-Chip) module (ESP32)
//!
//! ## Overview
//!
//! The `SOC` module provides access, functions and structures that are useful
//! for interacting with various system-related peripherals on `ESP32` chip.
pub mod cpu_control;
pub mod efuse;
pub mod gpio;

View File

@ -1,4 +1,25 @@
//! Peripheral instance singletons
//! # Peripheral instance singletons (ESP32)
//!
//! ## Overview
//!
//! The `Peripherals` module provides singleton instances of various peripherals
//! and allows users to access and use them in their applications.
//!
//! These peripherals provide various functionalities and interfaces for
//! interacting with different hardware components on the `ESP32` chip, such as
//! timers, `GPIO` pins, `I2C`, `SPI`, `UART`, and more. Users can access and
//! utilize these peripherals by importing the respective singleton instances
//! from this module.
//!
//! It's important to note that the module also exports the `Interrupt` enum
//! from the `ESP32` `PAC (Peripheral Access Crate)` for users to handle
//! interrupts associated with these peripherals.
//!
//! ⚠️ NOTE: notice that `psram` and `radio` are marked with `false` in the
//! `peripherals!` macro. Basically, that means that there's no real peripheral
//! (no `PSRAM` nor `RADIO` peripheral in the PACs) but we're creating "virtual
//! peripherals" for them in order to ensure the uniqueness of the instances
//! (Singletons).
use esp32 as pac;
// We need to export this for users to use

View File

@ -1,3 +1,24 @@
//! # PSRAM "virtual peripheral" driver (ESP32)
//!
//! ## Overview
//!
//! The `PSRAM` module provides support for accessing and controlling
//! the `Pseudo Static Random Access Memory (PSRAM)` on the `ESP32`.
//!
//! The `PSRAM` module enables users to interface with the `PSRAM` memory
//! present on the `ESP32` chip. `PSRAM` provides additional external memory to
//! supplement the internal memory of the `ESP32`, allowing for increased
//! storage capacity and improved performance in certain applications.
//!
//! The `PSRAM` module is accessed through a virtual address, defined as
//! `PSRAM_VADDR`. The starting virtual address for the PSRAM module is
//! 0x3F800000. The `PSRAM` module size depends on the configuration specified
//! during the compilation process. The available `PSRAM` sizes are `2MB`,
//! `4MB`, and `8MB`.
//!
//! NOTE: If you want to use `PSRAM` on `ESP32` or `ESP32-S3`, it'll work only
//! in `release` mode.
const PSRAM_VADDR: u32 = 0x3F800000;
pub fn psram_vaddr_start() -> usize {

View File

@ -1,3 +1,16 @@
//! # Radio clocks driver (ESP32)
//!
//! ## Overview
//!
//! The `Radio Clocks` module provides control and configuration functions for
//! various radio peripherals, such as `PHY`, `Bluetooth (BT)`, and `Wi-Fi`. The
//! module allows enabling and disabling these peripherals, resetting the `Media
//! Access Control (MAC)` and initializing clocks.
//!
//! The module defines a `RadioClockController` trait implemented by the
//! `RadioClockControl` struct. This trait provides methods to enable, disable,
//! reset the MAC, initialize clocks and perform other related operations.
use crate::system::{RadioClockControl, RadioClockController, RadioPeripherals};
const DPORT_WIFI_CLK_WIFI_BT_COMMON_M: u32 = 0x000003c9;

View File

@ -1,4 +1,37 @@
//! Reading of eFuses
//! # Reading of eFuses (ESP32-C2)
//!
//! ## Overview
//!
//! The `efuse` module provides functionality for reading eFuse data
//! from the `ESP32-C2` chip, allowing access to various chip-specific
//! information such as :
//! * MAC address
//! * core count
//! * CPU frequency
//! * chip type
//!
//! and more. It is useful for retrieving chip-specific configuration and
//! identification data during runtime.
//!
//! The `Efuse` struct represents the eFuse peripheral and is responsible for
//! reading various eFuse fields and values.
//!
//! ## Example
//!
//! ### Read chip's MAC address from the eFuse storage.
//! ```no_run
//! let mac_address = Efuse::get_mac_address();
//! writeln!(
//! serial_tx,
//! "MAC: {:#X}:{:#X}:{:#X}:{:#X}:{:#X}:{:#X}",
//! mac_address[0],
//! mac_address[1],
//! mac_address[2],
//! mac_address[3],
//! mac_address[4],
//! mac_address[5]
//! );
//! ```
pub use crate::soc::efuse_field::*;
use crate::{adc::Attenuation, peripherals::EFUSE};
@ -7,22 +40,6 @@ pub struct Efuse;
impl Efuse {
/// Reads chip's MAC address from the eFuse storage.
///
/// # Example
///
/// ```
/// let mac_address = Efuse::get_mac_address();
/// writeln!(
/// serial_tx,
/// "MAC: {:#X}:{:#X}:{:#X}:{:#X}:{:#X}:{:#X}",
/// mac_address[0],
/// mac_address[1],
/// mac_address[2],
/// mac_address[3],
/// mac_address[4],
/// mac_address[5]
/// );
/// ```
pub fn get_mac_address() -> [u8; 6] {
Self::read_field_be(MAC_FACTORY)
}

View File

@ -1,3 +1,44 @@
//! # GPIO configuration module (ESP32-C2)
//!
//! ## Overview
//!
//! The `GPIO` module provides functions and configurations for controlling the
//! `General Purpose Input/Output` pins on the `ESP32-C2` chip. It allows you to
//! configure pins as inputs or outputs, set their state and read their state.
//!
//! Let's get through the functionality and configurations provided by this GPIO
//! module:
//! - `get_io_mux_reg(gpio_num: u8) -> &'static
//! crate::peripherals::io_mux::GPIO`:
//! * Returns the IO_MUX register for the specified GPIO pin number.
//! - `gpio_intr_enable(int_enable: bool, nmi_enable: bool) -> u8`:
//! * This function enables or disables GPIO interrupts and Non-Maskable
//! Interrupts (NMI). It takes two boolean arguments int_enable and
//! nmi_enable to control the interrupt and NMI enable settings. The
//! function returns an u8 value representing the interrupt enable
//! settings.
//! - `gpio` block:
//! * Defines the pin configurations for various GPIO pins. Each line
//! represents a pin and its associated options such as input/output
//! mode, analog capability, and corresponding functions.
//! - `analog` block:
//! * Block defines the analog capabilities of various GPIO pins. Each
//! line represents a pin and its associated options such as mux
//! selection, function selection, and input enable.
//! - `enum InputSignal`:
//! * This enumeration defines input signals for the GPIO mux. Each input
//! signal is assigned a specific value.
//! - `enum OutputSignal`:
//! * This enumeration defines output signals for the GPIO mux. Each
//! output signal is assigned a specific value.
//!
//! This module also implements the `InterruptStatusRegisterAccess` trait for
//! two different banks:
//! * `InterruptStatusRegisterAccessBank0`
//! * `InterruptStatusRegisterAccessBank1`.
//! This trait provides functions to read the interrupt status and NMI status
//! registers for both the `PRO CPU` and `APP CPU`. The implementation uses the
//! `gpio` peripheral to access the appropriate registers.
use crate::{
gpio::{
AlternateFunction,

View File

@ -1,3 +1,10 @@
//! # SOC (System-on-Chip) module (ESP32-C2)
//!
//! ## Overview
//!
//! The `SOC` module provides access, functions and structures that are useful
//! for interacting with various system-related peripherals on `ESP32-C2` chip.
pub mod efuse;
pub mod gpio;
pub mod peripherals;

View File

@ -1,4 +1,24 @@
//! Peripheral instance singletons
//! # Peripheral instance singletons (ESP32-C2)
//!
//! ## Overview
//!
//! The `Peripherals` module provides singleton instances of various peripherals
//! and allows users to access and use them in their applications.
//!
//! These peripherals provide various functionalities and interfaces for
//! interacting with different hardware components on the `ESP32-C2` chip, such
//! as timers, `GPIO` pins, `I2C`, `SPI`, `UART`, and more. Users can access and
//! utilize these peripherals by importing the respective singleton instances
//! from this module.
//!
//! It's important to note that the module also exports the `Interrupt` enum
//! from the `ESP32-C2` `PAC (Peripheral Access Crate)` for users to handle
//! interrupts associated with these peripherals.
//!
//! ⚠️ NOTE: notice that `radio` is marked with `false` in the `peripherals!`
//! macro. Basically, that means that there's no real peripheral (no `RADIO`
//! peripheral in the PACs) but we're creating "virtual peripherals" for it in
//! order to ensure the uniqueness of the instance (Singleton).
use esp32c2 as pac;
// We need to export this for users to use

View File

@ -1,3 +1,16 @@
//! # Radio clocks driver (ESP32-C2)
//!
//! ## Overview
//!
//! The `Radio Clocks` module provides control and configuration functions for
//! various radio peripherals, such as `PHY`, `Bluetooth (BT)`, and `Wi-Fi`. The
//! module allows enabling and disabling these peripherals, resetting the `Media
//! Access Control (MAC)` and initializing clocks.
//!
//! The module defines a `RadioClockController` trait implemented by the
//! `RadioClockControl` struct. This trait provides methods to enable, disable,
//! reset the MAC, initialize clocks and perform other related operations.
use crate::system::{RadioClockControl, RadioClockController, RadioPeripherals};
// Mask for clock bits used by both WIFI and Bluetooth, 0, 1, 2, 3, 7, 8, 9, 10,

View File

@ -1,4 +1,37 @@
//! Reading of eFuses
//! # Reading of eFuses (ESP32-C3)
//!
//! ## Overview
//!
//! The `efuse` module provides functionality for reading eFuse data
//! from the `ESP32-C3` chip, allowing access to various chip-specific
//! information such as :
//! * MAC address
//! * core count
//! * CPU frequency
//! * chip type
//!
//! and more. It is useful for retrieving chip-specific configuration and
//! identification data during runtime.
//!
//! The `Efuse` struct represents the eFuse peripheral and is responsible for
//! reading various eFuse fields and values.
//!
//! ## Example
//!
//! ### Read chip's MAC address from the eFuse storage.
//! ```no_run
//! let mac_address = Efuse::get_mac_address();
//! writeln!(
//! serial_tx,
//! "MAC: {:#X}:{:#X}:{:#X}:{:#X}:{:#X}:{:#X}",
//! mac_address[0],
//! mac_address[1],
//! mac_address[2],
//! mac_address[3],
//! mac_address[4],
//! mac_address[5]
//! );
//! ```
pub use crate::soc::efuse_field::*;
use crate::{adc::Attenuation, peripherals::EFUSE};
@ -7,22 +40,6 @@ pub struct Efuse;
impl Efuse {
/// Reads chip's MAC address from the eFuse storage.
///
/// # Example
///
/// ```
/// let mac_address = Efuse::get_mac_address();
/// writeln!(
/// serial_tx,
/// "MAC: {:#X}:{:#X}:{:#X}:{:#X}:{:#X}:{:#X}",
/// mac_address[0],
/// mac_address[1],
/// mac_address[2],
/// mac_address[3],
/// mac_address[4],
/// mac_address[5]
/// );
/// ```
pub fn get_mac_address() -> [u8; 6] {
Self::read_field_be(MAC_FACTORY)
}

View File

@ -1,3 +1,45 @@
//! # GPIO configuration module (ESP32-C3)
//!
//! ## Overview
//!
//! The `GPIO` module provides functions and configurations for controlling the
//! `General Purpose Input/Output` pins on the `ESP32-C3` chip. It allows you to
//! configure pins as inputs or outputs, set their state and read their state.
//!
//! Let's get through the functionality and configurations provided by this GPIO
//! module:
//! - `get_io_mux_reg(gpio_num: u8) -> &'static
//! crate::peripherals::io_mux::GPIO0:`:
//! * Returns the IO_MUX register for the specified GPIO pin number.
//! - `gpio_intr_enable(int_enable: bool, nmi_enable: bool) -> u8`:
//! * This function enables or disables GPIO interrupts and Non-Maskable
//! Interrupts (NMI). It takes two boolean arguments int_enable and
//! nmi_enable to control the interrupt and NMI enable settings. The
//! function returns an u8 value representing the interrupt enable
//! settings.
//! - `gpio` block:
//! * Defines the pin configurations for various GPIO pins. Each line
//! represents a pin and its associated options such as input/output
//! mode, analog capability, and corresponding functions.
//! - `analog` block:
//! * Block defines the analog capabilities of various GPIO pins. Each
//! line represents a pin and its associated options such as mux
//! selection, function selection, and input enable.
//! - `enum InputSignal`:
//! * This enumeration defines input signals for the GPIO mux. Each input
//! signal is assigned a specific value.
//! - `enum OutputSignal`:
//! * This enumeration defines output signals for the GPIO mux. Each
//! output signal is assigned a specific value.
//!
//! This module also implements the `InterruptStatusRegisterAccess` trait for
//! two different banks:
//! * `InterruptStatusRegisterAccessBank0`
//! * `InterruptStatusRegisterAccessBank1`.
//! This trait provides functions to read the interrupt status and NMI status
//! registers for both the `PRO CPU` and `APP CPU`. The implementation uses the
//! `gpio` peripheral to access the appropriate registers.
use crate::{
gpio::{
AlternateFunction,

View File

@ -1,3 +1,14 @@
//! # SOC (System-on-Chip) module (ESP32-C3)
//!
//! ## Overview
//!
//! The `SOC` module provides access, functions and structures that are useful
//! for interacting with various system-related peripherals on `ESP32-C3` chip.
//!
//! Also few constants are defined in this module for `ESP32-C3` chip:
//! * I2S_SCLK: 160_000_000 - I2S clock frequency
//! * I2S_DEFAULT_CLK_SRC: 2 - I2S clock source
pub mod efuse;
pub mod gpio;
pub mod peripherals;

View File

@ -1,4 +1,24 @@
//! Peripheral instance singletons
//! # Peripheral instance singletons (ESP32-C3)
//!
//! ## Overview
//!
//! The `Peripherals` module provides singleton instances of various peripherals
//! and allows users to access and use them in their applications.
//!
//! These peripherals provide various functionalities and interfaces for
//! interacting with different hardware components on the `ESP32-C3` chip, such
//! as timers, `GPIO` pins, `I2C`, `SPI`, `UART`, and more. Users can access and
//! utilize these peripherals by importing the respective singleton instances
//! from this module.
//!
//! It's important to note that the module also exports the `Interrupt` enum
//! from the `ESP32-C3` `PAC (Peripheral Access Crate)` for users to handle
//! interrupts associated with these peripherals.
//!
//! ⚠️ NOTE: notice that `radio` is marked with `false` in the `peripherals!`
//! macro. Basically, that means that there's no real peripheral (no `RADIO`
//! peripheral in the PACs) but we're creating "virtual peripherals" for it in
//! order to ensure the uniqueness of the instance (Singleton).
use esp32c3 as pac;
// We need to export this for users to use

View File

@ -1,3 +1,16 @@
//! # Radio clocks driver (ESP32-C3)
//!
//! ## Overview
//!
//! The `Radio Clocks` module provides control and configuration functions for
//! various radio peripherals, such as `PHY`, `Bluetooth (BT)`, and `Wi-Fi`. The
//! module allows enabling and disabling these peripherals, resetting the `Media
//! Access Control (MAC)` and initializing clocks.
//!
//! The module defines a `RadioClockController` trait implemented by the
//! `RadioClockControl` struct. This trait provides methods to enable, disable,
//! reset the MAC, initialize clocks and perform other related operations.
use crate::system::{RadioClockControl, RadioClockController, RadioPeripherals};
// Mask for clock bits used by both WIFI and Bluetooth, 0, 1, 2, 3, 7, 8, 9, 10,

View File

@ -1,4 +1,37 @@
//! Reading of eFuses
//! # Reading of eFuses (ESP32-C6)
//!
//! ## Overview
//!
//! The `efuse` module provides functionality for reading eFuse data
//! from the `ESP32-C6` chip, allowing access to various chip-specific
//! information such as :
//! * MAC address
//! * core count
//! * CPU frequency
//! * chip type
//!
//! and more. It is useful for retrieving chip-specific configuration and
//! identification data during runtime.
//!
//! The `Efuse` struct represents the eFuse peripheral and is responsible for
//! reading various eFuse fields and values.
//!
//! ## Example
//!
//! ### Read chip's MAC address from the eFuse storage.
//! ```no_run
//! let mac_address = Efuse::get_mac_address();
//! writeln!(
//! serial_tx,
//! "MAC: {:#X}:{:#X}:{:#X}:{:#X}:{:#X}:{:#X}",
//! mac_address[0],
//! mac_address[1],
//! mac_address[2],
//! mac_address[3],
//! mac_address[4],
//! mac_address[5]
//! );
//! ```
pub use crate::soc::efuse_field::*;
use crate::{adc::Attenuation, peripherals::EFUSE};
@ -7,22 +40,6 @@ pub struct Efuse;
impl Efuse {
/// Reads chip's MAC address from the eFuse storage.
///
/// # Example
///
/// ```
/// let mac_address = Efuse::get_mac_address();
/// writeln!(
/// serial_tx,
/// "MAC: {:#X}:{:#X}:{:#X}:{:#X}:{:#X}:{:#X}",
/// mac_address[0],
/// mac_address[1],
/// mac_address[2],
/// mac_address[3],
/// mac_address[4],
/// mac_address[5]
/// );
/// ```
pub fn get_mac_address() -> [u8; 6] {
Self::read_field_be(MAC_FACTORY)
}

View File

@ -1,3 +1,45 @@
//! # GPIO configuration module (ESP32-C6)
//!
//! ## Overview
//!
//! The `GPIO` module provides functions and configurations for controlling the
//! `General Purpose Input/Output` pins on the `ESP32-C6` chip. It allows you to
//! configure pins as inputs or outputs, set their state and read their state.
//!
//! Let's get through the functionality and configurations provided by this GPIO
//! module:
//! - `get_io_mux_reg(gpio_num: u8) -> &'static
//! crate::peripherals::io_mux::GPIO0:`:
//! * Returns the IO_MUX register for the specified GPIO pin number.
//! - `gpio_intr_enable(int_enable: bool, nmi_enable: bool) -> u8`:
//! * This function enables or disables GPIO interrupts and Non-Maskable
//! Interrupts (NMI). It takes two boolean arguments int_enable and
//! nmi_enable to control the interrupt and NMI enable settings. The
//! function returns an u8 value representing the interrupt enable
//! settings.
//! - `gpio` block:
//! * Defines the pin configurations for various GPIO pins. Each line
//! represents a pin and its associated options such as input/output
//! mode, analog capability, and corresponding functions.
//! - `analog` block:
//! * Block defines the analog capabilities of various GPIO pins. Each
//! line represents a pin and its associated options such as mux
//! selection, function selection, and input enable.
//! - `enum InputSignal`:
//! * This enumeration defines input signals for the GPIO mux. Each input
//! signal is assigned a specific value.
//! - `enum OutputSignal`:
//! * This enumeration defines output signals for the GPIO mux. Each
//! output signal is assigned a specific value.
//!
//! This module also implements the `InterruptStatusRegisterAccess` trait for
//! two different banks:
//! * `InterruptStatusRegisterAccessBank0`
//! * `InterruptStatusRegisterAccessBank1`.
//! This trait provides functions to read the interrupt status and NMI status
//! registers for both the `PRO CPU` and `APP CPU`. The implementation uses the
//! `gpio` peripheral to access the appropriate registers.
use crate::{
gpio::{
AlternateFunction,

View File

@ -1,4 +1,63 @@
//! Control the LP core
//! # Control the LP core
//!
//! ## Overview
//! The `LP_CORE` driver provides an interface for controlling and managing the
//! low power core of `ESP` chips, allowing efficient low power operation and
//! wakeup from sleep based on configurable sources. The low power core is
//! responsible for executing low power tasks while the high power core is in
//! sleep mode.
//!
//! The `LpCore` struct provides methods to stop and run the low power core.
//!
//! The `stop` method stops the low power core, putting it into a sleep state.
//!
//! The `run` method starts the low power core and specifies the wakeup source.
//!
//! ## Example
//! ```no_run
//! const CODE: &[u8] = &[
//! 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00,
//! 0x00, 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x13, 0x00,
//! 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x13,
//! 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
//! 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00,
//! 0x00, 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x13, 0x00,
//! 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x13,
//! 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
//! 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x17, 0x05, 0x00, 0x00, 0x13, 0x05, 0x05,
//! 0x04, 0x85, 0x45, 0x23, 0x00, 0xb5, 0x00, 0xb7, 0x26, 0x0b, 0x60, 0xa1, 0x06, 0x37, 0x26,
//! 0x0b, 0x60, 0x11, 0x06, 0x09, 0x47, 0x18, 0xc2, 0xb7, 0x47, 0x0f, 0x00, 0x93, 0x87, 0x07,
//! 0x24, 0xfd, 0x17, 0xfd, 0xff, 0x85, 0x05, 0x23, 0x00, 0xb5, 0x00, 0x98, 0xc2, 0xb7, 0x47,
//! 0x0f, 0x00, 0x93, 0x87, 0x07, 0x24, 0xfd, 0x17, 0xfd, 0xff, 0xf9, 0xbf, 0x00, 0x00, 0x00,
//! 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//! ];
//!
//! // configure GPIO 1 as LP output pin
//! let mut lp_pin = io.pins.gpio1.into_low_power();
//! lp_pin.output_enable(true);
//!
//! let mut lp_core = esp32c6_hal::lp_core::LpCore::new(peripherals.LP_CORE);
//! lp_core.stop();
//! println!("lp core stopped");
//!
//! // copy code to LP ram
//! let lp_ram = 0x5000_0000 as *mut u8;
//! unsafe {
//! core::ptr::copy_nonoverlapping(CODE as *const _ as *const u8, lp_ram, CODE.len());
//! }
//! println!("copied code (len {})", CODE.len());
//!
//! // start LP core
//! lp_core.run(lp_core::LpCoreWakeupSource::HpCpu);
//! println!("lpcore run");
//!
//! let data = (0x500000c0) as *mut u32;
//! loop {
//! print!("Current {:x} \u{000d}", unsafe {
//! data.read_volatile()
//! });
//! }
//! ```
use esp32c6 as pac;

View File

@ -1,3 +1,15 @@
//! # SOC (System-on-Chip) module (ESP32-C6)
//!
//! ## Overview
//!
//! The `SOC` module provides access, functions and structures that are useful
//! for interacting with various system-related peripherals on `ESP32-C6` chip.
//!
//! Also few constants are defined in this module for `ESP32-C6` chip:
//! * TIMG_DEFAULT_CLK_SRC: 1 - Timer clock source
//! * I2S_DEFAULT_CLK_SRC: 2 - I2S clock source
//! * I2S_SCLK: 160_000_000 - I2S clock frequency
pub mod efuse;
pub mod gpio;
pub mod lp_core;

View File

@ -1,4 +1,25 @@
//! Peripheral instance singletons
//! # Peripheral instance singletons (ESP32-C6)
//!
//! ## Overview
//!
//! The `Peripherals` module provides singleton instances of various peripherals
//! and allows users to access and use them in their applications.
//!
//! These peripherals provide various functionalities and interfaces for
//! interacting with different hardware components on the `ESP32-C6` chip, such
//! as timers, `GPIO` pins, `I2C`, `SPI`, `UART`, and more. Users can access and
//! utilize these peripherals by importing the respective singleton instances
//! from this module.
//!
//! It's important to note that the module also exports the `Interrupt` enum
//! from the `ESP32-C6` `PAC (Peripheral Access Crate)` for users to handle
//! interrupts associated with these peripherals.
//!
//! ⚠️ NOTE: notice that `radio` and `lp_core` are marked with `false` in the
//! `peripherals!` macro. Basically, that means that there's no real peripheral
//! (no `RADIO` nor `LP_CORE` peripheral in the PACs) but we're
//! creating "virtual peripherals" for them in order to ensure the uniqueness of
//! the instances (Singletons).
use esp32c6 as pac;
// We need to export this for users to use

View File

@ -1,3 +1,16 @@
//! # Radio clocks driver (ESP32-C6)
//!
//! ## Overview
//!
//! The `Radio Clocks` module provides control and configuration functions for
//! various radio peripherals, such as `PHY`, `Bluetooth (BT)`, and `Wi-Fi`. The
//! module allows enabling and disabling these peripherals, resetting the `Media
//! Access Control (MAC)` and initializing clocks.
//!
//! The module defines a `RadioClockController` trait implemented by the
//! `RadioClockControl` struct. This trait provides methods to enable, disable,
//! reset the MAC, initialize clocks and perform other related operations.
use crate::system::{RadioClockControl, RadioClockController, RadioPeripherals};
impl RadioClockController for RadioClockControl {

View File

@ -1,4 +1,37 @@
//! Reading of eFuses
//! # Reading of eFuses (ESP32-H2)
//!
//! ## Overview
//!
//! The `efuse` module provides functionality for reading eFuse data
//! from the `ESP32-H2` chip, allowing access to various chip-specific
//! information such as :
//! * MAC address
//! * core count
//! * CPU frequency
//! * chip type
//!
//! and more. It is useful for retrieving chip-specific configuration and
//! identification data during runtime.
//!
//! The `Efuse` struct represents the eFuse peripheral and is responsible for
//! reading various eFuse fields and values.
//!
//! ## Example
//!
//! ### Read chip's MAC address from the eFuse storage.
//! ```no_run
//! let mac_address = Efuse::get_mac_address();
//! writeln!(
//! serial_tx,
//! "MAC: {:#X}:{:#X}:{:#X}:{:#X}:{:#X}:{:#X}",
//! mac_address[0],
//! mac_address[1],
//! mac_address[2],
//! mac_address[3],
//! mac_address[4],
//! mac_address[5]
//! );
//! ```
use crate::peripherals::EFUSE;
pub use crate::soc::efuse_field::*;
@ -7,22 +40,6 @@ pub struct Efuse;
impl Efuse {
/// Reads chip's MAC address from the eFuse storage.
///
/// # Example
///
/// ```
/// let mac_address = Efuse::get_mac_address();
/// writeln!(
/// serial_tx,
/// "MAC: {:#X}:{:#X}:{:#X}:{:#X}:{:#X}:{:#X}",
/// mac_address[0],
/// mac_address[1],
/// mac_address[2],
/// mac_address[3],
/// mac_address[4],
/// mac_address[5]
/// );
/// ```
pub fn get_mac_address() -> [u8; 6] {
Self::read_field_be(MAC_FACTORY)
}

View File

@ -1,3 +1,45 @@
//! # GPIO configuration module (ESP32-H2)
//!
//! ## Overview
//!
//! The `GPIO` module provides functions and configurations for controlling the
//! `General Purpose Input/Output` pins on the `ESP32-H2` chip. It allows you to
//! configure pins as inputs or outputs, set their state and read their state.
//!
//! Let's get through the functionality and configurations provided by this GPIO
//! module:
//! - `get_io_mux_reg(gpio_num: u8) -> &'static
//! crate::peripherals::io_mux::GPIO0:`:
//! * Returns the IO_MUX register for the specified GPIO pin number.
//! - `gpio_intr_enable(int_enable: bool, nmi_enable: bool) -> u8`:
//! * This function enables or disables GPIO interrupts and Non-Maskable
//! Interrupts (NMI). It takes two boolean arguments int_enable and
//! nmi_enable to control the interrupt and NMI enable settings. The
//! function returns an u8 value representing the interrupt enable
//! settings.
//! - `gpio` block:
//! * Defines the pin configurations for various GPIO pins. Each line
//! represents a pin and its associated options such as input/output
//! mode, analog capability, and corresponding functions.
//! - `analog` block:
//! * Block defines the analog capabilities of various GPIO pins. Each
//! line represents a pin and its associated options such as mux
//! selection, function selection, and input enable.
//! - `enum InputSignal`:
//! * This enumeration defines input signals for the GPIO mux. Each input
//! signal is assigned a specific value.
//! - `enum OutputSignal`:
//! * This enumeration defines output signals for the GPIO mux. Each
//! output signal is assigned a specific value.
//!
//! This module also implements the `InterruptStatusRegisterAccess` trait for
//! two different banks:
//! * `InterruptStatusRegisterAccessBank0`
//! * `InterruptStatusRegisterAccessBank1`.
//! This trait provides functions to read the interrupt status and NMI status
//! registers for both the `PRO CPU` and `APP CPU`. The implementation uses the
//! `gpio` peripheral to access the appropriate registers.
use crate::{
gpio::{
AlternateFunction,

View File

@ -1,3 +1,15 @@
//! # SOC (System-on-Chip) module (ESP32-H2)
//!
//! ## Overview
//!
//! The `SOC` module provides access, functions and structures that are useful
//! for interacting with various system-related peripherals on `ESP32-H2` chip.
//!
//! Also few constants are defined in this module for `ESP32-H2` chip:
//! * TIMG_DEFAULT_CLK_SRC: 2 - Timer clock source
//! * I2S_DEFAULT_CLK_SRC: 1 - I2S clock source
//! * I2S_SCLK: 96_000_000 - I2S clock frequency
pub mod efuse;
pub mod gpio;
pub mod peripherals;

View File

@ -1,4 +1,24 @@
//! Peripheral instance singletons
//! # Peripheral instance singletons (ESP32-H2)
//!
//! ## Overview
//!
//! The `Peripherals` module provides singleton instances of various peripherals
//! and allows users to access and use them in their applications.
//!
//! These peripherals provide various functionalities and interfaces for
//! interacting with different hardware components on the `ESP32-H2` chip, such
//! as timers, `GPIO` pins, `I2C`, `SPI`, `UART`, and more. Users can access and
//! utilize these peripherals by importing the respective singleton instances
//! from this module.
//!
//! It's important to note that the module also exports the `Interrupt` enum
//! from the `ESP32-H2` `PAC (Peripheral Access Crate)` for users to handle
//! interrupts associated with these peripherals.
//!
//! ⚠️ NOTE: notice that `radio` is marked with `false` in the `peripherals!`
//! macro. Basically, that means that there's no real peripheral (no `RADIO`
//! peripheral in the PACs) but we're creating "virtual peripherals" for it in
//! order to ensure the uniqueness of the instance (Singleton).
use esp32h2 as pac;
// We need to export this for users to use

View File

@ -1,3 +1,16 @@
//! # Radio clocks driver (ESP32-H2)
//!
//! ## Overview
//!
//! The `Radio Clocks` module provides control and configuration functions for
//! various radio peripherals, such as `PHY`, `Bluetooth (BT)`, and `Wi-Fi`. The
//! module allows enabling and disabling these peripherals, resetting the `Media
//! Access Control (MAC)` and initializing clocks.
//!
//! The module defines a `RadioClockController` trait implemented by the
//! `RadioClockControl` struct. This trait provides methods to enable, disable,
//! reset the MAC, initialize clocks and perform other related operations.
use crate::system::{RadioClockControl, RadioClockController, RadioPeripherals};
impl RadioClockController for RadioClockControl {

View File

@ -1,4 +1,37 @@
//! Reading of eFuses
//! # Reading of eFuses (ESP32-S2)
//!
//! ## Overview
//!
//! The `efuse` module provides functionality for reading eFuse data
//! from the `ESP32-S2` chip, allowing access to various chip-specific
//! information such as :
//! * MAC address
//! * core count
//! * CPU frequency
//! * chip type
//!
//! and more. It is useful for retrieving chip-specific configuration and
//! identification data during runtime.
//!
//! The `Efuse` struct represents the eFuse peripheral and is responsible for
//! reading various eFuse fields and values.
//!
//! ## Example
//!
//! ### Read chip's MAC address from the eFuse storage.
//! ```no_run
//! let mac_address = Efuse::get_mac_address();
//! writeln!(
//! serial_tx,
//! "MAC: {:#X}:{:#X}:{:#X}:{:#X}:{:#X}:{:#X}",
//! mac_address[0],
//! mac_address[1],
//! mac_address[2],
//! mac_address[3],
//! mac_address[4],
//! mac_address[5]
//! );
//! ```
use crate::peripherals::EFUSE;
pub use crate::soc::efuse_field::*;

View File

@ -1,3 +1,57 @@
//! # GPIO configuration module (ESP32-S2)
//!
//! ## Overview
//!
//! The `GPIO` module provides functions and configurations for controlling the
//! `General Purpose Input/Output` pins on the `ESP32-S2` chip. It allows you to
//! configure pins as inputs or outputs, set their state and read their state.
//!
//! Let's get through the functionality and configurations provided by this GPIO
//! module:
//! - `get_io_mux_reg(gpio_num: u8) -> &'static
//! crate::peripherals::io_mux::GPIO0:`:
//! * This function returns a reference to the GPIO register associated
//! with the given GPIO number. It uses unsafe code and transmutation to
//! access the GPIO registers based on the provided GPIO number.
//! - `gpio_intr_enable(int_enable: bool, nmi_enable: bool) -> u8`:
//! * This function enables or disables GPIO interrupts and Non-Maskable
//! Interrupts (NMI). It takes two boolean arguments int_enable and
//! nmi_enable to control the interrupt and NMI enable settings. The
//! function returns an u8 value representing the interrupt enable
//! settings.
//! - `impl_get_rtc_pad`:
//! * This macro_rule generates a function to get a specific RTC pad. It
//! takes a single argument `$pad_name`, which is an identifier
//! representing the name of the pad. Returns a reference to the
//! corresponding RTC pad.
//! - `impl_get_rtc_pad_indexed`:
//! * This macro_rule generates a function similar to the previous one but
//! for indexed RTC pads. It takes two arguments: `$pad_name`, which
//! represents the name of the pad, and `$idx`, which is the index of
//! the specific pad. Returns a reference to the indexed RTC pad.
//! - `gpio` block:
//! * Defines the pin configurations for various GPIO pins. Each line
//! represents a pin and its associated options such as input/output
//! mode, analog capability, and corresponding functions.
//! - `analog` block:
//! * Block defines the analog capabilities of various GPIO pins. Each
//! line represents a pin and its associated options such as mux
//! selection, function selection, and input enable.
//! - `enum InputSignal`:
//! * This enumeration defines input signals for the GPIO mux. Each input
//! signal is assigned a specific value.
//! - `enum OutputSignal`:
//! * This enumeration defines output signals for the GPIO mux. Each
//! output signal is assigned a specific value.
//!
//! This module also implements the `InterruptStatusRegisterAccess` trait for
//! two different banks:
//! * `InterruptStatusRegisterAccessBank0`
//! * `InterruptStatusRegisterAccessBank1`.
//! This trait provides functions to read the interrupt status and NMI status
//! registers for both the `PRO CPU` and `APP CPU`. The implementation uses the
//! `gpio` peripheral to access the appropriate registers.
use crate::{
gpio::{
AlternateFunction,

View File

@ -1,3 +1,13 @@
//! # SOC (System-on-Chip) module (ESP32-S2)
//!
//! ## Overview
//!
//! The `SOC` module provides access, functions and structures that are useful
//! for interacting with various system-related peripherals on `ESP32-S2` chip.
//!
//! Also few constants are defined in this module for `ESP32-S2` chip:
//! * I2S_SCLK: 160_000_000 - I2S clock frequency
//! * I2S_DEFAULT_CLK_SRC: 2 - I2S clock source
pub mod efuse;
pub mod gpio;
pub mod peripherals;

View File

@ -1,4 +1,25 @@
//! Peripheral instance singletons
//! # Peripheral instance singletons (ESP32-S2)
//!
//! ## Overview
//!
//! The `Peripherals` module singleton instances of various peripherals and
//! allows users to access and use them in their applications.
//!
//! These peripherals provide various functionalities and interfaces for
//! interacting with different hardware components on the `ESP32-S2` chip, such
//! as timers, `GPIO` pins, `I2C`, `SPI`, `UART`, and more. Users can access and
//! utilize these peripherals by importing the respective singleton instances
//! from this module.
//!
//! It's important to note that the module also exports the `Interrupt` enum
//! from the `ESP32-S2` `PAC (Peripheral Access Crate)` for users to handle
//! interrupts associated with these peripherals.
//!
//! ⚠️ NOTE: notice that `psram`, `radio` and `ulp_riscv_core` are marked with
//! `false` in the `peripherals!` macro. Basically, that means that there's no
//! real peripheral (no `PSRAM`, `RADIO` nor `ULP_RISCV_CORE` peripheral in the
//! `PAC`s) but we're creating "virtual peripherals" for them in order to ensure
//! the uniqueness of the instances (Singletons).
use esp32s2 as pac;
// We need to export this for users to use

View File

@ -1,3 +1,20 @@
//! # PSRAM "virtual peripheral" driver (ESP32-S2)
//!
//! ## Overview
//!
//! The `PSRAM` module provides support for accessing and controlling the
//! `Pseudo Static Random Access Memory (PSRAM)` on the `ESP32-S2`.
//!
//! The `PSRAM` module enables users to interface with the `PSRAM` memory
//! present on the `ESP32-S2` chip. `PSRAM` provides additional external memory
//! to supplement the internal memory of the `ESP32-S2`, allowing for increased
//! storage capacity and improved performance in certain applications.
//!
//! The `PSRAM` module is accessed through a virtual address, defined as
//! `PSRAM_VADDR`. The starting virtual address for the PSRAM module is
//! 0x3f500000. The `PSRAM` module size depends on the configuration specified
//! during the compilation process. The available `PSRAM` sizes are `2MB`,
//! `4MB`, and `8MB`.
const PSRAM_VADDR: u32 = 0x3f500000;
pub fn psram_vaddr_start() -> usize {
@ -123,6 +140,9 @@ pub fn init_psram(_peripheral: impl crate::peripheral::Peripheral<P = crate::per
#[cfg(any(feature = "psram_2m", feature = "psram_4m", feature = "psram_8m"))]
pub(crate) mod utils {
// Function initializes the PSRAM by configuring GPIO pins, resetting the PSRAM,
// and enabling Quad I/O (QIO) mode. It also calls the psram_cache_init
// function to configure cache parameters and read/write commands.
pub(crate) fn psram_init() {
psram_gpio_config();

View File

@ -1,3 +1,16 @@
//! # Radio clocks driver (ESP32-S2)
//!
//! ## Overview
//!
//! The `Radio Clocks` module provides control and configuration functions for
//! various radio peripherals, such as `PHY`, `Bluetooth (BT)`, and `Wi-Fi`. The
//! module allows enabling and disabling these peripherals, resetting the `Media
//! Access Control (MAC)` and initializing clocks.
//!
//! The module defines a `RadioClockController` trait implemented by the
//! `RadioClockControl` struct. This trait provides methods to enable, disable,
//! reset the MAC, initialize clocks and perform other related operations.
use crate::system::{RadioClockControl, RadioClockController, RadioPeripherals};
// Mask for clock bits used by both WIFI and Bluetooth, bit 0, 3, 6, 7, 8, 9

View File

@ -1,5 +1,39 @@
//! Control the ULP RISCV core
//! # Control the ULP core
//!
//! ## Overview
//!
//! The `ULP CORE` peripheral allows control over the `Ultra-Low Power
//! (ULP) core` in `ESP` chips. The ULP core is a low-power processor
//! designed for executing tasks in deep sleep mode, enabling efficient power
//! management in ESP systems.
//!
//! The `UlpCore` struct provides an interface to interact with the `ULP`
//! peripheral. It allows starting and configuring the ULP core for operation.
//! The `UlpCore` struct is initialized with a peripheral reference to the `ULP
//! CORE` instance.
//!
//! ## Example
//! ```no_run
//! let mut ulp_core = esp32s3_hal::ulp_core::UlpCore::new(peripherals.ULP_RISCV_CORE);
//! ulp_core.stop();
//! println!("ulp core stopped");
//!
//! // copy code to RTC ram
//! let lp_ram = 0x5000_0000 as *mut u8;
//! unsafe {
//! core::ptr::copy_nonoverlapping(CODE as *const _ as *const u8, lp_ram, CODE.len());
//! }
//! println!("copied code (len {})", CODE.len());
//!
//! // start ULP core
//! ulp_core.run(esp32s3_hal::ulp_core::UlpCoreWakeupSource::HpCpu);
//! println!("ulpcore run");
//!
//! let data = (0x5000_0010 - 0) as *mut u32;
//! loop {
//! println!("Current {}", unsafe { data.read_volatile() });
//! }
//! ```
use esp32s2 as pac;
use crate::peripheral::{Peripheral, PeripheralRef};
@ -23,7 +57,7 @@ impl<'d> UlpCore<'d> {
Self { _lp_core: lp_core }
}
// currently stopping the ULP doesn't work (while following the proedures
// currently stopping the ULP doesn't work (while following the proсedures
// outlines in the TRM) - so don't offer this funtion for now
//
// pub fn stop(&mut self) {

View File

@ -1,4 +1,53 @@
//! Control CPU Cores
//! # Control CPU Cores (ESP32-S3)
//!
//! ## Overview
//!
//! This module provides essential functionality for controlling
//! and managing the CPU cores on the `ESP32-S3` chip allowing for fine-grained
//! control over their execution and cache behavior. It is used in scenarios
//! where precise control over CPU core operation is required, such as
//! multi-threading or power management.
//!
//! The `CpuControl` struct represents the CPU control module and is responsible
//! for managing the behavior and operation of the CPU cores. It is typically
//! initialized with the `SystemCpuControl` struct, which is provided by the
//! `system` module.
//!
//! ## Example
//! ```no_run
//! let counter = Mutex::new(RefCell::new(0));
//!
//! let mut cpu_control = CpuControl::new(system.cpu_control);
//! let mut cpu1_fnctn = || {
//! cpu1_task(&mut timer1, &counter);
//! };
//! let _guard = cpu_control.start_app_core(&mut cpu1_fnctn).unwrap();
//!
//! loop {
//! block!(timer0.wait()).unwrap();
//!
//! let count = critical_section::with(|cs| *counter.borrow_ref(cs));
//! println!("Hello World - Core 0! Counter is {}", count);
//! }
//! ```
//!
//! Where `cpu1_task()` may be defined as:
//! ```no_run
//! fn cpu1_task(
//! timer: &mut Timer<Timer0<TIMG1>>,
//! counter: &critical_section::Mutex<RefCell<i32>>,
//! ) -> ! {
//! println!("Hello World - Core 1!");
//! loop {
//! block!(timer.wait()).unwrap();
//!
//! critical_section::with(|cs| {
//! let new_val = counter.borrow_ref_mut(cs).wrapping_add(1);
//! *counter.borrow_ref_mut(cs) = new_val;
//! });
//! }
//! }
//! ```
use core::marker::PhantomData;

View File

@ -1,4 +1,37 @@
//! Reading of eFuses
//! # Reading of eFuses (ESP32-S3)
//!
//! ## Overview
//!
//! The `efuse` module provides functionality for reading eFuse data
//! from the `ESP32-S3` chip, allowing access to various chip-specific
//! information such as :
//! * MAC address
//! * core count
//! * CPU frequency
//! * chip type
//!
//! and more. It is useful for retrieving chip-specific configuration and
//! identification data during runtime.
//!
//! The `Efuse` struct represents the eFuse peripheral and is responsible for
//! reading various eFuse fields and values.
//!
//! ## Example
//!
//! ### Read chip's MAC address from the eFuse storage.
//! ```no_run
//! let mac_address = Efuse::get_mac_address();
//! writeln!(
//! serial_tx,
//! "MAC: {:#X}:{:#X}:{:#X}:{:#X}:{:#X}:{:#X}",
//! mac_address[0],
//! mac_address[1],
//! mac_address[2],
//! mac_address[3],
//! mac_address[4],
//! mac_address[5]
//! );
//! ```
pub use crate::soc::efuse_field::*;
use crate::{analog::adc::Attenuation, peripherals::EFUSE};
@ -7,22 +40,6 @@ pub struct Efuse;
impl Efuse {
/// Reads chip's MAC address from the eFuse storage.
///
/// # Example
///
/// ```
/// let mac_address = Efuse::get_mac_address();
/// writeln!(
/// serial_tx,
/// "MAC: {:#X}:{:#X}:{:#X}:{:#X}:{:#X}:{:#X}",
/// mac_address[0],
/// mac_address[1],
/// mac_address[2],
/// mac_address[3],
/// mac_address[4],
/// mac_address[5]
/// );
/// ```
pub fn get_mac_address() -> [u8; 6] {
Self::read_field_be(MAC_FACTORY)
}

View File

@ -1,3 +1,45 @@
//! # GPIO configuration module (ESP32-S3)
//!
//! ## Overview
//!
//! The `GPIO` module provides functions and configurations for controlling the
//! `General Purpose Input/Output` pins on the `ESP32-S3` chip. It allows you to
//! configure pins as inputs or outputs, set their state and read their state.
//!
//! Let's get through the functionality and configurations provided by this GPIO
//! module:
//! - `get_io_mux_reg(gpio_num: u8) -> &'static
//! crate::peripherals::io_mux::GPIO0:`:
//! * Returns the IO_MUX register for the specified GPIO pin number.
//! - `gpio_intr_enable(int_enable: bool, nmi_enable: bool) -> u8`:
//! * This function enables or disables GPIO interrupts and Non-Maskable
//! Interrupts (NMI). It takes two boolean arguments int_enable and
//! nmi_enable to control the interrupt and NMI enable settings. The
//! function returns an u8 value representing the interrupt enable
//! settings.
//! - `gpio` block:
//! * Defines the pin configurations for various GPIO pins. Each line
//! represents a pin and its associated options such as input/output
//! mode, analog capability, and corresponding functions.
//! - `analog` block:
//! * Block defines the analog capabilities of various GPIO pins. Each
//! line represents a pin and its associated options such as mux
//! selection, function selection, and input enable.
//! - `enum InputSignal`:
//! * This enumeration defines input signals for the GPIO mux. Each input
//! signal is assigned a specific value.
//! - `enum OutputSignal`:
//! * This enumeration defines output signals for the GPIO mux. Each
//! output signal is assigned a specific value.
//!
//! This module also implements the `InterruptStatusRegisterAccess` trait for
//! two different banks:
//! * `InterruptStatusRegisterAccessBank0`
//! * `InterruptStatusRegisterAccessBank1`.
//! This trait provides functions to read the interrupt status and NMI status
//! registers for both the `PRO CPU` and `APP CPU`. The implementation uses the
//! `gpio` peripheral to access the appropriate registers.
use crate::{
gpio::{
AlternateFunction,

View File

@ -1,3 +1,13 @@
//! # SOC (System-on-Chip) module (ESP32-S3)
//!
//! ## Overview
//!
//! The `SOC` module provides access, functions and structures that are useful
//! for interacting with various system-related peripherals on `ESP32-S3` chip.
//!
//! Also few constants are defined in this module for `ESP32-S3` chip:
//! * I2S_SCLK: 160_000_000 - I2S clock frequency
//! * I2S_DEFAULT_CLK_SRC: 2 - I2S clock source
pub mod cpu_control;
pub mod efuse;
pub mod gpio;

View File

@ -1,4 +1,25 @@
//! Peripheral instance singletons
//! # Peripheral instance singletons (ESP32-S3)
//!
//! ## Overview
//!
//! The `Peripherals` module provides singleton instances of various peripherals
//! and allows users to access and use them in their applications.
//!
//! These peripherals provide various functionalities and interfaces for
//! interacting with different hardware components on the `ESP32-S3` chip, such
//! as timers, `GPIO` pins, `I2C`, `SPI`, `UART`, and more. Users can access and
//! utilize these peripherals by importing the respective singleton instances
//! from this module.
//!
//! It's important to note that the module also exports the `Interrupt` enum
//! from the `ESP32-S3` `PAC (Peripheral Access Crate)` for users to handle
//! interrupts associated with these peripherals.
//!
//! ⚠️ NOTE: notice that `psram`, `radio` and `ulp_riscv_core` are marked with
//! `false` in the `peripherals!` macro. Basically, that means that there's no
//! real peripheral (no `PSRAM` nor `RADIO` peripheral in the `PAC`s) but we're
//! creating "virtual peripherals" for them in order to ensure the uniqueness of
//! the instances (Singletons).
use esp32s3 as pac;
// We need to export this for users to use

View File

@ -1,3 +1,20 @@
//! # PSRAM "virtual peripheral" driver (ESP32-S2)
//!
//! ## Overview
//!
//! The `PSRAM` module provides support for accessing and controlling the
//! `Pseudo Static Random Access Memory (PSRAM)` on the `ESP32-S2`.
//!
//! The `PSRAM` module enables users to interface with the `PSRAM` memory
//! present on the `ESP32-S2` chip. `PSRAM` provides additional external memory
//! to supplement the internal memory of the `ESP32-S2`, allowing for increased
//! storage capacity and improved performance in certain applications.
//!
//! The `PSRAM` module is accessed through a virtual address, defined as
//! `PSRAM_VADDR`. The starting virtual address for the PSRAM module is
//! 0x3f500000. The `PSRAM` module size depends on the configuration specified
//! during the compilation process. The available `PSRAM` sizes are `2MB`,
//! `4MB`, and `8MB`.
static mut PSRAM_VADDR: u32 = 0x3C000000;
pub fn psram_vaddr_start() -> usize {

View File

@ -1,3 +1,15 @@
//! # Radio clocks driver (ESP32-S3)
//!
//! ## Overview
//!
//! The `Radio Clocks` module provides control and configuration functions for
//! various radio peripherals, such as `PHY`, `Bluetooth (BT)`, and `Wi-Fi`. The
//! module allows enabling and disabling these peripherals, resetting the `Media
//! Access Control (MAC)` and initializing clocks.
//!
//! The module defines a `RadioClockController` trait implemented by the
//! `RadioClockControl` struct. This trait provides methods to enable, disable,
//! reset the MAC, initialize clocks and perform other related operations.
use crate::system::{RadioClockControl, RadioClockController, RadioPeripherals};
// Note: this comment has been copied from esp-idf, including the mistake.

View File

@ -1,4 +1,39 @@
//! Control the ULP RISCV core
//! Control the ULP core
//!
//! ## Overview
//!
//! The `ULP CORE` peripheral allows control over the `Ultra-Low Power
//! (ULP) core` in `ESP` chips. The ULP core is a low-power processor
//! designed for executing tasks in deep sleep mode, enabling efficient power
//! management in ESP systems.
//!
//! The `UlpCore` struct provides an interface to interact with the `ULP
//! CORE` peripheral. It allows starting and configuring the ULP core for
//! operation. The `UlpCore` struct is initialized with a peripheral reference
//! to the `ULP CORE` instance.
//!
//! ## Example
//! ```no_run
//! let mut ulp_core = esp32s3_hal::ulp_core::UlpCore::new(peripherals.ULP_RISCV_CORE);
//! ulp_core.stop();
//! println!("ulp core stopped");
//!
//! // copy code to RTC ram
//! let lp_ram = 0x5000_0000 as *mut u8;
//! unsafe {
//! core::ptr::copy_nonoverlapping(CODE as *const _ as *const u8, lp_ram, CODE.len());
//! }
//! println!("copied code (len {})", CODE.len());
//!
//! // start ULP core
//! ulp_core.run(esp32s3_hal::ulp_core::UlpCoreWakeupSource::HpCpu);
//! println!("ulpcore run");
//!
//! let data = (0x5000_0010 - 0) as *mut u32;
//! loop {
//! println!("Current {}", unsafe { data.read_volatile() });
//! }
//! ```
use esp32s3 as pac;

View File

@ -1,9 +1,11 @@
//! # Serial Peripheral Interface
//!
//! ## Overview
//! There are multiple ways to use SPI, depending on your needs. Regardless of
//! which way you choose, you must first create an SPI instance with
//! [`Spi::new`].
//!
//! ## Example
//! ```rust
//! let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
//! let sclk = io.pins.gpio12;

View File

@ -1,8 +1,27 @@
//! System Control
//! # System Control
//!
//! The SYSTEM/DPORT peripheral needs to be split into several logical parts.
//! ## Overview
//! This `system` driver provides an interface to control and configure various
//! system-related features and peripherals on ESP chips. It includes
//! functionality to control peripheral clocks, manage software interrupts,
//! configure chip clocks, and control radio peripherals.
//!
//! Example
//! ### Software Interrupts
//! The `SoftwareInterrupt` enum represents the available software interrupt
//! sources.
//!
//! The SoftwareInterruptControl struct allows raising or resetting software
//! interrupts using the `raise()` and `reset()` methods. The behavior of these
//! methods depends on the specific chip variant.
//!
//! ### Peripheral Clock Control
//! The `PeripheralClockControl` struct controls the enablement of peripheral
//! clocks.
//!
//! It provides an `enable()` method to enable and reset specific peripherals.
//! The available peripherals are represented by the `Peripheral` enum
//!
//! ## Example
//! ```no_run
//! let peripherals = Peripherals::take();
//! let system = peripherals.SYSTEM.split();

View File

@ -1,4 +1,30 @@
//! System Timer peripheral driver
//! # System Timer peripheral driver
//!
//! ## Overview
//! This software module provides an interface to interact with the system timer
//! (SYSTIMER) peripheral on ESP microcontroller chips.
//!
//! Each ESP chip provides a timer (`52-bit` or `64-bit`, depends on chip),
//! which can be used to generate tick interrupts for operating system, or be
//! used as a general timer to generate periodic interrupts or one-time
//! interrupts. With the help of the RTC timer, system timer can be kept up to
//! date after Light-sleep or Deep-sleep.
//!
//! The driver supports features such as retrieving the current system time,
//! setting alarms for specific time points or periodic intervals, enabling and
//! clearing interrupts, configuring various settings of the system timer.
//!
//! By using the SYSTIMER peripheral driver, you can leverage the system timer
//! functionality of ESP chips for accurate timing measurements, event
//! triggering and synchronization in your applications.
//!
//! ## Example
//! ```no_run
//! let peripherals = Peripherals::take();
//!
//! let syst = SystemTimer::new(peripherals.SYSTIMER);
//! println!("SYSTIMER Current value = {}", SystemTimer::now());
//! ```
use core::{intrinsics::transmute, marker::PhantomData};

View File

@ -1,4 +1,46 @@
//! General-purpose timers
//! # General-purpose timers
//!
//! ## Overview
//! The `general-purpose timer` peripheral consists of a timer group, which can
//! have up to two timers (depending on the chip) and a watchdog timer. The
//! timer group allows for the management of multiple timers and synchronization
//! between them.
//!
//! This peripheral can be used to perform a variety of
//! tasks, such as triggering an interrupt after a particular interval
//! (periodically and aperiodically), precisely time an interval, act as a
//! hardware clock and so on.
//!
//! Each timer group consists of two general purpose timers and one Main System
//! Watchdog Timer(MSWDT). All general purpose timers are based on 16-bit
//! prescalers and 54-bit auto-reload-capable up-down counters.
//!
//! ## Example
//!
//! ```no_run
//! let mut rtc = Rtc::new(peripherals.RTC_CNTL);
//!
//! // Create timer groups
//! let timer_group0 = TimerGroup::new(
//! peripherals.TIMG0,
//! &clocks,
//! &mut system.peripheral_clock_control,
//! );
//! // Get watchdog timers of timer groups
//! let mut wdt0 = timer_group0.wdt;
//! let timer_group1 = TimerGroup::new(
//! peripherals.TIMG1,
//! &clocks,
//! &mut system.peripheral_clock_control,
//! );
//! let mut wdt1 = timer_group1.wdt;
//!
//! // Disable watchdog timers
//! rtc.swd.disable();
//! rtc.rwdt.disable();
//! wdt0.disable();
//! wdt1.disable();
//! ```
use core::{
marker::PhantomData,

View File

@ -1,8 +1,80 @@
//! # Two-wire Automotive Interface (TWAI)
//!
//! ## Overview
//! The TWAI peripheral driver provides functions and structs specifically
//! designed for the Two-Wire Automotive Interface (TWAI) on ESP chips. TWAI is
//! a communication protocol commonly used in automotive applications for
//! sending and receiving messages between electronic control units (ECUs) in a
//! vehicle.
//!
//! The driver enables you to configure and utilize the TWAI module on ESP
//! chips. It offers functions for initializing the TWAI peripheral, setting up
//! the ti1ming parameters, configuring acceptance filters, handling interrupts,
//! and transmitting/receiving messages on the TWAI bus.
//!
//! This driver manages the ISO 11898-1 (CAN Specification 2.0) compatible TWAI
//! controllers. It supports Standard Frame Format (11-bit) and Extended Frame
//! Format (29-bit) frame identifiers.
//!
//! ## Example
//! ```no_run
//! // Use GPIO pins 2 and 3 to connect to the respective pins on the CAN
//! // transceiver.
//! let can_tx_pin = io.pins.gpio2;
//! let can_rx_pin = io.pins.gpio3;
//!
//! // The speed of the CAN bus.
//! const CAN_BAUDRATE: twai::BaudRate = twai::BaudRate::B1000K;
//!
//! // Begin configuring the TWAI peripheral. The peripheral is in a reset like
//! // state that prevents transmission but allows configuration.
//! let mut can_config = twai::TwaiConfiguration::new(
//! peripherals.TWAI0,
//! can_tx_pin,
//! can_rx_pin,
//! &mut system.peripheral_clock_control,
//! &clocks,
//! CAN_BAUDRATE,
//! );
//!
//! // Partially filter the incoming messages to reduce overhead of receiving undesired messages
//! const FILTER: twai::filter::SingleStandardFilter =
//! twai::filter::SingleStandardFilter::new(b"xxxxxxxxxx0", b"x", [b"xxxxxxxx", b"xxxxxxxx"]);
//! can_config.set_filter(FILTER);
//!
//! // Start the peripheral. This locks the configuration settings of the peripheral
//! // and puts it into operation mode, allowing packets to be sent and
//! // received.
//! let mut can = can_config.start();
//!
//! loop {
//! // Wait for a frame to be received.
//! let frame = block!(can.receive()).unwrap();
//!
//! println!("Received a frame:");
//!
//! // Print different messages based on the frame id type.
//! match frame.id() {
//! Id::Standard(id) => {
//! println!("\tStandard Id: {:?}", id);
//! }
//! Id::Extended(id) => {
//! println!("\tExtended Id: {:?}", id);
//! }
//! }
//!
//! // Print out the frame data or the requested data length code for a remote
//! // transmission request frame.
//! if frame.is_data_frame() {
//! println!("\tData: {:?}", frame.data());
//! } else {
//! println!("\tRemote Frame. Data Length Code: {}", frame.dlc());
//! }
//!
//! // Transmit the frame back.
//! let _result = block!(can.transmit(&frame)).unwrap();
//! }
//! ```
#[cfg(feature = "eh1")]
use embedded_can::{nb::Can, Error, ErrorKind, ExtendedId, Frame, Id, StandardId};

View File

@ -1,4 +1,52 @@
//! UART driver
//! # UART driver
//!
//! ## Overview
//! In embedded system applications, data is required to be transferred in a
//! simple way with minimal system resources. This can be achieved by a
//! Universal Asynchronous Receiver/Transmitter (UART), which flexibly exchanges
//! data with other peripheral devices in full-duplex mode.
//! The UART driver provides an interface to communicate with UART peripherals
//! on ESP chips. It enables serial communication between the microcontroller
//! and external devices using the UART protocol.
//!
//! ## Example
//! ```no_run
//! let config = Config {
//! baudrate: 115200,
//! data_bits: DataBits::DataBits8,
//! parity: Parity::ParityNone,
//! stop_bits: StopBits::STOP1,
//! };
//!
//! let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
//! let pins = TxRxPins::new_tx_rx(
//! io.pins.gpio1.into_push_pull_output(),
//! io.pins.gpio2.into_floating_input(),
//! );
//!
//! let mut serial1 = Uart::new_with_config(
//! peripherals.UART1,
//! Some(config),
//! Some(pins),
//! &clocks,
//! &mut system.peripheral_clock_control,
//! );
//!
//! timer0.start(250u64.millis());
//!
//! println!("Start");
//! loop {
//! serial1.write(0x42).ok();
//! let read = block!(serial1.read());
//!
//! match read {
//! Ok(read) => println!("Read 0x{:02x}", read),
//! Err(err) => println!("Error {:?}", err),
//! }
//!
//! block!(timer0.wait()).unwrap();
//! }
//! ```
use self::config::Config;
#[cfg(uart2)]

View File

@ -1,4 +1,22 @@
//! USB Serial JTAG peripheral driver
//! # USB Serial JTAG peripheral driver
//!
//! ## Overview
//! The USB Serial JTAG peripheral driver provides an interface to communicate
//! with the USB Serial/JTAG peripheral on ESP chips. It enables serial
//! communication and JTAG debugging capabilities, allowing developers to
//! interact with the ESP chip for programming, debugging, and data transfer
//! purposes, can be also used to program the SoC's flash, read program output,
//! as well as attach a debugger to a running program.
//!
//! ## Example
//! ```no_run
//! let peripherals = Peripherals::take();
//! let mut system = peripherals.SYSTEM.split();
//! let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
//! ...
//! // Initialize USB Serial/JTAG peripheral
//! let mut usb_serial =
//! UsbSerialJtag::new(peripherals.USB_DEVICE, &mut system.peripheral_clock_control);
use core::convert::Infallible;

View File

@ -1,5 +1,49 @@
//! Procedural macros for placing statics and functions into RAM, and for
//! marking interrupt handlers.
//! Procedural macros
//!
//! ## Overview
//! The `esp-hal-procmacros` module provides procedural macros for placing
//! statics and functions into RAM and for marking interrupt handlers on ESP
//! microcontrollers.
//!
//! These macros offer developers a convenient way to control memory placement
//! and define interrupt handlers in their embedded applications, allowing for
//! optimized memory usage and precise handling of hardware interrupts.
//!
//! Key Components:
//! - [ram](attr.ram.html) - Attribute macro for placing statics and functions
//! into specific memory sections, such as SRAM or RTC RAM (slow or fast)
//! with different initialization options. Supported options are:
//! - `rtc_fast` - Use RTC fast RAM
//! - `rtc_slow` - Use RTC slow RAM (not all targets support slow RTC RAM)
//! - `uninitialized` - Skip initialization of the memory
//! - `zeroed` - Initialize the memory to zero
//! - [interrupt](attr.interrupt.html) - Attribute macro for marking interrupt
//! handlers. Interrupt handlers are used to handle specific hardware
//! interrupts generated by peripherals.<br> The macro allows users to
//! specify the interrupt name explicitly or use the function name to match
//! the interrupt.
//!
//! ## Examples
//!
//! #### `ram` macro
//! ```no_run
//! #[ram(rtc_fast)]
//! static mut SOME_INITED_DATA: [u8; 2] = [0xaa, 0xbb];
//!
//! #[ram(rtc_fast, uninitialized)]
//! static mut SOME_UNINITED_DATA: [u8; 2] = [0; 2];
//!
//! #[ram(rtc_fast, zeroed)]
//! static mut SOME_ZEROED_DATA: [u8; 8] = [0; 8];
//! ```
//!
//! #### `interrupt` macro
//! ```no_run
//! #[interrupt]
//! fn INTR_NAME() {
//! // Interrupt handling code here
//! }
//! ```
#![doc(html_logo_url = "https://avatars.githubusercontent.com/u/46717278")]