From 2bd10526a7324dd079d3239744867b5474d63e87 Mon Sep 17 00:00:00 2001 From: Kirill Mikhailov <62840029+playfulFence@users.noreply.github.com> Date: Wed, 9 Aug 2023 15:33:50 +0200 Subject: [PATCH] Documenting a number of peripherals and packages (#680) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 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 Fix typo Co-authored-by: Dániel Buga Fix typo Co-authored-by: Dániel Buga Fix typo Co-authored-by: Dániel Buga fix typo Co-authored-by: Dániel Buga Fix typo Co-authored-by: Dániel Buga Fix typo Co-authored-by: Scott Mabin Fixing typos, mistakes, improving docs. * Fix formatting, mistakes and typos * Fixing a bunch of logical, grammatical and formatting mistakes --- CHANGELOG.md | 2 + esp-hal-common/src/aes/mod.rs | 59 +++++++- esp-hal-common/src/analog/adc/esp32.rs | 33 +++- esp-hal-common/src/analog/adc/riscv.rs | 142 ++++++++++++++++-- esp-hal-common/src/analog/adc/xtensa.rs | 66 +++++++- esp-hal-common/src/analog/dac.rs | 14 ++ esp-hal-common/src/analog/mod.rs | 84 +++++++++++ esp-hal-common/src/assist_debug.rs | 12 +- esp-hal-common/src/clock/mod.rs | 49 ++++++ esp-hal-common/src/delay.rs | 17 ++- esp-hal-common/src/dma/gdma.rs | 23 ++- esp-hal-common/src/dma/mod.rs | 73 ++++++++- esp-hal-common/src/dma/pdma.rs | 18 ++- esp-hal-common/src/embassy/mod.rs | 69 +++++++++ esp-hal-common/src/gpio.rs | 16 +- esp-hal-common/src/i2c.rs | 35 ++++- esp-hal-common/src/i2s.rs | 68 ++++++++- esp-hal-common/src/interrupt/mod.rs | 54 ++++++- esp-hal-common/src/interrupt/riscv.rs | 2 +- esp-hal-common/src/ledc/channel.rs | 11 ++ esp-hal-common/src/ledc/mod.rs | 42 +++--- esp-hal-common/src/ledc/timer.rs | 11 ++ esp-hal-common/src/mcpwm/mod.rs | 9 +- esp-hal-common/src/mcpwm/operator.rs | 12 ++ esp-hal-common/src/mcpwm/timer.rs | 10 +- esp-hal-common/src/otg_fs.rs | 28 +++- esp-hal-common/src/pcnt/channel.rs | 10 ++ esp-hal-common/src/pcnt/mod.rs | 134 ++++++++++++++++- esp-hal-common/src/pcnt/unit.rs | 12 ++ esp-hal-common/src/peripheral.rs | 37 ++++- esp-hal-common/src/radio.rs | 17 ++- esp-hal-common/src/reset.rs | 37 ++++- esp-hal-common/src/rmt.rs | 7 +- esp-hal-common/src/rng.rs | 3 +- esp-hal-common/src/rom/crc.rs | 7 +- esp-hal-common/src/rom/md5.rs | 8 +- esp-hal-common/src/rom/mod.rs | 24 ++- esp-hal-common/src/rsa/mod.rs | 38 ++++- esp-hal-common/src/rtc_cntl/mod.rs | 71 ++++++++- esp-hal-common/src/rtc_cntl/sleep.rs | 21 +++ esp-hal-common/src/sha.rs | 62 +++++++- esp-hal-common/src/soc/esp32/cpu_control.rs | 51 ++++++- esp-hal-common/src/soc/esp32/efuse.rs | 52 ++++--- esp-hal-common/src/soc/esp32/gpio.rs | 47 ++++++ esp-hal-common/src/soc/esp32/mod.rs | 7 + esp-hal-common/src/soc/esp32/peripherals.rs | 23 ++- esp-hal-common/src/soc/esp32/psram.rs | 21 +++ esp-hal-common/src/soc/esp32/radio_clocks.rs | 13 ++ esp-hal-common/src/soc/esp32c2/efuse.rs | 51 ++++--- esp-hal-common/src/soc/esp32c2/gpio.rs | 41 +++++ esp-hal-common/src/soc/esp32c2/mod.rs | 7 + esp-hal-common/src/soc/esp32c2/peripherals.rs | 22 ++- .../src/soc/esp32c2/radio_clocks.rs | 13 ++ esp-hal-common/src/soc/esp32c3/efuse.rs | 51 ++++--- esp-hal-common/src/soc/esp32c3/gpio.rs | 42 ++++++ esp-hal-common/src/soc/esp32c3/mod.rs | 11 ++ esp-hal-common/src/soc/esp32c3/peripherals.rs | 22 ++- .../src/soc/esp32c3/radio_clocks.rs | 13 ++ esp-hal-common/src/soc/esp32c6/efuse.rs | 51 ++++--- esp-hal-common/src/soc/esp32c6/gpio.rs | 42 ++++++ esp-hal-common/src/soc/esp32c6/lp_core.rs | 61 +++++++- esp-hal-common/src/soc/esp32c6/mod.rs | 12 ++ esp-hal-common/src/soc/esp32c6/peripherals.rs | 23 ++- .../src/soc/esp32c6/radio_clocks.rs | 13 ++ esp-hal-common/src/soc/esp32h2/efuse.rs | 51 ++++--- esp-hal-common/src/soc/esp32h2/gpio.rs | 42 ++++++ esp-hal-common/src/soc/esp32h2/mod.rs | 12 ++ esp-hal-common/src/soc/esp32h2/peripherals.rs | 22 ++- .../src/soc/esp32h2/radio_clocks.rs | 13 ++ esp-hal-common/src/soc/esp32s2/efuse.rs | 35 ++++- esp-hal-common/src/soc/esp32s2/gpio.rs | 54 +++++++ esp-hal-common/src/soc/esp32s2/mod.rs | 10 ++ esp-hal-common/src/soc/esp32s2/peripherals.rs | 23 ++- esp-hal-common/src/soc/esp32s2/psram.rs | 20 +++ .../src/soc/esp32s2/radio_clocks.rs | 13 ++ esp-hal-common/src/soc/esp32s2/ulp_core.rs | 40 ++++- esp-hal-common/src/soc/esp32s3/cpu_control.rs | 51 ++++++- esp-hal-common/src/soc/esp32s3/efuse.rs | 51 ++++--- esp-hal-common/src/soc/esp32s3/gpio.rs | 42 ++++++ esp-hal-common/src/soc/esp32s3/mod.rs | 10 ++ esp-hal-common/src/soc/esp32s3/peripherals.rs | 23 ++- esp-hal-common/src/soc/esp32s3/psram.rs | 17 +++ .../src/soc/esp32s3/radio_clocks.rs | 12 ++ esp-hal-common/src/soc/esp32s3/ulp_core.rs | 37 ++++- esp-hal-common/src/spi.rs | 2 + esp-hal-common/src/system.rs | 25 ++- esp-hal-common/src/systimer.rs | 28 +++- esp-hal-common/src/timer.rs | 44 +++++- esp-hal-common/src/twai/mod.rs | 72 +++++++++ esp-hal-common/src/uart.rs | 50 +++++- esp-hal-common/src/usb_serial_jtag.rs | 20 ++- esp-hal-procmacros/src/lib.rs | 48 +++++- 92 files changed, 2789 insertions(+), 214 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e98fd4f00..6fe33201b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/esp-hal-common/src/aes/mod.rs b/esp-hal-common/src/aes/mod.rs index ecd5caef7..5682d0d40 100644 --- a/esp-hal-common/src/aes/mod.rs +++ b/esp-hal-common/src/aes/mod.rs @@ -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::::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; diff --git a/esp-hal-common/src/analog/adc/esp32.rs b/esp-hal-common/src/analog/adc/esp32.rs index 75b3a457f..34a56ec75 100644 --- a/esp-hal-common/src/analog/adc/esp32.rs +++ b/esp-hal-common/src/analog/adc/esp32.rs @@ -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::::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; diff --git a/esp-hal-common/src/analog/adc/riscv.rs b/esp-hal-common/src/analog/adc/riscv.rs index 32b56f888..f0e0c7f8c 100644 --- a/esp-hal-common/src/analog/adc/riscv.rs +++ b/esp-hal-common/src/analog/adc/riscv.rs @@ -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::::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::::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::::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::::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; diff --git a/esp-hal-common/src/analog/adc/xtensa.rs b/esp-hal-common/src/analog/adc/xtensa.rs index cfba895a5..153734af2 100644 --- a/esp-hal-common/src/analog/adc/xtensa.rs +++ b/esp-hal-common/src/analog/adc/xtensa.rs @@ -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::::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::::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; diff --git a/esp-hal-common/src/analog/dac.rs b/esp-hal-common/src/analog/dac.rs index 4804ad7b8..598bd357f 100644 --- a/esp-hal-common/src/analog/dac.rs +++ b/esp-hal-common/src/analog/dac.rs @@ -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}, diff --git a/esp-hal-common/src/analog/mod.rs b/esp-hal-common/src/analog/mod.rs index 18690cb81..9dd7bb720 100644 --- a/esp-hal-common/src/analog/mod.rs +++ b/esp-hal-common/src/analog/mod.rs @@ -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::::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::::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")] diff --git a/esp-hal-common/src/assist_debug.rs b/esp-hal-common/src/assist_debug.rs index 37d714ab9..2a779a64e 100644 --- a/esp-hal-common/src/assist_debug.rs +++ b/esp-hal-common/src/assist_debug.rs @@ -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}, diff --git a/esp-hal-common/src/clock/mod.rs b/esp-hal-common/src/clock/mod.rs index 13b98631e..3f90cc885 100644 --- a/esp-hal-common/src/clock/mod.rs +++ b/esp-hal-common/src/clock/mod.rs @@ -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::{ diff --git a/esp-hal-common/src/delay.rs b/esp-hal-common/src/delay.rs index 4ffb9a97d..5d6342730 100644 --- a/esp-hal-common/src/delay.rs +++ b/esp-hal-common/src/delay.rs @@ -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/ diff --git a/esp-hal-common/src/dma/gdma.rs b/esp-hal-common/src/dma/gdma.rs index a9c0ad55f..aa8dac7f2 100644 --- a/esp-hal-common/src/dma/gdma.rs +++ b/esp-hal-common/src/dma/gdma.rs @@ -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); +//! ``` +//! +//! PS: Note that the number of DMA channels is chip-specific. use crate::{ dma::*, diff --git a/esp-hal-common/src/dma/mod.rs b/esp-hal-common/src/dma/mod.rs index a09b9d872..f24924937 100644 --- a/esp-hal-common/src/dma/mod.rs +++ b/esp-hal-common/src/dma/mod.rs @@ -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.
The `Tx` trait includes +//! functions to start, stop, and check the completion status of an +//! outbound DMA transfer.
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.
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.
It provides functions to +//! initialize DMA channels, configure burst mode, priority, and +//! peripheral for both input and output data transfers.
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, @@ -607,6 +673,7 @@ where fn waker() -> &'static embassy_sync::waitqueue::AtomicWaker; } +/// DMA transmit channel pub struct ChannelTx<'a, T, R> where T: TxChannel, diff --git a/esp-hal-common/src/dma/pdma.rs b/esp-hal-common/src/dma/pdma.rs index e2c254b7e..2a8d5bd81 100644 --- a/esp-hal-common/src/dma/pdma.rs +++ b/esp-hal-common/src/dma/pdma.rs @@ -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::*, diff --git a/esp-hal-common/src/embassy/mod.rs b/esp-hal-common/src/embassy/mod.rs index d036e4db1..2f7e78a11 100644 --- a/esp-hal-common/src/embassy/mod.rs +++ b/esp-hal-common/src/embassy/mod.rs @@ -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.
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.
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>) { +//! 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}; diff --git a/esp-hal-common/src/gpio.rs b/esp-hal-common/src/gpio.rs index 1ad0319a1..3ff98216c 100644 --- a/esp-hal-common/src/gpio.rs +++ b/esp-hal-common/src/gpio.rs @@ -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}; diff --git a/esp-hal-common/src/i2c.rs b/esp-hal-common/src/i2c.rs index c4b4cee02..ae13393e1 100644 --- a/esp-hal-common/src/i2c.rs +++ b/esp-hal-common/src/i2c.rs @@ -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; diff --git a/esp-hal-common/src/i2s.rs b/esp-hal-common/src/i2s.rs index ee1e59a0c..7ce80ea29 100644 --- a/esp-hal-common/src/i2s.rs +++ b/esp-hal-common/src/i2s.rs @@ -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::*; diff --git a/esp-hal-common/src/interrupt/mod.rs b/esp-hal-common/src/interrupt/mod.rs index 773438435..308ab9fff 100644 --- a/esp-hal-common/src/interrupt/mod.rs +++ b/esp-hal-common/src/interrupt/mod.rs @@ -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::*; diff --git a/esp-hal-common/src/interrupt/riscv.rs b/esp-hal-common/src/interrupt/riscv.rs index 34013a894..72568762b 100644 --- a/esp-hal-common/src/interrupt/riscv.rs +++ b/esp-hal-common/src/interrupt/riscv.rs @@ -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. diff --git a/esp-hal-common/src/ledc/channel.rs b/esp-hal-common/src/ledc/channel.rs index 55ee52d30..291058f40 100644 --- a/esp-hal-common/src/ledc/channel.rs +++ b/esp-hal-common/src/ledc/channel.rs @@ -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)] diff --git a/esp-hal-common/src/ledc/mod.rs b/esp-hal-common/src/ledc/mod.rs index bb51cdc26..698c88136 100644 --- a/esp-hal-common/src/ledc/mod.rs +++ b/esp-hal-common/src/ledc/mod.rs @@ -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::(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::(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 diff --git a/esp-hal-common/src/ledc/timer.rs b/esp-hal-common/src/ledc/timer.rs index de73ad5a3..4a3b5d09d 100644 --- a/esp-hal-common/src/ledc/timer.rs +++ b/esp-hal-common/src/ledc/timer.rs @@ -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)] diff --git a/esp-hal-common/src/mcpwm/mod.rs b/esp-hal-common/src/mcpwm/mod.rs index 9acc6f0a4..bbaca192a 100644 --- a/esp-hal-common/src/mcpwm/mod.rs +++ b/esp-hal-common/src/mcpwm/mod.rs @@ -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}; //! diff --git a/esp-hal-common/src/mcpwm/operator.rs b/esp-hal-common/src/mcpwm/operator.rs index 7cb9f8960..0213613d2 100644 --- a/esp-hal-common/src/mcpwm/operator.rs +++ b/esp-hal-common/src/mcpwm/operator.rs @@ -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::{ diff --git a/esp-hal-common/src/mcpwm/timer.rs b/esp-hal-common/src/mcpwm/timer.rs index ccdcc3280..ebf86bcfa 100644 --- a/esp-hal-common/src/mcpwm/timer.rs +++ b/esp-hal-common/src/mcpwm/timer.rs @@ -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 Timer { /// 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 diff --git a/esp-hal-common/src/otg_fs.rs b/esp-hal-common/src/otg_fs.rs index 740d6819a..a6573f284 100644 --- a/esp-hal-common/src/otg_fs.rs +++ b/esp-hal-common/src/otg_fs.rs @@ -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; diff --git a/esp-hal-common/src/pcnt/channel.rs b/esp-hal-common/src/pcnt/channel.rs index e7583c125..397221018 100644 --- a/esp-hal-common/src/pcnt/channel.rs +++ b/esp-hal-common/src/pcnt/channel.rs @@ -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}, diff --git a/esp-hal-common/src/pcnt/mod.rs b/esp-hal-common/src/pcnt/mod.rs index ddd2bc864..7dcca1017 100644 --- a/esp-hal-common/src/pcnt/mod.rs +++ b/esp-hal-common/src/pcnt/mod.rs @@ -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::{ diff --git a/esp-hal-common/src/pcnt/unit.rs b/esp-hal-common/src/pcnt/unit.rs index 9703d9caa..7e46170d7 100644 --- a/esp-hal-common/src/pcnt/unit.rs +++ b/esp-hal-common/src/pcnt/unit.rs @@ -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; diff --git a/esp-hal-common/src/peripheral.rs b/esp-hal-common/src/peripheral.rs index c39b035db..8f3e6d583 100644 --- a/esp-hal-common/src/peripheral.rs +++ b/esp-hal-common/src/peripheral.rs @@ -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, diff --git a/esp-hal-common/src/radio.rs b/esp-hal-common/src/radio.rs index 0dcd42724..ece23d027 100644 --- a/esp-hal-common/src/radio.rs +++ b/esp-hal-common/src/radio.rs @@ -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; diff --git a/esp-hal-common/src/reset.rs b/esp-hal-common/src/reset.rs index 6aa760a78..0e304bea8 100644 --- a/esp-hal-common/src/reset.rs +++ b/esp-hal-common/src/reset.rs @@ -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 { 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() } diff --git a/esp-hal-common/src/rmt.rs b/esp-hal-common/src/rmt.rs index 48f9982bd..6cbf590ac 100644 --- a/esp-hal-common/src/rmt.rs +++ b/esp-hal-common/src/rmt.rs @@ -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: //! //! -//! # 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 = [ diff --git a/esp-hal-common/src/rng.rs b/esp-hal-common/src/rng.rs index 7e0c41ea2..c4aae893c 100644 --- a/esp-hal-common/src/rng.rs +++ b/esp-hal-common/src/rng.rs @@ -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 diff --git a/esp-hal-common/src/rom/crc.rs b/esp-hal-common/src/rom/crc.rs index f80200f71..7a7ce147d 100644 --- a/esp-hal-common/src/rom/crc.rs +++ b/esp-hal-common/src/rom/crc.rs @@ -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 //! diff --git a/esp-hal-common/src/rom/md5.rs b/esp-hal-common/src/rom/md5.rs index 3d15efa08..e760473cc 100644 --- a/esp-hal-common/src/rom/md5.rs +++ b/esp-hal-common/src/rom/md5.rs @@ -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: //! diff --git a/esp-hal-common/src/rom/mod.rs b/esp-hal-common/src/rom/mod.rs index f0ba0f80d..e12c91240 100644 --- a/esp-hal-common/src/rom/mod.rs +++ b/esp-hal-common/src/rom/mod.rs @@ -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; diff --git a/esp-hal-common/src/rsa/mod.rs b/esp-hal-common/src/rsa/mod.rs index 59453eefc..f9aaf2f8d 100644 --- a/esp-hal-common/src/rsa/mod.rs +++ b/esp-hal-common/src/rsa/mod.rs @@ -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 +//! (Rivest–Shamir–Adleman)` 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}; diff --git a/esp-hal-common/src/rtc_cntl/mod.rs b/esp-hal-common/src/rtc_cntl/mod.rs index dd3daa79a..1ddf39669 100644 --- a/esp-hal-common/src/rtc_cntl/mod.rs +++ b/esp-hal-common/src/rtc_cntl/mod.rs @@ -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)))] diff --git a/esp-hal-common/src/rtc_cntl/sleep.rs b/esp-hal-common/src/rtc_cntl/sleep.rs index 35c93f763..15692ce23 100644 --- a/esp-hal-common/src/rtc_cntl/sleep.rs +++ b/esp-hal-common/src/rtc_cntl/sleep.rs @@ -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::{ diff --git a/esp-hal-common/src/sha.rs b/esp-hal-common/src/sha.rs index 5f922fc42..815f0cf8a 100644 --- a/esp-hal-common/src/sha.rs +++ b/esp-hal-common/src/sha.rs @@ -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; diff --git a/esp-hal-common/src/soc/esp32/cpu_control.rs b/esp-hal-common/src/soc/esp32/cpu_control.rs index 9b4cc1135..84e622965 100644 --- a/esp-hal-common/src/soc/esp32/cpu_control.rs +++ b/esp-hal-common/src/soc/esp32/cpu_control.rs @@ -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>, +//! counter: &critical_section::Mutex>, +//! ) -> ! { +//! 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; diff --git a/esp-hal-common/src/soc/esp32/efuse.rs b/esp-hal-common/src/soc/esp32/efuse.rs index 73fbccc64..1848c6dc0 100644 --- a/esp-hal-common/src/soc/esp32/efuse.rs +++ b/esp-hal-common/src/soc/esp32/efuse.rs @@ -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) } diff --git a/esp-hal-common/src/soc/esp32/gpio.rs b/esp-hal-common/src/soc/esp32/gpio.rs index caf02168c..8dce73b0f 100644 --- a/esp-hal-common/src/soc/esp32/gpio.rs +++ b/esp-hal-common/src/soc/esp32/gpio.rs @@ -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, diff --git a/esp-hal-common/src/soc/esp32/mod.rs b/esp-hal-common/src/soc/esp32/mod.rs index 6f5cfbaee..6a7aa2a13 100644 --- a/esp-hal-common/src/soc/esp32/mod.rs +++ b/esp-hal-common/src/soc/esp32/mod.rs @@ -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; diff --git a/esp-hal-common/src/soc/esp32/peripherals.rs b/esp-hal-common/src/soc/esp32/peripherals.rs index 7ef250a35..cff9cb387 100644 --- a/esp-hal-common/src/soc/esp32/peripherals.rs +++ b/esp-hal-common/src/soc/esp32/peripherals.rs @@ -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 diff --git a/esp-hal-common/src/soc/esp32/psram.rs b/esp-hal-common/src/soc/esp32/psram.rs index d31e2094c..6cf594b95 100644 --- a/esp-hal-common/src/soc/esp32/psram.rs +++ b/esp-hal-common/src/soc/esp32/psram.rs @@ -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 { diff --git a/esp-hal-common/src/soc/esp32/radio_clocks.rs b/esp-hal-common/src/soc/esp32/radio_clocks.rs index 9d748887c..d9e9fe7f2 100644 --- a/esp-hal-common/src/soc/esp32/radio_clocks.rs +++ b/esp-hal-common/src/soc/esp32/radio_clocks.rs @@ -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; diff --git a/esp-hal-common/src/soc/esp32c2/efuse.rs b/esp-hal-common/src/soc/esp32c2/efuse.rs index 8e456a47c..9f45da388 100644 --- a/esp-hal-common/src/soc/esp32c2/efuse.rs +++ b/esp-hal-common/src/soc/esp32c2/efuse.rs @@ -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) } diff --git a/esp-hal-common/src/soc/esp32c2/gpio.rs b/esp-hal-common/src/soc/esp32c2/gpio.rs index 4892e0fe9..8fdf95fe0 100644 --- a/esp-hal-common/src/soc/esp32c2/gpio.rs +++ b/esp-hal-common/src/soc/esp32c2/gpio.rs @@ -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, diff --git a/esp-hal-common/src/soc/esp32c2/mod.rs b/esp-hal-common/src/soc/esp32c2/mod.rs index 907b45c93..2eb7733d0 100644 --- a/esp-hal-common/src/soc/esp32c2/mod.rs +++ b/esp-hal-common/src/soc/esp32c2/mod.rs @@ -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; diff --git a/esp-hal-common/src/soc/esp32c2/peripherals.rs b/esp-hal-common/src/soc/esp32c2/peripherals.rs index c2b905a69..1842716a1 100644 --- a/esp-hal-common/src/soc/esp32c2/peripherals.rs +++ b/esp-hal-common/src/soc/esp32c2/peripherals.rs @@ -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 diff --git a/esp-hal-common/src/soc/esp32c2/radio_clocks.rs b/esp-hal-common/src/soc/esp32c2/radio_clocks.rs index 6e6a2e2af..b99239ede 100644 --- a/esp-hal-common/src/soc/esp32c2/radio_clocks.rs +++ b/esp-hal-common/src/soc/esp32c2/radio_clocks.rs @@ -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, diff --git a/esp-hal-common/src/soc/esp32c3/efuse.rs b/esp-hal-common/src/soc/esp32c3/efuse.rs index 5fd150120..44e280a6b 100644 --- a/esp-hal-common/src/soc/esp32c3/efuse.rs +++ b/esp-hal-common/src/soc/esp32c3/efuse.rs @@ -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) } diff --git a/esp-hal-common/src/soc/esp32c3/gpio.rs b/esp-hal-common/src/soc/esp32c3/gpio.rs index cad3186f0..41a50de52 100644 --- a/esp-hal-common/src/soc/esp32c3/gpio.rs +++ b/esp-hal-common/src/soc/esp32c3/gpio.rs @@ -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, diff --git a/esp-hal-common/src/soc/esp32c3/mod.rs b/esp-hal-common/src/soc/esp32c3/mod.rs index bcdc63ce6..271658b61 100644 --- a/esp-hal-common/src/soc/esp32c3/mod.rs +++ b/esp-hal-common/src/soc/esp32c3/mod.rs @@ -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; diff --git a/esp-hal-common/src/soc/esp32c3/peripherals.rs b/esp-hal-common/src/soc/esp32c3/peripherals.rs index 3d54f2caa..5ca7db42a 100644 --- a/esp-hal-common/src/soc/esp32c3/peripherals.rs +++ b/esp-hal-common/src/soc/esp32c3/peripherals.rs @@ -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 diff --git a/esp-hal-common/src/soc/esp32c3/radio_clocks.rs b/esp-hal-common/src/soc/esp32c3/radio_clocks.rs index 16b368bbc..785c69bf8 100644 --- a/esp-hal-common/src/soc/esp32c3/radio_clocks.rs +++ b/esp-hal-common/src/soc/esp32c3/radio_clocks.rs @@ -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, diff --git a/esp-hal-common/src/soc/esp32c6/efuse.rs b/esp-hal-common/src/soc/esp32c6/efuse.rs index 4f22dc9f9..ec7db6221 100644 --- a/esp-hal-common/src/soc/esp32c6/efuse.rs +++ b/esp-hal-common/src/soc/esp32c6/efuse.rs @@ -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) } diff --git a/esp-hal-common/src/soc/esp32c6/gpio.rs b/esp-hal-common/src/soc/esp32c6/gpio.rs index c39e05291..56687a02d 100644 --- a/esp-hal-common/src/soc/esp32c6/gpio.rs +++ b/esp-hal-common/src/soc/esp32c6/gpio.rs @@ -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, diff --git a/esp-hal-common/src/soc/esp32c6/lp_core.rs b/esp-hal-common/src/soc/esp32c6/lp_core.rs index 754198f68..4c322e03e 100644 --- a/esp-hal-common/src/soc/esp32c6/lp_core.rs +++ b/esp-hal-common/src/soc/esp32c6/lp_core.rs @@ -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; diff --git a/esp-hal-common/src/soc/esp32c6/mod.rs b/esp-hal-common/src/soc/esp32c6/mod.rs index b3e02b652..48aa712d5 100644 --- a/esp-hal-common/src/soc/esp32c6/mod.rs +++ b/esp-hal-common/src/soc/esp32c6/mod.rs @@ -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; diff --git a/esp-hal-common/src/soc/esp32c6/peripherals.rs b/esp-hal-common/src/soc/esp32c6/peripherals.rs index 5b14df9cd..7eb11bb84 100644 --- a/esp-hal-common/src/soc/esp32c6/peripherals.rs +++ b/esp-hal-common/src/soc/esp32c6/peripherals.rs @@ -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 diff --git a/esp-hal-common/src/soc/esp32c6/radio_clocks.rs b/esp-hal-common/src/soc/esp32c6/radio_clocks.rs index ea43f5d5c..bfeaf77aa 100644 --- a/esp-hal-common/src/soc/esp32c6/radio_clocks.rs +++ b/esp-hal-common/src/soc/esp32c6/radio_clocks.rs @@ -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 { diff --git a/esp-hal-common/src/soc/esp32h2/efuse.rs b/esp-hal-common/src/soc/esp32h2/efuse.rs index ec0110130..f0245dc12 100644 --- a/esp-hal-common/src/soc/esp32h2/efuse.rs +++ b/esp-hal-common/src/soc/esp32h2/efuse.rs @@ -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) } diff --git a/esp-hal-common/src/soc/esp32h2/gpio.rs b/esp-hal-common/src/soc/esp32h2/gpio.rs index a8ddfccf6..78c6cd375 100644 --- a/esp-hal-common/src/soc/esp32h2/gpio.rs +++ b/esp-hal-common/src/soc/esp32h2/gpio.rs @@ -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, diff --git a/esp-hal-common/src/soc/esp32h2/mod.rs b/esp-hal-common/src/soc/esp32h2/mod.rs index 46969890c..4213bd1c7 100644 --- a/esp-hal-common/src/soc/esp32h2/mod.rs +++ b/esp-hal-common/src/soc/esp32h2/mod.rs @@ -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; diff --git a/esp-hal-common/src/soc/esp32h2/peripherals.rs b/esp-hal-common/src/soc/esp32h2/peripherals.rs index 4e96b1aa5..44cd85746 100644 --- a/esp-hal-common/src/soc/esp32h2/peripherals.rs +++ b/esp-hal-common/src/soc/esp32h2/peripherals.rs @@ -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 diff --git a/esp-hal-common/src/soc/esp32h2/radio_clocks.rs b/esp-hal-common/src/soc/esp32h2/radio_clocks.rs index 78b7d7ac2..affd5d3b4 100644 --- a/esp-hal-common/src/soc/esp32h2/radio_clocks.rs +++ b/esp-hal-common/src/soc/esp32h2/radio_clocks.rs @@ -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 { diff --git a/esp-hal-common/src/soc/esp32s2/efuse.rs b/esp-hal-common/src/soc/esp32s2/efuse.rs index b327d1573..697caf995 100644 --- a/esp-hal-common/src/soc/esp32s2/efuse.rs +++ b/esp-hal-common/src/soc/esp32s2/efuse.rs @@ -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::*; diff --git a/esp-hal-common/src/soc/esp32s2/gpio.rs b/esp-hal-common/src/soc/esp32s2/gpio.rs index 5cea10fd7..594c59d8a 100644 --- a/esp-hal-common/src/soc/esp32s2/gpio.rs +++ b/esp-hal-common/src/soc/esp32s2/gpio.rs @@ -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, diff --git a/esp-hal-common/src/soc/esp32s2/mod.rs b/esp-hal-common/src/soc/esp32s2/mod.rs index d5755e6b4..2dd40a360 100644 --- a/esp-hal-common/src/soc/esp32s2/mod.rs +++ b/esp-hal-common/src/soc/esp32s2/mod.rs @@ -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; diff --git a/esp-hal-common/src/soc/esp32s2/peripherals.rs b/esp-hal-common/src/soc/esp32s2/peripherals.rs index b93f2839a..1a5fe202d 100644 --- a/esp-hal-common/src/soc/esp32s2/peripherals.rs +++ b/esp-hal-common/src/soc/esp32s2/peripherals.rs @@ -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 diff --git a/esp-hal-common/src/soc/esp32s2/psram.rs b/esp-hal-common/src/soc/esp32s2/psram.rs index 2c594d237..05dbe0f96 100644 --- a/esp-hal-common/src/soc/esp32s2/psram.rs +++ b/esp-hal-common/src/soc/esp32s2/psram.rs @@ -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

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) { diff --git a/esp-hal-common/src/soc/esp32s3/cpu_control.rs b/esp-hal-common/src/soc/esp32s3/cpu_control.rs index fc5605043..883a034f5 100644 --- a/esp-hal-common/src/soc/esp32s3/cpu_control.rs +++ b/esp-hal-common/src/soc/esp32s3/cpu_control.rs @@ -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>, +//! counter: &critical_section::Mutex>, +//! ) -> ! { +//! 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; diff --git a/esp-hal-common/src/soc/esp32s3/efuse.rs b/esp-hal-common/src/soc/esp32s3/efuse.rs index 7bf79e2a9..daf09edd2 100644 --- a/esp-hal-common/src/soc/esp32s3/efuse.rs +++ b/esp-hal-common/src/soc/esp32s3/efuse.rs @@ -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) } diff --git a/esp-hal-common/src/soc/esp32s3/gpio.rs b/esp-hal-common/src/soc/esp32s3/gpio.rs index d56301ea9..1bf25e764 100644 --- a/esp-hal-common/src/soc/esp32s3/gpio.rs +++ b/esp-hal-common/src/soc/esp32s3/gpio.rs @@ -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, diff --git a/esp-hal-common/src/soc/esp32s3/mod.rs b/esp-hal-common/src/soc/esp32s3/mod.rs index e79ba3058..a9cf92c25 100644 --- a/esp-hal-common/src/soc/esp32s3/mod.rs +++ b/esp-hal-common/src/soc/esp32s3/mod.rs @@ -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; diff --git a/esp-hal-common/src/soc/esp32s3/peripherals.rs b/esp-hal-common/src/soc/esp32s3/peripherals.rs index 74aa12859..9912bdf44 100644 --- a/esp-hal-common/src/soc/esp32s3/peripherals.rs +++ b/esp-hal-common/src/soc/esp32s3/peripherals.rs @@ -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 diff --git a/esp-hal-common/src/soc/esp32s3/psram.rs b/esp-hal-common/src/soc/esp32s3/psram.rs index 25305ad82..c7afde1b9 100644 --- a/esp-hal-common/src/soc/esp32s3/psram.rs +++ b/esp-hal-common/src/soc/esp32s3/psram.rs @@ -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 { diff --git a/esp-hal-common/src/soc/esp32s3/radio_clocks.rs b/esp-hal-common/src/soc/esp32s3/radio_clocks.rs index 02dae1af8..d3b3691be 100644 --- a/esp-hal-common/src/soc/esp32s3/radio_clocks.rs +++ b/esp-hal-common/src/soc/esp32s3/radio_clocks.rs @@ -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. diff --git a/esp-hal-common/src/soc/esp32s3/ulp_core.rs b/esp-hal-common/src/soc/esp32s3/ulp_core.rs index 5c90dc243..17ae121ec 100644 --- a/esp-hal-common/src/soc/esp32s3/ulp_core.rs +++ b/esp-hal-common/src/soc/esp32s3/ulp_core.rs @@ -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; diff --git a/esp-hal-common/src/spi.rs b/esp-hal-common/src/spi.rs index 7cc500a30..4ac1a0a81 100644 --- a/esp-hal-common/src/spi.rs +++ b/esp-hal-common/src/spi.rs @@ -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; diff --git a/esp-hal-common/src/system.rs b/esp-hal-common/src/system.rs index b036fe4cc..2427429ba 100755 --- a/esp-hal-common/src/system.rs +++ b/esp-hal-common/src/system.rs @@ -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(); diff --git a/esp-hal-common/src/systimer.rs b/esp-hal-common/src/systimer.rs index 7396ef063..e357cc7e3 100644 --- a/esp-hal-common/src/systimer.rs +++ b/esp-hal-common/src/systimer.rs @@ -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}; diff --git a/esp-hal-common/src/timer.rs b/esp-hal-common/src/timer.rs index 7714379e2..297da608b 100644 --- a/esp-hal-common/src/timer.rs +++ b/esp-hal-common/src/timer.rs @@ -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, diff --git a/esp-hal-common/src/twai/mod.rs b/esp-hal-common/src/twai/mod.rs index 7bd1aa230..fdf7ae98c 100644 --- a/esp-hal-common/src/twai/mod.rs +++ b/esp-hal-common/src/twai/mod.rs @@ -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}; diff --git a/esp-hal-common/src/uart.rs b/esp-hal-common/src/uart.rs index 90471b18a..514250267 100644 --- a/esp-hal-common/src/uart.rs +++ b/esp-hal-common/src/uart.rs @@ -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)] diff --git a/esp-hal-common/src/usb_serial_jtag.rs b/esp-hal-common/src/usb_serial_jtag.rs index 0e219d9eb..804658bee 100644 --- a/esp-hal-common/src/usb_serial_jtag.rs +++ b/esp-hal-common/src/usb_serial_jtag.rs @@ -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; diff --git a/esp-hal-procmacros/src/lib.rs b/esp-hal-procmacros/src/lib.rs index e3a58a97f..dbd65f6b3 100644 --- a/esp-hal-procmacros/src/lib.rs +++ b/esp-hal-procmacros/src/lib.rs @@ -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.
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")]