From 4c5e493b1be18710ba9cc19c71be9efef18692df Mon Sep 17 00:00:00 2001 From: Juraj Sadel Date: Tue, 11 Jun 2024 12:18:09 +0200 Subject: [PATCH] esp-hal: Add runnable doctests to peripheral drivers (#1663) * Check docs examples II * rebase and update * fix root crate macro expansion in doctest snippets * clean up and fmt * add xtask run-doc-test subcommand and check in CI * address review comments * remove commented printlns * fix the host target check * rebase and update * hide docs for before_snippet macro and remove commented block code in twai --- .github/workflows/ci.yml | 11 ++- esp-alloc/src/macros.rs | 2 +- esp-hal-procmacros/src/lib.rs | 6 +- esp-hal/build.rs | 6 ++ esp-hal/doc-helper/before | 12 +++ esp-hal/src/aes/mod.rs | 85 ++++----------------- esp-hal/src/analog/adc/mod.rs | 29 +++++-- esp-hal/src/analog/dac.rs | 21 ++--- esp-hal/src/clock/mod.rs | 30 +++++--- esp-hal/src/delay.rs | 9 ++- esp-hal/src/dma/gdma.rs | 4 - esp-hal/src/dma/mod.rs | 45 ++++++----- esp-hal/src/etm.rs | 25 +++++- esp-hal/src/gpio/etm.rs | 17 ++++- esp-hal/src/gpio/lp_io.rs | 8 +- esp-hal/src/gpio/mod.rs | 9 ++- esp-hal/src/gpio/rtc_io.rs | 2 +- esp-hal/src/i2c.rs | 11 ++- esp-hal/src/i2s.rs | 41 ++++++---- esp-hal/src/interrupt/mod.rs | 49 +++++++----- esp-hal/src/interrupt/riscv.rs | 2 +- esp-hal/src/lcd_cam/cam.rs | 30 +++++++- esp-hal/src/lcd_cam/lcd/i8080.rs | 24 +++++- esp-hal/src/ledc/mod.rs | 50 +++++------- esp-hal/src/lib.rs | 28 ++++++- esp-hal/src/mcpwm/mod.rs | 26 +++++-- esp-hal/src/mcpwm/operator.rs | 28 +++++-- esp-hal/src/parl_io.rs | 55 +++++++++---- esp-hal/src/pcnt/mod.rs | 102 +------------------------ esp-hal/src/peripheral.rs | 20 +---- esp-hal/src/rmt.rs | 39 ++++------ esp-hal/src/rng.rs | 20 ----- esp-hal/src/rom/crc.rs | 71 +++++++++++------ esp-hal/src/rom/md5.rs | 26 +++++-- esp-hal/src/rsa/mod.rs | 34 +-------- esp-hal/src/rtc_cntl/mod.rs | 53 ++++++------- esp-hal/src/sha.rs | 37 +++++---- esp-hal/src/soc/esp32/cpu_control.rs | 38 +++++---- esp-hal/src/soc/esp32/efuse/mod.rs | 9 ++- esp-hal/src/soc/esp32c2/efuse/mod.rs | 9 ++- esp-hal/src/soc/esp32c3/efuse/mod.rs | 9 ++- esp-hal/src/soc/esp32c6/efuse/mod.rs | 9 ++- esp-hal/src/soc/esp32c6/lp_core.rs | 27 +------ esp-hal/src/soc/esp32h2/efuse/mod.rs | 9 ++- esp-hal/src/soc/esp32s2/efuse/mod.rs | 25 ++---- esp-hal/src/soc/esp32s2/ulp_core.rs | 24 +++--- esp-hal/src/soc/esp32s3/cpu_control.rs | 38 +++++---- esp-hal/src/soc/esp32s3/efuse/mod.rs | 9 ++- esp-hal/src/soc/esp32s3/ulp_core.rs | 22 +++--- esp-hal/src/spi/master.rs | 23 +++--- esp-hal/src/spi/slave.rs | 66 +++++++++------- esp-hal/src/system.rs | 4 +- esp-hal/src/time.rs | 5 +- esp-hal/src/timer/mod.rs | 19 +++-- esp-hal/src/timer/systimer.rs | 57 ++++++++++++-- esp-hal/src/timer/timg.rs | 20 +++-- esp-hal/src/trace.rs | 11 ++- esp-hal/src/twai/filter.rs | 10 +-- esp-hal/src/twai/mod.rs | 50 ++++++------ esp-hal/src/uart.rs | 63 ++++++++++----- esp-hal/src/usb_serial_jtag.rs | 31 +++++--- examples/src/bin/embassy_i2s_read.rs | 6 +- examples/src/bin/hmac.rs | 1 - examples/src/bin/i2s_read.rs | 6 +- xtask/src/main.rs | 30 ++++++++ 65 files changed, 965 insertions(+), 732 deletions(-) create mode 100644 esp-hal/doc-helper/before diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 53fc345cf..7d3b9f5ff 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -104,6 +104,15 @@ jobs: # Build all supported examples for the specified device: - name: Build (examples) run: cargo xtask build-examples esp-hal ${{ matrix.device.soc }} + # Check doc-tests + - if: ${{ !contains(fromJson('["esp32", "esp32s2", "esp32s3"]'), matrix.device.soc) }} + uses: dtolnay/rust-toolchain@v1 + with: + target: riscv32imc-unknown-none-elf,riscv32imac-unknown-none-elf + toolchain: nightly + components: rust-src + - name: Check doc-tests + run: cargo xtask run-doc-test esp-hal ${{ matrix.device.soc }} esp-lp-hal: runs-on: ubuntu-latest @@ -345,4 +354,4 @@ jobs: ldproxy: false - uses: Swatinem/rust-cache@v2 - - run: cargo xtask build-tests ${{ matrix.target.soc }} + - run: cargo xtask build-tests ${{ matrix.target.soc }} \ No newline at end of file diff --git a/esp-alloc/src/macros.rs b/esp-alloc/src/macros.rs index 079a39e0b..17eec9662 100644 --- a/esp-alloc/src/macros.rs +++ b/esp-alloc/src/macros.rs @@ -23,7 +23,7 @@ macro_rules! heap_allocator { /// and the psram module path. /// /// # Usage -/// ```no_run +/// ```rust, no_run /// esp_alloc::psram_allocator!(peripherals.PSRAM, hal::psram); /// ``` #[macro_export] diff --git a/esp-hal-procmacros/src/lib.rs b/esp-hal-procmacros/src/lib.rs index 9f5385382..e108fcfb0 100644 --- a/esp-hal-procmacros/src/lib.rs +++ b/esp-hal-procmacros/src/lib.rs @@ -39,7 +39,7 @@ //! //! Requires the `embassy` feature to be enabled. //! -//! ```no_run +//! ```rust, no_run //! #[main] //! async fn main(spawner: Spawner) { //! // Your application's entry point @@ -50,7 +50,7 @@ //! //! Requires the `ram` feature to be enabled. //! -//! ```no_run +//! ```rust, no_run //! #[ram(rtc_fast)] //! static mut SOME_INITED_DATA: [u8; 2] = [0xaa, 0xbb]; //! @@ -316,7 +316,7 @@ pub fn make_gpio_enum_dispatch_macro(input: TokenStream) -> TokenStream { /// Load code to be run on the LP/ULP core. /// /// ## Example -/// ```no_run +/// ```rust, no_run /// let lp_core_code = load_lp_code!("path.elf"); /// lp_core_code.run(&mut lp_core, lp_core::LpCoreWakeupSource::HpCpu, lp_pin); /// ```` diff --git a/esp-hal/build.rs b/esp-hal/build.rs index 2ed457c87..53d292770 100644 --- a/esp-hal/build.rs +++ b/esp-hal/build.rs @@ -117,6 +117,12 @@ fn main() -> Result<(), Box> { )?; } + // needed for before_snippet! macro + let host = env::var_os("HOST").expect("HOST not set"); + if let Some("windows") = host.to_str().unwrap().split('-').nth(2) { + println!("cargo:rustc-cfg=host_os=\"windows\""); + } + // With the architecture-specific linker scripts taken care of, we can copy all // remaining linker scripts which are common to all devices: copy_dir_all(&config_symbols, "ld/sections", &out)?; diff --git a/esp-hal/doc-helper/before b/esp-hal/doc-helper/before new file mode 100644 index 000000000..7781574e3 --- /dev/null +++ b/esp-hal/doc-helper/before @@ -0,0 +1,12 @@ +# #![no_std] +# use esp_hal::peripherals::Peripherals; +# use esp_hal::clock::ClockControl; +# use esp_hal::system::SystemControl; +# #[panic_handler] +# fn panic(_ : &core::panic::PanicInfo) -> ! { +# loop {} +# } +# fn main() { +# let peripherals = Peripherals::take(); +# let system = SystemControl::new(peripherals.SYSTEM); +# let mut clocks = ClockControl::boot_defaults(system.clock_control).freeze(); \ No newline at end of file diff --git a/esp-hal/src/aes/mod.rs b/esp-hal/src/aes/mod.rs index 61b3dc7d9..d5d9b9538 100644 --- a/esp-hal/src/aes/mod.rs +++ b/esp-hal/src/aes/mod.rs @@ -12,53 +12,26 @@ //! //! ## Example //! -//! ### Initialization -//! -//! ```no_run -//! let mut aes = Aes::new(peripherals.AES); -//! ``` -//! -//! ### 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 +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use esp_hal::aes::{Aes, Mode}; +//! # let keytext = "SUp4SeCp@sSw0rd".as_bytes(); +//! # let plaintext = "message".as_bytes(); +//! # let mut keybuf = [0_u8; 16]; +//! # keybuf[..keytext.len()].copy_from_slice(keytext); //! let mut block_buf = [0_u8; 16]; //! block_buf[..plaintext.len()].copy_from_slice(plaintext); -//! ``` -//! -//! ### Encrypting and Decrypting (using hardware) -//! -//! ```no_run //! let mut block = block_buf.clone(); +//! +//! let mut aes = Aes::new(peripherals.AES); //! aes.process(&mut block, Mode::Encryption128, keybuf); //! let hw_encrypted = block.clone(); //! //! aes.process(&mut block, Mode::Decryption128, keybuf); //! 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 on ESP32 and ESP32S2 ⚠️ @@ -69,39 +42,11 @@ //! //! * Initialization vector (IV) is currently not supported ⚠️ //! -//! ## Example +//! ⚠️: The examples for AES with DMA peripheral are quite extensive, so for a more +//! detailed study of how to use this driver please visit [the repository +//! with corresponding example]. //! -//! ### Initialization -//! -//! ```no_run -//! let dma = Gdma::new(peripherals.DMA); -//! let dma_channel = dma.channel0; -//! -//! let mut descriptors = [0u32; 8 * 3]; -//! let mut rx_descriptors = [0u32; 8 * 3]; -//! -//! let aes = Aes::new(peripherals.AES).with_dma(dma_channel.configure( -//! false, -//! &mut descriptors, -//! &mut rx_descriptors, -//! DmaPriority::Priority0, -//! )); -//! ``` -//! -//! ### Operation -//! -//! ```no_run -//! let transfer = aes -//! .process( -//! plaintext, -//! hw_encrypted, -//! Mode::Encryption128, -//! CipherMode::Ecb, -//! keybuf, -//! ) -//! .unwrap(); -//! transfer.wait().unwrap(); -//! ``` +//! [the repository with corresponding example]: https://github.com/esp-rs/esp-hal/blob/main/hil-test/tests/aes_dma.rs use crate::{ peripheral::{Peripheral, PeripheralRef}, diff --git a/esp-hal/src/analog/adc/mod.rs b/esp-hal/src/analog/adc/mod.rs index 0b479d053..2227e1bcc 100644 --- a/esp-hal/src/analog/adc/mod.rs +++ b/esp-hal/src/analog/adc/mod.rs @@ -6,19 +6,36 @@ //! //! ## Example //! -//! ```no_run +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use esp_hal::analog::adc::AdcConfig; +//! # use esp_hal::peripherals::ADC1; +//! # use esp_hal::analog::adc::Attenuation; +//! # use esp_hal::analog::adc::Adc; +//! # use esp_hal::delay::Delay; +//! # use esp_hal::gpio::Io; +//! # use core::result::Result::Err; +//! +//! # let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); +#![cfg_attr(esp32, doc = "let analog_pin = io.pins.gpio32;")] +#![cfg_attr(any(esp32s2, esp32s3), doc = "let analog_pin = io.pins.gpio3;")] +#![cfg_attr( + not(any(esp32, esp32s2, esp32s3)), + doc = "let analog_pin = io.pins.gpio2;" +)] //! let mut adc1_config = AdcConfig::new(); -//! let mut adc1 = ADC::::new(peripherals.ADC1, adc1_config); -//! let mut pin = adc1_config.enable_pin(io.pins.gpio2, Attenuation::Attenuation11dB); +//! let mut pin = adc1_config.enable_pin(analog_pin, +//! Attenuation::Attenuation11dB); let mut adc1 = Adc::new(peripherals.ADC1, +//! adc1_config); //! //! let mut delay = Delay::new(&clocks); //! //! loop { -//! let pin_value: u16 = nb::block!(adc1.read(&mut pin)).unwrap(); -//! println!("PIN2 ADC reading = {}", pin_value); +//! let pin_value: u16 = nb::block!(adc1.read_oneshot(&mut pin)).unwrap(); //! -//! delay.delay_ms(1500u32); +//! delay.delay_millis(1500); //! } +//! # } //! ``` use core::marker::PhantomData; diff --git a/esp-hal/src/analog/dac.rs b/esp-hal/src/analog/dac.rs index b5f422972..1683f25a0 100644 --- a/esp-hal/src/analog/dac.rs +++ b/esp-hal/src/analog/dac.rs @@ -11,29 +11,30 @@ //! //! ## Example //! -//! ```no_run -//! let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); -//! let gpio25 = io.pins.gpio25; -//! let gpio26 = io.pins.gpio26; +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use esp_hal::gpio::Io; +//! # use esp_hal::analog::dac::Dac; +//! # use esp_hal::delay::Delay; +//! # use embedded_hal::delay::DelayNs; //! -//! let mut dac1 = Dac::new(peripherals.DAC1, gpio25); -//! let mut dac2 = Dac::new(peripherals.DAC2, gpio26); +//! let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); +#![cfg_attr(esp32, doc = "let dac1_pin = io.pins.gpio25;")] +#![cfg_attr(esp32s2, doc = "let dac1_pin = io.pins.gpio17;")] +//! let mut dac1 = Dac::new(peripherals.DAC1, dac1_pin); //! //! let mut delay = Delay::new(&clocks); //! //! let mut voltage_dac1 = 200u8; -//! let mut voltage_dac2 = 255u8; //! //! // Change voltage on the pins using write function: //! loop { //! voltage_dac1 = voltage_dac1.wrapping_add(1); //! dac1.write(voltage_dac1); //! -//! voltage_dac2 = voltage_dac2.wrapping_sub(1); -//! dac2.write(voltage_dac2); -//! //! delay.delay_ms(50u32); //! } +//! # } //! ``` #![deny(missing_docs)] diff --git a/esp-hal/src/clock/mod.rs b/esp-hal/src/clock/mod.rs index cb6a143c0..97f466470 100644 --- a/esp-hal/src/clock/mod.rs +++ b/esp-hal/src/clock/mod.rs @@ -40,19 +40,29 @@ //! ## Examples //! //! #### Initialize with default clock frequency for this chip -//! ```no_run -//! let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); -//! ``` -//! -//! #### Initialize with the highest possible frequency for this chip -//! ```no_run +//! ```rust, no_run +//! # #![no_std] +//! # use esp_hal::peripherals::Peripherals; +//! # use esp_hal::clock::ClockControl; +//! # use esp_hal::system::SystemControl; +//! # #[panic_handler] +//! # fn panic(_ : &core::panic::PanicInfo) -> ! { +//! # loop {} +//! # } +//! # fn main() { +//! # let peripherals = Peripherals::take(); +//! # let system = SystemControl::new(peripherals.SYSTEM); +//! // Initialize with the highest possible frequency for this chip //! let clocks = ClockControl::max(system.clock_control).freeze(); -//! ``` //! -//! #### Initialize with custom clock frequency -//! ```no_run -//! let clocks = ClockControl::configure(system.clock_control, CpuClock::Clock160MHz).freeze(); +//! // Initialize with custom clock frequency +//! // let clocks = ClockControl::configure(system.clock_control, CpuClock::Clock160MHz).freeze(); +//! // +//! // Initialize with default clock frequency for this chip +//! // let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); +//! # } //! ``` + use fugit::HertzU32; #[cfg(any(esp32, esp32c2))] diff --git a/esp-hal/src/delay.rs b/esp-hal/src/delay.rs index e134ef5da..304bd6361 100644 --- a/esp-hal/src/delay.rs +++ b/esp-hal/src/delay.rs @@ -11,13 +11,16 @@ //! affected by many factors, including interrupt usage. //! //! ## Example -//! ```no_run -//! let mut clocks = ClockControl::boot_defaults(system.clock_control).freeze(); +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use esp_hal::delay::Delay; +//! # use embedded_hal::delay::DelayNs; //! let mut delay = Delay::new(&clocks); //! //! delay.delay_ms(1000 as u32); +//! # } //! ``` -//! +//! //! [DelayMs]: embedded_hal_02::blocking::delay::DelayMs //! [DelayUs]: embedded_hal_02::blocking::delay::DelayUs //! [embedded-hal]: https://docs.rs/embedded-hal/0.2.7/embedded_hal/index.html diff --git a/esp-hal/src/dma/gdma.rs b/esp-hal/src/dma/gdma.rs index cb8e7b7a1..d7c42d1e1 100644 --- a/esp-hal/src/dma/gdma.rs +++ b/esp-hal/src/dma/gdma.rs @@ -18,10 +18,6 @@ //! 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); -//! ``` -//! //! PS: Note that the number of DMA channels is chip-specific. use crate::{ diff --git a/esp-hal/src/dma/mod.rs b/esp-hal/src/dma/mod.rs index 9fe918102..882fb10df 100644 --- a/esp-hal/src/dma/mod.rs +++ b/esp-hal/src/dma/mod.rs @@ -15,31 +15,36 @@ //! //! ### Initialize and utilize DMA controller in `SPI` //! -//! ```no_run +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use esp_hal::dma_buffers; +//! # use esp_hal::gpio::Io; +//! # use esp_hal::spi::{master::{Spi, prelude::*}, SpiMode}; +//! # use esp_hal::dma::{Dma, DmaPriority}; +//! # use crate::esp_hal::prelude::_fugit_RateExtU32; //! let dma = Dma::new(peripherals.DMA); -//! let dma_channel = dma.channel0; +#![cfg_attr(any(esp32, esp32s2), doc = "let dma_channel = dma.spi2channel;")] +#![cfg_attr(not(any(esp32, esp32s2)), doc = "let dma_channel = dma.channel0;")] +//! let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); +//! let sclk = io.pins.gpio0; +//! let miso = io.pins.gpio2; +//! let mosi = io.pins.gpio4; +//! let cs = io.pins.gpio5; //! -//! let mut descriptors = [DmaDescriptor::EMPTY; 8]; -//! let mut rx_descriptors = [DmaDescriptor::EMPTY; 8]; +//! let (tx_buffer, mut tx_descriptors, rx_buffer, mut rx_descriptors) = +//! dma_buffers!(32000); //! -//! let mut spi = Spi::new( -//! peripherals.SPI2, -//! sclk, -//! mosi, -//! miso, -//! cs, -//! 100.kHz(), -//! SpiMode::Mode0, -//! &clocks, -//! ) +//! let mut spi = Spi::new(peripherals.SPI2, 100.kHz(), SpiMode::Mode0, &clocks) +//! .with_pins(Some(sclk), Some(mosi), Some(miso), Some(cs)) //! .with_dma(dma_channel.configure( //! false, -//! &mut descriptors, +//! &mut tx_descriptors, //! &mut rx_descriptors, //! DmaPriority::Priority0, //! )); +//! # } //! ``` -//! +//! //! ⚠️ Note: Descriptors should be sized as `(CHUNK_SIZE + 4091) / 4092`. //! I.e., to transfer buffers of size `1..=4092`, you need 1 descriptor. //! @@ -139,7 +144,7 @@ const CHUNK_SIZE: usize = 4092; /// Convenience macro to create DMA buffers and descriptors /// /// ## Usage -/// ```rust,no_run +/// ```rust,ignore /// // TX and RX buffers are 32000 bytes - passing only one parameter makes TX and RX the same size /// let (tx_buffer, mut tx_descriptors, rx_buffer, mut rx_descriptors) = dma_buffers!(32000, 32000); /// ``` @@ -179,7 +184,7 @@ macro_rules! dma_buffers { /// Convenience macro to create circular DMA buffers and descriptors /// /// ## Usage -/// ```rust,no_run +/// ```rust,ignore /// // TX and RX buffers are 32000 bytes - passing only one parameter makes TX and RX the same size /// let (tx_buffer, mut tx_descriptors, rx_buffer, mut rx_descriptors) = /// dma_circular_buffers!(32000, 32000); @@ -240,7 +245,7 @@ macro_rules! dma_circular_buffers { /// Convenience macro to create DMA descriptors /// /// ## Usage -/// ```rust,no_run +/// ```rust,ignore /// // Create TX and RX descriptors for transactions up to 32000 bytes - passing only one parameter assumes TX and RX are the same size /// let (mut tx_descriptors, mut rx_descriptors) = dma_descriptors!(32000, 32000); /// ``` @@ -262,7 +267,7 @@ macro_rules! dma_descriptors { /// Convenience macro to create circular DMA descriptors /// /// ## Usage -/// ```rust,no_run +/// ```rust,ignore /// // Create TX and RX descriptors for transactions up to 32000 bytes - passing only one parameter assumes TX and RX are the same size /// let (mut tx_descriptors, mut rx_descriptors) = dma_circular_descriptors!(32000, 32000); /// ``` diff --git a/esp-hal/src/etm.rs b/esp-hal/src/etm.rs index fac9ed752..9388eb128 100644 --- a/esp-hal/src/etm.rs +++ b/esp-hal/src/etm.rs @@ -21,15 +21,33 @@ //! For more information, please refer to the #![doc = concat!("[ESP-IDF documentation](https://docs.espressif.com/projects/esp-idf/en/latest/", crate::soc::chip!(), "/api-reference/peripherals/etm.html)")] //! ## Example -//! ```no_run +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use esp_hal::gpio::Io; +//! # use esp_hal::gpio::etm::GpioEtmChannels; +//! # use esp_hal::etm::Etm; +//! # use esp_hal::gpio::etm::GpioEtmInputConfig; +//! # use esp_hal::gpio::etm::GpioEtmOutputConfig; +//! # use esp_hal::gpio::Pull; +//! # use esp_hal::gpio::Level; +//! //! let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); //! let mut led = io.pins.gpio1; //! let button = io.pins.gpio9; //! //! // setup ETM //! let gpio_ext = GpioEtmChannels::new(peripherals.GPIO_SD); -//! let led_task = gpio_ext.channel0_task.toggle(&mut led); -//! let button_event = gpio_ext.channel0_event.falling_edge(button); +//! let led_task = gpio_ext.channel0_task.toggle( +//! &mut led, +//! GpioEtmOutputConfig { +//! open_drain: false, +//! pull: Pull::None, +//! initial_state: Level::Low, +//! }, +//! ); +//! let button_event = gpio_ext +//! .channel0_event +//! .falling_edge(button, GpioEtmInputConfig { pull: Pull::Down }); //! //! let etm = Etm::new(peripherals.SOC_ETM); //! let channel0 = etm.channel0; @@ -40,6 +58,7 @@ //! //! // the LED is controlled by the button without involving the CPU //! loop {} +//! # } //! ``` use crate::{ diff --git a/esp-hal/src/gpio/etm.rs b/esp-hal/src/gpio/etm.rs index 159c192c6..b62f83a3a 100644 --- a/esp-hal/src/gpio/etm.rs +++ b/esp-hal/src/gpio/etm.rs @@ -22,7 +22,21 @@ //! reversed //! //! ## Example -//! ```no_run +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use esp_hal::gpio::Io; +//! # use esp_hal::gpio::etm::GpioEtmChannels; +//! # use esp_hal::etm::Etm; +//! # use esp_hal::gpio::etm::GpioEtmInputConfig; +//! # use esp_hal::gpio::etm::GpioEtmOutputConfig; +//! # use esp_hal::gpio::Pull; +//! # use esp_hal::gpio::Level; +//! +//! # let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); +//! # let mut led = io.pins.gpio1; +//! # let button = io.pins.gpio9; +//! +//! let gpio_ext = GpioEtmChannels::new(peripherals.GPIO_SD); //! let led_task = gpio_ext.channel0_task.toggle( //! &mut led, //! GpioEtmOutputConfig { @@ -34,6 +48,7 @@ //! let button_event = gpio_ext //! .channel0_event //! .falling_edge(button, GpioEtmInputConfig { pull: Pull::Down }); +//! # } //! ``` use crate::{ diff --git a/esp-hal/src/gpio/lp_io.rs b/esp-hal/src/gpio/lp_io.rs index 3ea02108f..2fc8387eb 100644 --- a/esp-hal/src/gpio/lp_io.rs +++ b/esp-hal/src/gpio/lp_io.rs @@ -14,10 +14,14 @@ //! chip from Deep-sleep. //! //! # Example -//! ```no_run +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! use esp_hal::gpio::Io; +//! use esp_hal::gpio::lp_io::LowPowerOutput; //! let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); //! // configure GPIO 1 as LP output pin -//! let lp_pin = LowPowerOutput::new(io.pins.gpio1); +//! let lp_pin: LowPowerOutput<'_, 1> = LowPowerOutput::new(io.pins.gpio1); +//! # } //! ``` use core::marker::PhantomData; diff --git a/esp-hal/src/gpio/mod.rs b/esp-hal/src/gpio/mod.rs index 01b8dbffb..7d9ca244b 100644 --- a/esp-hal/src/gpio/mod.rs +++ b/esp-hal/src/gpio/mod.rs @@ -15,11 +15,14 @@ //! designed struct from the pac struct `GPIO` and `IO_MUX` using `Io::new`. //! //! ## Example -//! ```no_run +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use esp_hal::gpio::{Io, Level, Output}; //! let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); -//! let mut led = Output::new(io.pins.gpio5); +//! let mut led = Output::new(io.pins.gpio5, Level::High); +//! # } //! ``` -//! +//! //! [embedded-hal]: https://docs.rs/embedded-hal/latest/embedded_hal/ #![warn(missing_docs)] diff --git a/esp-hal/src/gpio/rtc_io.rs b/esp-hal/src/gpio/rtc_io.rs index 51afd5bda..d6c1470c0 100644 --- a/esp-hal/src/gpio/rtc_io.rs +++ b/esp-hal/src/gpio/rtc_io.rs @@ -14,7 +14,7 @@ //! chip from Deep-sleep. //! //! # Example -//! ```no_run +//! ```rust, ignore //! let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); //! // configure GPIO 1 as ULP output pin //! let lp_pin = LowPowerOutput::new(io.pins.gpio1); diff --git a/esp-hal/src/i2c.rs b/esp-hal/src/i2c.rs index 76f018a78..208f3021c 100644 --- a/esp-hal/src/i2c.rs +++ b/esp-hal/src/i2c.rs @@ -14,7 +14,13 @@ //! ## Example //! Following code shows how to read data from a BMP180 sensor using I2C. //! -//! ```no_run +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use esp_hal::i2c::I2C; +//! # use esp_hal::gpio::Io; +//! # use core::option::Option::None; +//! # use crate::esp_hal::prelude::_fugit_RateExtU32; +//! # let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); //! // Create a new peripheral object with the described wiring //! // and standard I2C clock speed //! let mut i2c = I2C::new( @@ -28,9 +34,8 @@ //! loop { //! let mut data = [0u8; 22]; //! i2c.write_read(0x77, &[0xaa], &mut data).ok(); -//! -//! println!("{:02x?}", data); //! } +//! # } //! ``` use core::marker::PhantomData; diff --git a/esp-hal/src/i2s.rs b/esp-hal/src/i2s.rs index 9de1031ee..a81d65b3f 100644 --- a/esp-hal/src/i2s.rs +++ b/esp-hal/src/i2s.rs @@ -22,7 +22,25 @@ //! ## Examples //! //! ### initialization -//! ```no_run +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use esp_hal::i2s::I2s; +//! # use esp_hal::i2s::Standard; +//! # use esp_hal::i2s::DataFormat; +//! # use esp_hal::gpio::Io; +//! # use esp_hal::dma_buffers; +//! # use esp_hal::dma::{Dma, DmaPriority}; +//! # use crate::esp_hal::prelude::_fugit_RateExtU32; +//! # use crate::esp_hal::peripherals::Peripherals; +//! # use crate::esp_hal::i2s::I2sReadDma; +//! # use core::ptr::addr_of_mut; +//! # let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); +//! let dma = Dma::new(peripherals.DMA); +#![cfg_attr(any(esp32, esp32s2), doc = "let dma_channel = dma.i2s0channel;")] +#![cfg_attr(not(any(esp32, esp32s2)), doc = "let dma_channel = dma.channel0;")] +//! let (_, mut tx_descriptors, mut rx_buffer, mut rx_descriptors) = +//! dma_buffers!(0, 4 * 4092); +//! //! let i2s = I2s::new( //! peripherals.I2S0, //! Standard::Philips, @@ -35,24 +53,15 @@ //! DmaPriority::Priority0, //! ), //! &clocks, -//! ) -//! .with_mclk(io.pins.gpio4); -//! ``` -//! -//! ### Reading -//! ```no_run -//! let i2s_rx = i2s.i2s_rx. +//! ); +#![cfg_attr(not(esp32), doc = "let i2s = i2s.with_mclk(io.pins.gpio0);")] +//! let mut i2s_rx = i2s.i2s_rx //! .with_bclk(io.pins.gpio1) //! .with_ws(io.pins.gpio2) -//! .with_dout(io.pins.gpio5) +//! .with_din(io.pins.gpio5) //! .build(); //! -//! // 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"); +//! let mut transfer = i2s_rx.read_dma_circular(&mut rx_buffer).unwrap(); //! //! loop { //! let avail = transfer.available(); @@ -60,9 +69,9 @@ //! if avail > 0 { //! let mut rcv = [0u8; 5000]; //! transfer.pop(&mut rcv[..avail]).unwrap(); -//! println!("Received {:x?}...", &rcv[..30]); //! } //! } +//! # } //! ``` use core::marker::PhantomData; diff --git a/esp-hal/src/interrupt/mod.rs b/esp-hal/src/interrupt/mod.rs index e28e6a566..bb74e9b06 100644 --- a/esp-hal/src/interrupt/mod.rs +++ b/esp-hal/src/interrupt/mod.rs @@ -8,38 +8,53 @@ //! This is the preferred way to register handlers. //! //! ## Example using the peripheral driver to register an interrupt handler + +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use core::cell::RefCell; //! -//! ```no_run -//! #[entry] -//! fn main() -> ! { -//! ... -//! let mut sw_int = system.software_interrupt_control; +//! # use critical_section::Mutex; +//! # use esp_hal::{ +//! # prelude::*, +//! # system::{SoftwareInterrupt, SystemControl}, +//! # }; +//! # use esp_hal::interrupt::Priority; +//! # use esp_hal::interrupt::InterruptHandler; +//! +//! static SWINT0: Mutex>>> = +//! Mutex::new(RefCell::new(None)); +//! +//! let mut sw_int = system.software_interrupt_control; //! critical_section::with(|cs| { //! sw_int -//! .software_interrupt0 -//! .set_interrupt_handler(swint0_handler); +//! .software_interrupt0 +//! .set_interrupt_handler(swint0_handler); //! SWINT0 -//! .borrow_ref_mut(cs) -//! .replace(sw_int.software_interrupt0); +//! .borrow_ref_mut(cs) +//! .replace(sw_int.software_interrupt0); //! }); //! -//! // trigger the interrupt //! critical_section::with(|cs| { -//! SWINT0.borrow_ref_mut(cs).as_mut().unwrap().raise(); +//! SWINT0.borrow_ref(cs).as_ref().unwrap().raise(); //! }); -//! ... +//! +//! loop {} //! } //! -//! // use the `handler` macro to define a handler, optionally you can set a priority -//! #[handler(priority = esp_hal::interrupt::Priority::Priority2)] +//! # use procmacros::handler; +//! # use esp_hal::interrupt; +//! # use critical_section::Mutex; +//! # use core::cell::RefCell; +//! # use esp_hal::system::SoftwareInterrupt; +//! # static SWINT0: Mutex>>> = Mutex::new(RefCell::new(None)); +//! #[handler(priority = esp_hal::interrupt::Priority::Priority1)] //! fn swint0_handler() { -//! esp_println::println!("SW interrupt0"); +//! // esp_println::println!("SW interrupt0"); //! critical_section::with(|cs| { -//! SWINT0.borrow_ref_mut(cs).as_mut().unwrap().reset(); +//! SWINT0.borrow_ref(cs).as_ref().unwrap().reset(); //! }); //! } //! ``` -//! //! There are additional ways to register interrupt handlers which are generally //! only meant to be used in very special situations (mostly internal to the HAL //! or the supporting libraries). Those are outside the scope of this diff --git a/esp-hal/src/interrupt/riscv.rs b/esp-hal/src/interrupt/riscv.rs index 9e5716311..ca5018b42 100644 --- a/esp-hal/src/interrupt/riscv.rs +++ b/esp-hal/src/interrupt/riscv.rs @@ -5,7 +5,7 @@ //! //! On chips with a PLIC CPU interrupts 1,2,5,6,9 .. 19 are used. //! -//! ```rust +//! ```rust, ignore //! interrupt1() => Priority::Priority1 //! interrupt2() => Priority::Priority2 //! ... diff --git a/esp-hal/src/lcd_cam/cam.rs b/esp-hal/src/lcd_cam/cam.rs index 110244ba5..6526ca12d 100644 --- a/esp-hal/src/lcd_cam/cam.rs +++ b/esp-hal/src/lcd_cam/cam.rs @@ -12,7 +12,27 @@ //! Following code shows how to receive some bytes from an 8 bit DVP stream in //! master mode. //! -//! ```no_run +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use esp_hal::gpio::Io; +//! # use esp_hal::lcd_cam::{cam::{Camera, RxEightBits}, LcdCam}; +//! # use fugit::RateExtU32; +//! # use esp_hal::dma_buffers; +//! # use esp_hal::dma::{Dma, DmaPriority}; +//! # let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); +//! +//! # let dma = Dma::new(peripherals.DMA); +//! # let channel = dma.channel0; +//! +//! # let (tx_buffer, mut tx_descriptors, _, mut rx_descriptors) = dma_buffers!(32678, 0); +//! +//! # let channel = channel.configure( +//! # false, +//! # &mut tx_descriptors, +//! # &mut rx_descriptors, +//! # DmaPriority::Priority0, +//! # ); +//! //! let mclk_pin = io.pins.gpio15; //! let vsync_pin = io.pins.gpio6; //! let href_pin = io.pins.gpio7; @@ -29,9 +49,11 @@ //! ); //! //! let lcd_cam = LcdCam::new(peripherals.LCD_CAM); -//! let mut camera = Camera::new(lcd_cam.cam, channel.rx, data_pins, 20u32.MHz(), &clocks) -//! .with_master_clock(mclk_pin) // Remove this for slave mode. -//! .with_ctrl_pins(vsync_pin, href_pin, pclk_pin); +//! let mut camera = +//! Camera::new(lcd_cam.cam, channel.rx, data_pins, 20u32.MHz(), &clocks) +//! .with_master_clock(mclk_pin) // Remove this for slave mode. +//! .with_ctrl_pins(vsync_pin, href_pin, pclk_pin); +//! # } //! ``` use core::mem::size_of; diff --git a/esp-hal/src/lcd_cam/lcd/i8080.rs b/esp-hal/src/lcd_cam/lcd/i8080.rs index fac424f6b..c6263bc96 100644 --- a/esp-hal/src/lcd_cam/lcd/i8080.rs +++ b/esp-hal/src/lcd_cam/lcd/i8080.rs @@ -9,7 +9,28 @@ //! Following code show how to send a command to a MIPI-DSI display over I8080 //! protocol. //! -//! ```no_run +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use esp_hal::gpio::Io; +//! # use esp_hal::lcd_cam::{LcdCam, lcd::i8080::{Config, I8080, TxEightBits}}; +//! # use esp_hal::dma_buffers; +//! # use esp_hal::dma::{Dma, DmaPriority}; +//! # use fugit::RateExtU32; +//! +//! # let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); +//! +//! # let dma = Dma::new(peripherals.DMA); +//! # let channel = dma.channel0; +//! +//! # let (tx_buffer, mut tx_descriptors, _, mut rx_descriptors) = dma_buffers!(32678, 0); +//! +//! # let channel = channel.configure( +//! # false, +//! # &mut tx_descriptors, +//! # &mut rx_descriptors, +//! # DmaPriority::Priority0, +//! # ); +//! //! let tx_pins = TxEightBits::new( //! io.pins.gpio9, //! io.pins.gpio46, @@ -33,6 +54,7 @@ //! .with_ctrl_pins(io.pins.gpio0, io.pins.gpio47); //! //! i8080.send(0x3A, 0, &[0x55]).unwrap(); // RGB565 +//! # } //! ``` use core::{fmt::Formatter, mem::size_of}; diff --git a/esp-hal/src/ledc/mod.rs b/esp-hal/src/ledc/mod.rs index d69deb66f..391027041 100644 --- a/esp-hal/src/ledc/mod.rs +++ b/esp-hal/src/ledc/mod.rs @@ -9,8 +9,22 @@ //! The following will configure the Low Speed Channel0 to 24kHz output with //! 10% duty using the ABPClock //! -//! ```no_run -//! let mut ledc = Ledc::new(peripherals.LEDC, &clock_control); +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use esp_hal::ledc::Ledc; +//! # use esp_hal::ledc::LSGlobalClkSource; +//! # use esp_hal::ledc::timer; +//! # use esp_hal::ledc::LowSpeed; +//! # use esp_hal::ledc::channel; +//! # use esp_hal::gpio::Io; +//! # use crate::esp_hal::prelude::_esp_hal_ledc_timer_TimerIFace; +//! # use crate::esp_hal::prelude::_fugit_RateExtU32; +//! # use crate::esp_hal::prelude::_esp_hal_ledc_channel_ChannelIFace; +//! +//! # let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); +//! # let led = io.pins.gpio0; +//! +//! let mut ledc = Ledc::new(peripherals.LEDC, &clocks); //! ledc.set_global_slow_clock(LSGlobalClkSource::APBClk); //! //! let mut lstimer0 = ledc.get_timer::(timer::Number::Timer0); @@ -26,37 +40,13 @@ //! channel0 //! .configure(channel::config::Config { //! timer: &lstimer0, -//! duty: 10, +//! duty_pct: 10, +//! pin_config: channel::config::PinConfig::PushPull, //! }) //! .unwrap(); +//! # } //! ``` -//! -//! # HighSpeed Example (ESP32 only): -//! -//! The following will configure the High Speed Channel0 to 24kHz output with -//! 10% duty using the ABPClock -//! -//! ```no_run -//! let ledc = Ledc::new(peripherals.LEDC, &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: 24.kHz(), -//! }) -//! .unwrap(); -//! -//! let mut channel0 = ledc.get_channel(channel::Number::Channel0, led); -//! channel0 -//! .configure(channel::config::Config { -//! timer: &hstimer0, -//! duty: 10, -//! }) -//! .unwrap(); -//! ``` -//! +//! //! # Unsupported //! - Source clock selection //! - Interrupts diff --git a/esp-hal/src/lib.rs b/esp-hal/src/lib.rs index 82a7f2ee7..70bc91049 100644 --- a/esp-hal/src/lib.rs +++ b/esp-hal/src/lib.rs @@ -32,7 +32,7 @@ //! Invoke the following command in the root of the esp-hal repository to get //! started. //! -//! ```no_run +//! ```bash //! cargo xtask help //! ``` //! @@ -45,7 +45,7 @@ //! We have a template for quick starting bare-metal projects, [esp-template]. //! The template uses [cargo-generate], so ensure that it is installed and run //! -//! ```no_run +//! ```bash //! cargo generate -a esp-rs/esp-template //! ``` //! @@ -461,8 +461,8 @@ mod critical_section_impl { /// often a `const` variable. /// /// Example usage using [`spi::master::dma::SpiDma`] -/// ```no_run -/// const ARRAY_IN_FLASH = [0xAA; 128] +/// ```rust, ignore +/// const ARRAY_IN_FLASH = [0xAA; 128]; /// /// let spi = SpiDma::new(/* */); /// @@ -525,3 +525,23 @@ fn hal_main(a0: usize, a1: usize, a2: usize) -> ! { unsafe extern "C" fn stack_chk_fail() { panic!("Stack corruption detected"); } + +#[doc(hidden)] +/// Helper macro for checking doctest code snippets +#[cfg(not(host_os = "windows"))] +#[macro_export] +macro_rules! before_snippet { + () => { + core::include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/doc-helper/before")) + }; +} + +#[doc(hidden)] +/// Helper macro for checking doctest code snippets +#[cfg(host_os = "windows")] +#[macro_export] +macro_rules! before_snippet { + () => { + core::include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "\\doc-helper\\before")) + }; +} diff --git a/esp-hal/src/mcpwm/mod.rs b/esp-hal/src/mcpwm/mod.rs index dbc3bcb6f..8abc58ce6 100644 --- a/esp-hal/src/mcpwm/mod.rs +++ b/esp-hal/src/mcpwm/mod.rs @@ -31,14 +31,26 @@ //! ## 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 +//! ```rust, no_run +#![doc = crate::before_snippet!()] //! # use esp_hal::{mcpwm, prelude::*}; -//! use mcpwm::{operator::PwmPinConfig, timer::PwmWorkingMode, McPwm, PeripheralClockConfig}; +//! # use esp_hal::mcpwm::operator::{DeadTimeCfg, PWMStream}; +//! # use mcpwm::{operator::PwmPinConfig, timer::PwmWorkingMode, McPwm, PeripheralClockConfig}; +//! # use esp_hal::gpio::Io; +//! +//! # let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); +//! # let pin = io.pins.gpio0; //! //! // initialize peripheral -//! let clock_cfg = PeripheralClockConfig::with_frequency(&clocks, 40.MHz()).unwrap(); -//! let mut mcpwm = McPwm::new(peripherals.PWM0, clock_cfg); +#![cfg_attr( + esp32h2, + doc = "let clock_cfg = PeripheralClockConfig::with_frequency(&clocks, 40.MHz()).unwrap();" +)] +#![cfg_attr( + not(esp32h2), + doc = "let clock_cfg = PeripheralClockConfig::with_frequency(&clocks, 32.MHz()).unwrap();" +)] +//! let mut mcpwm = McPwm::new(peripherals.MCPWM0, clock_cfg); //! //! // connect operator0 to timer0 //! mcpwm.operator0.set_timer(&mcpwm.timer0); @@ -47,7 +59,8 @@ //! .operator0 //! .with_pin_a(pin, PwmPinConfig::UP_ACTIVE_HIGH); //! -//! // start timer with timestamp values in the range of 0..=99 and a frequency of 20 kHz +//! // start timer with timestamp values in the range of 0..=99 and a frequency +//! // of 20 kHz //! let timer_clock_cfg = clock_cfg //! .timer_clock_with_frequency(99, PwmWorkingMode::Increase, 20.kHz()) //! .unwrap(); @@ -55,6 +68,7 @@ //! //! // pin will be high 50% of the time //! pwm_pin.set_timestamp(50); +//! # } //! ``` #![deny(missing_docs)] diff --git a/esp-hal/src/mcpwm/operator.rs b/esp-hal/src/mcpwm/operator.rs index 5fe4e0193..9876dc747 100644 --- a/esp-hal/src/mcpwm/operator.rs +++ b/esp-hal/src/mcpwm/operator.rs @@ -480,17 +480,34 @@ impl<'d, Pin: OutputPin, PWM: PwmPeripheral, const OP: u8, const IS_A: bool> /// configured deadtime. /// /// # H-Bridge example -/// ```no_run +/// ```rust, no_run +#[doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/doc-helper/before"))] +/// # use esp_hal::{mcpwm, prelude::*}; +/// # use esp_hal::mcpwm::{McPwm, PeripheralClockConfig}; +/// # use esp_hal::mcpwm::operator::{DeadTimeCfg, PwmPinConfig, PWMStream}; +/// # use esp_hal::gpio::Io; +/// # let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); /// // active high complementary using PWMA input /// let bridge_active = DeadTimeCfg::new_ahc(); /// // use PWMB as input for both outputs -/// let bridge_off = DeadTimeCfg::new_bypass().set_output_swap(PWMStream::PWMA, true); +/// let bridge_off = DeadTimeCfg::new_bypass().set_output_swap(PWMStream::PWMA, +/// true); +#[cfg_attr( + esp32h2, + doc = "let clock_cfg = PeripheralClockConfig::with_frequency(&clocks, 40.MHz()).unwrap();" +)] +#[cfg_attr( + not(esp32h2), + doc = "let clock_cfg = PeripheralClockConfig::with_frequency(&clocks, 32.MHz()).unwrap();" +)] +/// let mut mcpwm = McPwm::new(peripherals.MCPWM0, clock_cfg); +/// /// let mut pins = mcpwm.operator0.with_linked_pins( -/// pin_a, +/// io.pins.gpio0, /// PwmPinConfig::UP_DOWN_ACTIVE_HIGH, // use PWMA as our main input -/// pin_b, +/// io.pins.gpio1, /// PwmPinConfig::EMPTY, // keep PWMB "low" -/// bride_off, +/// bridge_off, /// ); /// /// pins.set_falling_edge_deadtime(5); @@ -501,6 +518,7 @@ impl<'d, Pin: OutputPin, PWM: PwmPeripheral, const OP: u8, const IS_A: bool> /// pins.set_deadtime_cfg(bridge_active); /// // pin_a: _______-------_____________-------______ /// // pin_b: ------_________-----------_________----- +/// # } /// ``` pub struct LinkedPins<'d, PinA, PinB, PWM, const OP: u8> { pin_a: PwmPin<'d, PinA, PWM, OP, true>, diff --git a/esp-hal/src/parl_io.rs b/esp-hal/src/parl_io.rs index 783e3b9a8..698f9dd34 100644 --- a/esp-hal/src/parl_io.rs +++ b/esp-hal/src/parl_io.rs @@ -12,9 +12,25 @@ //! ## Examples //! //! ### Initialization for TX -//! ```no_run +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use esp_hal::gpio::Io; +//! # use esp_hal::dma_buffers; +//! # use esp_hal::dma::{Dma, DmaPriority}; +//! # use esp_hal::parl_io::{ClkOutPin, no_clk_pin, BitPackOrder, ParlIoTxOnly, SampleEdge, TxFourBits, TxPinConfigWithValidPin}; +//! # use crate::esp_hal::prelude::_fugit_RateExtU32; +//! +//! # let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); +//! +//! # let dma = Dma::new(peripherals.DMA); +//! # let dma_channel = dma.channel0; +//! +//! let (tx_buffer, mut tx_descriptors, _, mut rx_descriptors) = +//! dma_buffers!(32000, 0); let buffer = tx_buffer; +//! //! // configure the data pins to use -//! let tx_pins = TxFourBits::new(io.pins.gpio1, io.pins.gpio2, io.pins.gpio3, io.pins.gpio4); +//! let tx_pins = TxFourBits::new(io.pins.gpio1, io.pins.gpio2, io.pins.gpio3, +//! io.pins.gpio4); //! //! // configure the valid pin which will be driven high during a TX transfer //! let mut pin_conf = TxPinConfigWithValidPin::new(tx_pins, io.pins.gpio5); @@ -45,18 +61,32 @@ //! BitPackOrder::Msb, //! ) //! .unwrap(); -//! ``` //! -//! ### Start TX transfer -//! ```no_run -//! let mut transfer = parl_io_tx.write_dma(buffer).unwrap(); +//! let mut transfer = parl_io_tx.write_dma(&buffer).unwrap(); //! //! transfer.wait().unwrap(); +//! # } //! ``` -//! +//! //! ### Initialization for RX -//! ```no_run -//! let mut rx_pins = RxFourBits::new(io.pins.gpio1, io.pins.gpio2, io.pins.gpio3, io.pins.gpio4); +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use esp_hal::gpio::Io; +//! # use esp_hal::dma_buffers; +//! # use esp_hal::dma::{Dma, DmaPriority}; +//! # use esp_hal::parl_io::{no_clk_pin, BitPackOrder, ParlIoRxOnly, RxFourBits}; +//! # use crate::esp_hal::prelude::_fugit_RateExtU32; +//! +//! # let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); +//! +//! # let dma = Dma::new(peripherals.DMA); +//! # let dma_channel = dma.channel0; +//! +//! let mut rx_pins = RxFourBits::new(io.pins.gpio1, io.pins.gpio2, +//! io.pins.gpio3, io.pins.gpio4); +//! +//! let (_, mut tx_descriptors, rx_buffer, mut rx_descriptors) = dma_buffers!(0, +//! 32000); let mut buffer = rx_buffer; //! //! let parl_io = ParlIoRxOnly::new( //! peripherals.PARL_IO, @@ -75,13 +105,12 @@ //! .rx //! .with_config(&mut rx_pins, no_clk_pin(), BitPackOrder::Msb, Some(0xfff)) //! .unwrap(); -//! ``` //! -//! ### Start RX transfer -//! ```no_run -//! let mut transfer = parl_io_rx.read_dma(buffer).unwrap(); +//! let mut transfer = parl_io_rx.read_dma(&mut buffer).unwrap(); //! transfer.wait().unwrap(); +//! # } //! ``` + #![warn(missing_docs)] use core::marker::PhantomData; diff --git a/esp-hal/src/pcnt/mod.rs b/esp-hal/src/pcnt/mod.rs index a71978dc3..27b52f3b9 100644 --- a/esp-hal/src/pcnt/mod.rs +++ b/esp-hal/src/pcnt/mod.rs @@ -28,107 +28,13 @@ //! 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, Some(interrupt_handler)); -//! 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; -//! let mut pin_b = io.pins.gpio6; -//! -//! ch0.configure( -//! PcntSource::from_pin(&mut pin_a, PcntInputConfig { pull: Pull::Up }), -//! PcntSource::from_pin(&mut pin_b, PcntInputConfig { pull: Pull::Up }), -//! 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, PcntInputConfig { pull: Pull::Up }), -//! PcntSource::from_pin(&mut pin_a, PcntInputConfig { pull: Pull::Up }), -//! 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)); -//! -//! 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 -//! #[handler(priority = esp_hal::interrupt::Priority::Priority2)] -//! fn interrupt_handler() { -//! 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(); -//! } -//! }); -//! } -//! ``` +//! ⚠️: The examples for PCNT peripheral are quite extensive, so for a more +//! detailed study of how to use this driver please visit [the repository +//! with corresponding example]. //! //! [channel]: channel/index.html //! [unit]: unit/index.html +//! [the repository with corresponding example]: https://github.com/esp-rs/esp-hal/blob/main/examples/src/bin/pcnt_encoder.rs use self::unit::Unit; use crate::{ diff --git a/esp-hal/src/peripheral.rs b/esp-hal/src/peripheral.rs index 1bb7333a1..59f8ad022 100644 --- a/esp-hal/src/peripheral.rs +++ b/esp-hal/src/peripheral.rs @@ -20,20 +20,6 @@ //! 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.LPWR, None); -//! ``` -//! ```no_run -//! let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); -//! ``` use core::{ marker::PhantomData, @@ -139,7 +125,7 @@ impl<'a, T> DerefMut for PeripheralRef<'a, T> { /// /// For example, if you have a driver with a constructor like this: /// -/// ```ignore +/// ```rust, ignore /// impl<'d, T: Instance> Twim<'d, T> { /// pub fn new( /// twim: impl Peripheral

+ 'd, @@ -154,14 +140,14 @@ impl<'a, T> DerefMut for PeripheralRef<'a, T> { /// You may call it with owned peripherals, which yields an instance that can /// live forever (`'static`): /// -/// ```ignore +/// ```rust, ignore /// let mut twi: Twim<'static, ...> = Twim::new(p.TWISPI0, irq, p.P0_03, p.P0_04, config); /// ``` /// /// Or you may call it with borrowed peripherals, which yields an instance that /// can only live for as long as the borrows last: /// -/// ```ignore +/// ```rust, ignore /// let mut twi: Twim<'_, ...> = Twim::new(&mut p.TWISPI0, &mut irq, &mut p.P0_03, &mut p.P0_04, config); /// ``` /// diff --git a/esp-hal/src/rmt.rs b/esp-hal/src/rmt.rs index 6948d35f7..720d7ff7c 100644 --- a/esp-hal/src/rmt.rs +++ b/esp-hal/src/rmt.rs @@ -40,8 +40,19 @@ //! //! ### Initialization //! -//! ```no_run -//! let rmt = Rmt::new(peripherals.RMT, 80.MHz(), &mut clock_control, &clocks).unwrap(); +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use esp_hal::peripherals::Peripherals; +//! # use esp_hal::rmt::TxChannelConfig; +//! # use esp_hal::rmt::Rmt; +//! # use esp_hal::gpio::Io; +//! # use esp_hal::clock::ClockControl; +//! # use crate::esp_hal::rmt::TxChannelCreator; +//! # use crate::esp_hal::prelude::_fugit_RateExtU32; +//! # let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); +#![cfg_attr(esp32h2, doc = "let freq = 32.MHz();")] +#![cfg_attr(not(esp32h2), doc = "let freq = 80.MHz();")] +//! let rmt = Rmt::new(peripherals.RMT, freq, &clocks, None).unwrap(); //! let mut channel = rmt //! .channel0 //! .configure( @@ -57,31 +68,11 @@ //! }, //! ) //! .unwrap(); +//! # } //! ``` //! (on ESP32 and ESP32-S2 you cannot specify a base frequency other than 80 //! MHz) -//! -//! ### Sending a pulse sequence -//! -//! ```no_run -//! let data = [ -//! PulseCode { -//! level1: true, -//! length1: 100, -//! level2: false, -//! length2: 300, -//! }, -//! PulseCode { -//! level1: true, -//! length1: 100, -//! level2: false, -//! length2: 0, // a zero-length pulse marks the end of the sequence -//! }, -//! ]; -//! -//! let transaction = channel.transmit(&data); -//! channel = transaction.wait().unwrap(); -//! ``` + #![warn(missing_docs)] use core::marker::PhantomData; diff --git a/esp-hal/src/rng.rs b/esp-hal/src/rng.rs index 98e61709b..3a4579d57 100644 --- a/esp-hal/src/rng.rs +++ b/esp-hal/src/rng.rs @@ -41,26 +41,6 @@ //! //! For more information, please refer to the #![doc = concat!("[ESP-IDF documentation](https://docs.espressif.com/projects/esp-idf/en/latest/", crate::soc::chip!(), "/api-reference/system/random.html)")] -//! # Examples -//! -//! ## Initialization -//! -//! ```no_run -//! let mut rng = Rng::new(peripherals.RNG); -//! ``` -//! -//! ## Generate a random word (u32) -//! -//! ```no_run -//! let random: u32 = rng.random(); -//! ``` -//! -//! ## Fill a buffer of arbitrary size with random bytes -//! -//! ```no_run -//! let mut buffer = [0u8; 32]; -//! rng.read(&mut buffer).unwrap(); -//! ``` use core::marker::PhantomData; diff --git a/esp-hal/src/rom/crc.rs b/esp-hal/src/rom/crc.rs index c2585f6ee..b21b948d3 100644 --- a/esp-hal/src/rom/crc.rs +++ b/esp-hal/src/rom/crc.rs @@ -24,14 +24,20 @@ //! ongoing calculation over multiple buffers. To do this, the initial value //! passed in and the final value returned are one's complemented. //! -//! ``` +//! ```rust, no_run //! // CRC-32/MPEG-2 -//! const CRC_INITIAL: _ = 0xffffffff; // "init" or "xorin" of all ones -//! let mut crc = crc32_be(!CRC_INITIAL, &data0); // start -//! crc = crc32_be(crc, &data1); -//! crc = !crc32_be(crc, &data2); // finish +#![doc = crate::before_snippet!()] +//! # use esp_hal::rom::crc::crc32_be; +//! # let data0 = "123456789"; +//! # let data1 = "123456789"; +//! # let data2 = "123456789"; +//! const CRC_INITIAL: u32 = 0xffffffff; // "init" or "xorin" of all ones +//! let mut crc = crc32_be(!CRC_INITIAL, &data0.as_ref()); // start +//! crc = crc32_be(crc, &data1.as_ref()); +//! crc = !crc32_be(crc, &data2.as_ref()); // finish +//! # } //! ``` -//! +//! //! ## Examples //! //! A catalogue of these parameters can be found at @@ -39,36 +45,51 @@ //! //! CRC-32/ISO-HDLC poly=0x04c11db7 init=0xffffffff refin=true refout=true //! xorout=0xffffffff -//! +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use esp_hal::rom::crc::crc32_le; +//! # let data = "123456789"; +//! let crc = crc32_le(!0xffffffff, &data.as_ref()); +//! # } //! ``` -//! let crc = crc32_le(!0xffffffff, &data); -//! ``` -//! +//! //! CRC-32/BZIP2 poly=0x04c11db7 init=0xffffffff refin=false refout=false //! xorout=0xffffffff -//! +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use esp_hal::rom::crc::crc32_be; +//! # let data = "123456789"; +//! let crc = crc32_be(!0xffffffff, &data.as_ref()); +//! # } //! ``` -//! let crc = crc32_be(!0xffffffff, &data); -//! ``` -//! +//! //! CRC-32/MPEG-2 poly=0x04c11db7 init=0xffffffff refin=false refout=false //! xorout=0x00000000 -//! +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use esp_hal::rom::crc::crc32_be; +//! # let data = "123456789"; +//! let crc = !crc32_be(!0xffffffff, &data.as_ref()); +//! # } //! ``` -//! let crc = !crc32_be(!0xffffffff, &data); -//! ``` -//! +//! //! CRC-32/CKSUM poly=0x04c11db7 init=0x00000000 refin=false refout=false //! xorout=0xffffffff -//! +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use esp_hal::rom::crc::crc32_be; +//! # let data = "123456789"; +//! let crc = crc32_be(!0, &data.as_ref()); +//! # } //! ``` -//! let crc = crc32_be(!0, &data); -//! ``` -//! +//! //! CRC-16/KERMIT poly=0x1021 init=0x0000 refin=true refout=true xorout=0x0000 -//! -//! ``` -//! let crc = !crc16_le(!0, &data); +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use esp_hal::rom::crc::crc16_le; +//! # let data = "123456789"; +//! let crc = !crc16_le(!0, &data.as_ref()); +//! # } //! ``` // SAFETY: These functions are all implemented as table lookups. No locking is diff --git a/esp-hal/src/rom/md5.rs b/esp-hal/src/rom/md5.rs index 07e9aade1..73412e0f8 100644 --- a/esp-hal/src/rom/md5.rs +++ b/esp-hal/src/rom/md5.rs @@ -28,21 +28,37 @@ //! //! To compute a full digest from a single buffer, use the following: //! -//! ``` +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use esp_hal::rom::md5; +//! # use esp_hal::uart::Uart; +//! # use core::writeln; +//! # use core::fmt::Write; +//! # let mut uart0 = Uart::new(peripherals.UART0, &clocks); +//! # let data = "Dummy"; //! let d: md5::Digest = md5::compute(&data); //! writeln!(uart0, "{}", d); +//! # } //! ``` -//! +//! //! To compute a digest over multiple buffers: -//! -//! ``` +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use esp_hal::rom::md5; +//! # use esp_hal::uart::Uart; +//! # use core::writeln; +//! # use core::fmt::Write; +//! # let mut uart0 = Uart::new(peripherals.UART0, &clocks); +//! # let data0 = "Dummy"; +//! # let data1 = "Dummy"; //! let mut ctx = md5::Context::new(); //! ctx.consume(&data0); //! ctx.consume(&data1); //! let d: md5::Digest = ctx.compute(); //! writeln!(uart0, "{}", d); +//! # } //! ``` -//! +//! //! [1]: #[allow(unused)] diff --git a/esp-hal/src/rsa/mod.rs b/esp-hal/src/rsa/mod.rs index 63f635f6c..425dcecef 100644 --- a/esp-hal/src/rsa/mod.rs +++ b/esp-hal/src/rsa/mod.rs @@ -19,38 +19,6 @@ //! 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 rsa = Rsa::new(peripherals.RSA, None); -//! ``` -//! -//! ### Async (modular exponentiation) -//! ```no_run -//! #[embassy_executor::task] -//! async fn mod_exp_example(mut rsa: Rsa<'static>) { -//! let mut outbuf = [0_u32; U512::LIMBS]; -//! let mut mod_exp = RsaModularExponentiation::::new( -//! &mut rsa, -//! BIGNUM_2.as_words(), -//! BIGNUM_3.as_words(), -//! compute_mprime(&BIGNUM_3), -//! ); -//! let r = compute_r(&BIGNUM_3); -//! let base = &BIGNUM_1.as_words(); -//! mod_exp -//! .exponentiation(base, r.as_words(), &mut outbuf) -//! .await; -//! let residue_params = DynResidueParams::new(&BIGNUM_3); -//! let residue = DynResidue::new(&BIGNUM_1, residue_params); -//! let sw_out = residue.pow(&BIGNUM_2); -//! assert_eq!(U512::from_words(outbuf), sw_out.retrieve()); -//! println!("modular exponentiation done"); -//! } -//! ``` - //! This peripheral supports `async` on every available chip except of `esp32` //! (to be solved). //! @@ -59,7 +27,7 @@ //! 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 +//! [the repository with corresponding example]: https://github.com/esp-rs/esp-hal/blob/main/hil-test/tests/rsa.rs use core::{marker::PhantomData, ptr::copy_nonoverlapping}; diff --git a/esp-hal/src/rtc_cntl/mod.rs b/esp-hal/src/rtc_cntl/mod.rs index ab8a39f1b..b6b443427 100644 --- a/esp-hal/src/rtc_cntl/mod.rs +++ b/esp-hal/src/rtc_cntl/mod.rs @@ -19,51 +19,52 @@ //! //! ## Examples //! ### Print time in milliseconds from the RTC Timer -//! ```no_run +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use core::cell::RefCell; +//! +//! # use critical_section::Mutex; +//! # use esp_hal::delay::Delay; +//! # use esp_hal::rtc_cntl::Rtc; +//! # use esp_hal::rtc_cntl::Rwdt; +//! # use crate::esp_hal::prelude::_fugit_ExtU64; +//! static RWDT: Mutex>> = Mutex::new(RefCell::new(None)); //! 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()); +//! let mut rtc = Rtc::new(peripherals.LPWR, Some(interrupt_handler)); +//! rtc.rwdt.set_timeout(2000.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 +//! // Where the `LP_WDT` interrupt handler is defined as: //! // Handle the corresponding interrupt +//! # use core::cell::RefCell; +//! +//! # use critical_section::Mutex; +//! # use esp_hal::prelude::handler; +//! # use esp_hal::interrupt::InterruptHandler; +//! # use esp_hal::interrupt; +//! # use esp_hal::interrupt::Priority; +//! # use crate::esp_hal::prelude::_fugit_ExtU64; +//! # use esp_hal::rtc_cntl::Rwdt; +//! static RWDT: Mutex>> = Mutex::new(RefCell::new(None)); //! #[handler] //! fn interrupt_handler() { //! critical_section::with(|cs| { -//! esp_println::println!("RWDT Interrupt"); +//! // 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..."); +//! // esp_println::println!("Restarting in 5 seconds..."); //! -//! rwdt.start(5000u64.millis()); +//! rwdt.set_timeout(5000u64.millis()); //! rwdt.unlisten(); //! }); //! } diff --git a/esp-hal/src/sha.rs b/esp-hal/src/sha.rs index 407889011..092e22a2c 100644 --- a/esp-hal/src/sha.rs +++ b/esp-hal/src/sha.rs @@ -28,32 +28,37 @@ //! if needed. //! //! ## Example -//! ```no_run +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use esp_hal::sha::Sha; +//! # use esp_hal::sha::ShaMode; +//! # use core::option::Option::None; +//! # use nb::block; //! let source_data = "HELLO, ESPRESSIF!".as_bytes(); //! let mut remaining = source_data; -//! let mut hasher = Sha::new(peripherals.SHA, ShaMode::SHA256); -//! -//! // Short hashes can be created by decreasing the output buffer to the desired -//! // length +#![cfg_attr( + not(esp32), + doc = "let mut hasher = Sha::new(peripherals.SHA, ShaMode::SHA256, None);" +)] +#![cfg_attr( + esp32, + doc = "let mut hasher = Sha::new(peripherals.SHA, ShaMode::SHA256);" +)] +//! // 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! +//! // 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. +//! // 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, marker::PhantomData}; diff --git a/esp-hal/src/soc/esp32/cpu_control.rs b/esp-hal/src/soc/esp32/cpu_control.rs index a823ee796..a0947f2a8 100644 --- a/esp-hal/src/soc/esp32/cpu_control.rs +++ b/esp-hal/src/soc/esp32/cpu_control.rs @@ -8,41 +8,47 @@ //! //! ## Example //! -//! ```no_run +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use esp_hal::delay::Delay; +//! # use esp_hal::cpu_control::{CpuControl, Stack}; +//! # use core::{cell::RefCell, ptr::addr_of_mut}; +//! # use critical_section::Mutex; +//! # use esp_hal::prelude::*; //! static mut APP_CORE_STACK: Stack<8192> = Stack::new(); //! +//! # let delay = Delay::new(&clocks); +//! //! let counter = Mutex::new(RefCell::new(0)); //! //! let mut cpu_control = CpuControl::new(peripherals.CPU_CTRL); //! let cpu1_fnctn = || { -//! cpu1_task(&mut timer1, &counter); +//! cpu1_task(&delay, &counter); //! }; //! let _guard = cpu_control -//! .start_app_core(unsafe { &mut APP_CORE_STACK }, cpu1_fnctn) -//! .unwrap(); +//! .start_app_core(unsafe { &mut *addr_of_mut!(APP_CORE_STACK) }, +//! cpu1_fnctn) .unwrap(); //! //! loop { -//! block!(timer0.wait()).unwrap(); -//! +//! delay.delay(1.secs()); //! 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 +//! // Where `cpu1_task()` may be defined as: +//! # use esp_hal::delay::Delay; +//! # use core::cell::RefCell; +//! # use esp_hal::prelude::*; //! fn cpu1_task( -//! timer: &mut Timer>, +//! delay: &Delay, //! counter: &critical_section::Mutex>, //! ) -> ! { -//! println!("Hello World - Core 1!"); //! loop { -//! block!(timer.wait()).unwrap(); +//! delay.delay(500.millis()); //! //! critical_section::with(|cs| { -//! let new_val = counter.borrow_ref_mut(cs).wrapping_add(1); -//! *counter.borrow_ref_mut(cs) = new_val; +//! let mut val = counter.borrow_ref_mut(cs); +//! *val = val.wrapping_add(1); //! }); //! } //! } diff --git a/esp-hal/src/soc/esp32/efuse/mod.rs b/esp-hal/src/soc/esp32/efuse/mod.rs index 4514b08b4..4bae02441 100644 --- a/esp-hal/src/soc/esp32/efuse/mod.rs +++ b/esp-hal/src/soc/esp32/efuse/mod.rs @@ -19,7 +19,13 @@ //! ## Example //! //! ### Read chip's MAC address from the eFuse storage. -//! ```no_run +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use esp_hal::efuse::Efuse; +//! # use esp_hal::uart::Uart; +//! # use core::writeln; +//! # use core::fmt::Write; +//! # let mut serial_tx = Uart::new(peripherals.UART0, &clocks); //! let mac_address = Efuse::read_base_mac_address(); //! writeln!( //! serial_tx, @@ -31,6 +37,7 @@ //! mac_address[4], //! mac_address[5] //! ); +//! # } //! ``` use fugit::{HertzU32, RateExtU32}; diff --git a/esp-hal/src/soc/esp32c2/efuse/mod.rs b/esp-hal/src/soc/esp32c2/efuse/mod.rs index 9b02b5131..ecc687210 100644 --- a/esp-hal/src/soc/esp32c2/efuse/mod.rs +++ b/esp-hal/src/soc/esp32c2/efuse/mod.rs @@ -19,7 +19,13 @@ //! ## Example //! //! ### Read chip's MAC address from the eFuse storage. -//! ```no_run +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use esp_hal::efuse::Efuse; +//! # use esp_hal::uart::Uart; +//! # use core::writeln; +//! # use core::fmt::Write; +//! # let mut serial_tx = Uart::new(peripherals.UART0, &clocks); //! let mac_address = Efuse::read_base_mac_address(); //! writeln!( //! serial_tx, @@ -31,6 +37,7 @@ //! mac_address[4], //! mac_address[5] //! ); +//! # } //! ``` pub use self::fields::*; diff --git a/esp-hal/src/soc/esp32c3/efuse/mod.rs b/esp-hal/src/soc/esp32c3/efuse/mod.rs index 16f7a685e..7ed70bea1 100644 --- a/esp-hal/src/soc/esp32c3/efuse/mod.rs +++ b/esp-hal/src/soc/esp32c3/efuse/mod.rs @@ -19,7 +19,13 @@ //! ## Example //! //! ### Read chip's MAC address from the eFuse storage. -//! ```no_run +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use esp_hal::efuse::Efuse; +//! # use esp_hal::uart::Uart; +//! # use core::writeln; +//! # use core::fmt::Write; +//! # let mut serial_tx = Uart::new(peripherals.UART0, &clocks); //! let mac_address = Efuse::read_base_mac_address(); //! writeln!( //! serial_tx, @@ -31,6 +37,7 @@ //! mac_address[4], //! mac_address[5] //! ); +//! # } //! ``` pub use self::fields::*; diff --git a/esp-hal/src/soc/esp32c6/efuse/mod.rs b/esp-hal/src/soc/esp32c6/efuse/mod.rs index 13214b50e..a16a854ba 100644 --- a/esp-hal/src/soc/esp32c6/efuse/mod.rs +++ b/esp-hal/src/soc/esp32c6/efuse/mod.rs @@ -19,7 +19,13 @@ //! ## Example //! //! ### Read chip's MAC address from the eFuse storage. -//! ```no_run +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use esp_hal::efuse::Efuse; +//! # use esp_hal::uart::Uart; +//! # use core::writeln; +//! # use core::fmt::Write; +//! # let mut serial_tx = Uart::new(peripherals.UART0, &clocks); //! let mac_address = Efuse::read_base_mac_address(); //! writeln!( //! serial_tx, @@ -31,6 +37,7 @@ //! mac_address[4], //! mac_address[5] //! ); +//! # } //! ``` pub use self::fields::*; diff --git a/esp-hal/src/soc/esp32c6/lp_core.rs b/esp-hal/src/soc/esp32c6/lp_core.rs index b1ab8226e..24330a349 100644 --- a/esp-hal/src/soc/esp32c6/lp_core.rs +++ b/esp-hal/src/soc/esp32c6/lp_core.rs @@ -13,30 +13,11 @@ //! //! The `run` method starts the low power core and specifies the wakeup source. //! -//! ## Example -//! ```no_run -//! // configure GPIO 1 as LP output pin -//! let lp_pin = LowPowerOutput::new(io.pins.gpio1); +//! ⚠️: The examples for LP Core are quite extensive, so for a more +//! detailed study of how to use this LP Core please visit [the repository +//! with corresponding example]. //! -//! let mut lp_core = esp_hal::lp_core::LpCore::new(peripherals.LP_CORE); -//! lp_core.stop(); -//! println!("lp core stopped"); -//! -//! // load code to LP core -//! let lp_core_code = -//! load_lp_code!("../esp-lp-hal/target/riscv32imac-unknown-none-elf/release/examples/blinky"); -//! -//! // start LP core -//! lp_core.run(lp_core::LpCoreWakeupSource::HpCpu); -//! println!("lpcore run"); -//! -//! let data = (0x5000_2000) as *mut u32; -//! loop { -//! print!("Current {:x} \u{000d}", unsafe { -//! data.read_volatile() -//! }); -//! } -//! ``` +//! [the repository with corresponding example]: https://github.com/esp-rs/esp-hal/blob/main/examples/src/bin/lp_core_basic.rs use esp32c6 as pac; diff --git a/esp-hal/src/soc/esp32h2/efuse/mod.rs b/esp-hal/src/soc/esp32h2/efuse/mod.rs index 0e6ef809b..f5c628f0a 100644 --- a/esp-hal/src/soc/esp32h2/efuse/mod.rs +++ b/esp-hal/src/soc/esp32h2/efuse/mod.rs @@ -19,7 +19,13 @@ //! ## Example //! //! ### Read chip's MAC address from the eFuse storage. -//! ```no_run +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use esp_hal::efuse::Efuse; +//! # use esp_hal::uart::Uart; +//! # use core::writeln; +//! # use core::fmt::Write; +//! # let mut serial_tx = Uart::new(peripherals.UART0, &clocks); //! let mac_address = Efuse::read_base_mac_address(); //! writeln!( //! serial_tx, @@ -31,6 +37,7 @@ //! mac_address[4], //! mac_address[5] //! ); +//! # } //! ``` pub use self::fields::*; diff --git a/esp-hal/src/soc/esp32s2/efuse/mod.rs b/esp-hal/src/soc/esp32s2/efuse/mod.rs index c1de26982..786d3d480 100644 --- a/esp-hal/src/soc/esp32s2/efuse/mod.rs +++ b/esp-hal/src/soc/esp32s2/efuse/mod.rs @@ -19,7 +19,13 @@ //! ## Example //! //! ### Read chip's MAC address from the eFuse storage. -//! ```no_run +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use esp_hal::efuse::Efuse; +//! # use esp_hal::uart::Uart; +//! # use core::writeln; +//! # use core::fmt::Write; +//! # let mut serial_tx = Uart::new(peripherals.UART0, &clocks); //! let mac_address = Efuse::read_base_mac_address(); //! writeln!( //! serial_tx, @@ -31,6 +37,7 @@ //! mac_address[4], //! mac_address[5] //! ); +//! # } //! ``` pub use self::fields::*; @@ -42,22 +49,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 read_base_mac_address() -> [u8; 6] { Self::read_field_be(MAC) } diff --git a/esp-hal/src/soc/esp32s2/ulp_core.rs b/esp-hal/src/soc/esp32s2/ulp_core.rs index fc571c0c7..15852c25e 100644 --- a/esp-hal/src/soc/esp32s2/ulp_core.rs +++ b/esp-hal/src/soc/esp32s2/ulp_core.rs @@ -13,28 +13,30 @@ //! CORE` instance. //! //! ## Example -//! ```no_run -//! let mut ulp_core = esp_hal::ulp_core::UlpCore::new(peripherals.ULP_RISCV_CORE); -//! ulp_core.stop(); -//! println!("ulp core stopped"); +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! const CODE: &[u8] = &[ +//! 0x17, 0x05, 0x00, 0x00, 0x13, 0x05, 0x05, 0x01, 0x81, 0x45, 0x85, 0x05, +//! 0x0c, 0xc1, 0xf5, 0xbf, 0x00, 0x00, 0x00, 0x00, +//! ]; +//! let mut ulp_core = +//! esp_hal::ulp_core::UlpCore::new(peripherals.ULP_RISCV_CORE); +//! // ulp_core.stop(); currently not implemented //! //! // 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()); +//! core::ptr::copy_nonoverlapping(CODE as *const _ as *const u8, lp_ram, +//! CODE.len()); } //! //! // start ULP core //! ulp_core.run(esp_hal::ulp_core::UlpCoreWakeupSource::HpCpu); -//! println!("ulpcore run"); //! //! unsafe { //! let data = 0x5000_0010 as *mut u32; -//! loop { -//! println!("Current {}", unsafe { data.read_volatile() }); -//! } +//! loop {} //! } +//! # } //! ``` use esp32s2 as pac; diff --git a/esp-hal/src/soc/esp32s3/cpu_control.rs b/esp-hal/src/soc/esp32s3/cpu_control.rs index 032af814c..407448a04 100644 --- a/esp-hal/src/soc/esp32s3/cpu_control.rs +++ b/esp-hal/src/soc/esp32s3/cpu_control.rs @@ -8,41 +8,47 @@ //! //! ## Example //! -//! ```no_run +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use esp_hal::delay::Delay; +//! # use esp_hal::cpu_control::{CpuControl, Stack}; +//! # use core::{cell::RefCell, ptr::addr_of_mut}; +//! # use critical_section::Mutex; +//! # use esp_hal::prelude::*; //! static mut APP_CORE_STACK: Stack<8192> = Stack::new(); //! +//! # let delay = Delay::new(&clocks); +//! //! let counter = Mutex::new(RefCell::new(0)); //! //! let mut cpu_control = CpuControl::new(peripherals.CPU_CTRL); //! let cpu1_fnctn = || { -//! cpu1_task(&mut timer1, &counter); +//! cpu1_task(&delay, &counter); //! }; //! let _guard = cpu_control -//! .start_app_core(unsafe { &mut APP_CORE_STACK }, cpu1_fnctn) -//! .unwrap(); +//! .start_app_core(unsafe { &mut *addr_of_mut!(APP_CORE_STACK) }, +//! cpu1_fnctn) .unwrap(); //! //! loop { -//! block!(timer0.wait()).unwrap(); -//! +//! delay.delay(1.secs()); //! 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 +//! // Where `cpu1_task()` may be defined as: +//! # use esp_hal::delay::Delay; +//! # use core::cell::RefCell; +//! # use esp_hal::prelude::*; //! fn cpu1_task( -//! timer: &mut Timer>, +//! delay: &Delay, //! counter: &critical_section::Mutex>, //! ) -> ! { -//! println!("Hello World - Core 1!"); //! loop { -//! block!(timer.wait()).unwrap(); +//! delay.delay(500.millis()); //! //! critical_section::with(|cs| { -//! let new_val = counter.borrow_ref_mut(cs).wrapping_add(1); -//! *counter.borrow_ref_mut(cs) = new_val; +//! let mut val = counter.borrow_ref_mut(cs); +//! *val = val.wrapping_add(1); //! }); //! } //! } diff --git a/esp-hal/src/soc/esp32s3/efuse/mod.rs b/esp-hal/src/soc/esp32s3/efuse/mod.rs index 3c806bc48..da84efce3 100644 --- a/esp-hal/src/soc/esp32s3/efuse/mod.rs +++ b/esp-hal/src/soc/esp32s3/efuse/mod.rs @@ -19,7 +19,13 @@ //! ## Example //! //! ### Read chip's MAC address from the eFuse storage. -//! ```no_run +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use esp_hal::efuse::Efuse; +//! # use esp_hal::uart::Uart; +//! # use core::writeln; +//! # use core::fmt::Write; +//! # let mut serial_tx = Uart::new(peripherals.UART0, &clocks); //! let mac_address = Efuse::read_base_mac_address(); //! writeln!( //! serial_tx, @@ -31,6 +37,7 @@ //! mac_address[4], //! mac_address[5] //! ); +//! # } //! ``` pub use self::fields::*; diff --git a/esp-hal/src/soc/esp32s3/ulp_core.rs b/esp-hal/src/soc/esp32s3/ulp_core.rs index edca1e814..578a901a3 100644 --- a/esp-hal/src/soc/esp32s3/ulp_core.rs +++ b/esp-hal/src/soc/esp32s3/ulp_core.rs @@ -13,28 +13,30 @@ //! to the `ULP CORE` instance. //! //! ## Example -//! ```no_run -//! let mut ulp_core = esp_hal::ulp_core::UlpCore::new(peripherals.ULP_RISCV_CORE); +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! const CODE: &[u8] = &[ +//! 0x17, 0x05, 0x00, 0x00, 0x13, 0x05, 0x05, 0x01, 0x81, 0x45, 0x85, 0x05, +//! 0x0c, 0xc1, 0xf5, 0xbf, 0x00, 0x00, 0x00, 0x00, +//! ]; +//! let mut ulp_core = +//! esp_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()); +//! core::ptr::copy_nonoverlapping(CODE as *const _ as *const u8, lp_ram, +//! CODE.len()); } //! //! // start ULP core //! ulp_core.run(esp_hal::ulp_core::UlpCoreWakeupSource::HpCpu); -//! println!("ulpcore run"); //! //! unsafe { //! let data = 0x5000_0010 as *mut u32; -//! loop { -//! println!("Current {}", unsafe { data.read_volatile() }); -//! } +//! loop {} //! } +//! # } //! ``` use esp32s3 as pac; diff --git a/esp-hal/src/spi/master.rs b/esp-hal/src/spi/master.rs index 1833aebad..b9eb455b4 100644 --- a/esp-hal/src/spi/master.rs +++ b/esp-hal/src/spi/master.rs @@ -7,23 +7,28 @@ //! [`Spi::new`]. //! //! ## Example -//! ```rust -//! let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); -//! let sclk = io.pins.gpio12; -//! let miso = io.pins.gpio11; -//! let mosi = io.pins.gpio13; -//! let cs = io.pins.gpio10; +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use crate::esp_hal::prelude::_fugit_RateExtU32; +//! # use esp_hal::spi::SpiMode; +//! # use esp_hal::spi::master::Spi; +//! # use esp_hal::gpio::Io; +//! # let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); +//! let sclk = io.pins.gpio0; +//! let miso = io.pins.gpio2; +//! let mosi = io.pins.gpio1; +//! let cs = io.pins.gpio5; //! -//! let mut spi = hal::spi::Spi::new( +//! let mut spi = Spi::new( //! peripherals.SPI2, //! 100.kHz(), //! SpiMode::Mode0, -//! &mut peripheral_clock_control, //! &mut clocks, //! ) //! .with_pins(Some(sclk), Some(mosi), Some(miso), Some(cs)); +//! # } //! ``` -//! +//! //! ## Exclusive access to the SPI bus //! //! If all you want to do is to communicate to a single device, and you initiate diff --git a/esp-hal/src/spi/slave.rs b/esp-hal/src/spi/slave.rs index 2877ba9e5..fc3d28b88 100644 --- a/esp-hal/src/spi/slave.rs +++ b/esp-hal/src/spi/slave.rs @@ -8,16 +8,6 @@ //! //! ## Example //! -//! ```rust -//! let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); -//! let sclk = io.pins.gpio12; -//! let miso = io.pins.gpio11; -//! let mosi = io.pins.gpio13; -//! let cs = io.pins.gpio10; -//! -//! let mut spi = hal::spi::slave::Spi::new(peripherals.SPI2, sclk, mosi, miso, cs, SpiMode::Mode0); -//! ``` -//! //! There are several options for working with the SPI peripheral in slave mode, //! but the code currently only supports single transfers (not segmented //! transfers), full duplex, single bit (not dual or quad SPI), and DMA mode @@ -26,24 +16,48 @@ //! then the DmaTransfer trait instance can be wait()ed on or polled for //! is_done(). //! -//! ```rust -//! let dma = Gdma::new(peripherals.DMA); -//! const N: usize = (buffer_size + 4091) / 4092; -//! let mut tx_descriptors = [0u32; N * 3]; -//! let mut rx_descriptors = [0u32; N * 3]; -//! let mut spi = spi.with_dma(dma.channel0.configure( -//! /* circular = */ false, -//! tx_descriptors, -//! rx_descriptors, +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use esp_hal::dma::DmaPriority; +//! # use esp_hal::dma_buffers; +//! # use esp_hal::spi::SpiMode; +//! # use esp_hal::spi::slave::{prelude::*, Spi}; +//! # use esp_hal::dma::Dma; +//! # use esp_hal::gpio::Io; +//! let dma = Dma::new(peripherals.DMA); +#![cfg_attr(esp32s2, doc = "let dma_channel = dma.spi2channel;")] +#![cfg_attr(not(esp32s2), doc = "let dma_channel = dma.channel0;")] +//! let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); +//! let sclk = io.pins.gpio0; +//! let miso = io.pins.gpio1; +//! let mosi = io.pins.gpio2; +//! let cs = io.pins.gpio3; +//! +//! let (tx_buffer, mut tx_descriptors, rx_buffer, mut rx_descriptors) = +//! dma_buffers!(32000); let mut spi = Spi::new( +//! peripherals.SPI2, +//! sclk, +//! mosi, +//! miso, +//! cs, +//! SpiMode::Mode0, +//! ) +//! .with_dma(dma_channel.configure( +//! false, +//! &mut tx_descriptors, +//! &mut rx_descriptors, //! DmaPriority::Priority0, //! )); -//! // This is not legal rust, but any method of getting a &mut 'static is good. -//! let tx_buf = &'static [0u8; N * 4092]; -//! let rx_buf = &mut 'static [0u8; N * 4092]; -//! let transfer = spi.dma_transfer(tx_buf, rx_buf).unwrap(); -//! // Do other operations, checking transfer.is_done() -//! // When the master sends enough clock pulses, is_done() will be true. -//! (tx_buf, rx_buf, spi) = transfer.wait(); +//! +//! let mut send = tx_buffer; +//! let mut receive = rx_buffer; +//! +//! let transfer = spi +//! .dma_transfer(&mut send, &mut receive) +//! .unwrap(); +//! +//! transfer.wait().unwrap(); +//! # } //! ``` use core::marker::PhantomData; diff --git a/esp-hal/src/system.rs b/esp-hal/src/system.rs index 9d1917d24..a741baeba 100755 --- a/esp-hal/src/system.rs +++ b/esp-hal/src/system.rs @@ -21,10 +21,12 @@ //! The available peripherals are represented by the `Peripheral` enum //! //! ## Example -//! ```no_run +//! ```rust, no_run +#![doc = crate::before_snippet!()] //! let peripherals = Peripherals::take(); //! let system = SystemControl::new(peripherals.SYSTEM); //! let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); +//! # } //! ``` use crate::{interrupt::InterruptHandler, peripheral::PeripheralRef, peripherals::SYSTEM}; diff --git a/esp-hal/src/time.rs b/esp-hal/src/time.rs index 034e7acd2..8341c676e 100644 --- a/esp-hal/src/time.rs +++ b/esp-hal/src/time.rs @@ -1,8 +1,11 @@ //! The `time` module offers a way to get the system uptime. //! //! ### Example -//! ```no_run +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use esp_hal::time; //! let time = time::current_time(); +//! # } //! ``` #![warn(missing_docs)] diff --git a/esp-hal/src/timer/mod.rs b/esp-hal/src/timer/mod.rs index 4362d66d9..f3e75675d 100644 --- a/esp-hal/src/timer/mod.rs +++ b/esp-hal/src/timer/mod.rs @@ -9,23 +9,32 @@ //! //! #### One-shot Timer //! -//! ```no_run +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use esp_hal::timer::{OneShotTimer, PeriodicTimer, timg::TimerGroup}; +//! # use esp_hal::prelude::*; +//! # use core::option::Option::None; //! let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks, None); //! let one_shot = OneShotTimer::new(timg0.timer0); //! //! one_shot.delay_millis(500); +//! # } //! ``` -//! +//! //! #### Periodic Timer -//! -//! ```no_run +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use esp_hal::timer::{PeriodicTimer, timg::TimerGroup}; +//! # use esp_hal::prelude::*; +//! # use core::option::Option::None; //! let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks, None); -//! let periodic = PeriodicTimer::new(timg0.timer0); +//! let mut periodic = PeriodicTimer::new(timg0.timer0); //! //! periodic.start(1.secs()); //! loop { //! nb::block!(periodic.wait()); //! } +//! # } //! ``` #![deny(missing_docs)] diff --git a/esp-hal/src/timer/systimer.rs b/esp-hal/src/timer/systimer.rs index 785748dbe..2271e94e0 100644 --- a/esp-hal/src/timer/systimer.rs +++ b/esp-hal/src/timer/systimer.rs @@ -17,19 +17,60 @@ //! //! #### General-purpose Timer //! -//! ```no_run +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use esp_hal::timer::systimer::SystemTimer; +//! # use esp_hal::timer::timg::{TimerGroup, TimerInterrupts}; +//! # use crate::esp_hal::prelude::_esp_hal_timer_Timer; +//! # use esp_hal::prelude::*; //! let systimer = SystemTimer::new(peripherals.SYSTIMER); //! //! // Get the current timestamp, in microseconds: -//! let now = systimer.now(); +//! let now = SystemTimer::now(); +//! +//! let timg0 = TimerGroup::new( +//! peripherals.TIMG0, +//! &clocks, +//! Some(TimerInterrupts { +//! timer0_t0: Some(tg0_t0_level), +//! ..Default::default() +//! }), +//! ); +//! +//! # let timer0 = timg0.timer0; //! //! // Wait for timeout: -//! systimer.load_value(1.secs()); -//! systimer.start(); +//! timer0.load_value(1.secs()); +//! timer0.start(); //! -//! while !systimer.is_interrupt_set() { +//! while !timer0.is_interrupt_set() { //! // Wait //! } +//! # } +//! +//! +//! # use core::cell::RefCell; +//! # use critical_section::Mutex; +//! # use procmacros::handler; +//! # use esp_hal::interrupt::InterruptHandler; +//! # use esp_hal::interrupt; +//! # use esp_hal::peripherals::TIMG0; +//! # use esp_hal::timer::timg::{Timer, Timer0}; +//! # use crate::esp_hal::prelude::_esp_hal_timer_Timer; +//! # static TIMER0: Mutex, esp_hal::Blocking>>>> = Mutex::new(RefCell::new(None)); +//! #[handler] +//! fn tg0_t0_level() { +//! critical_section::with(|cs| { +//! let mut timer0 = TIMER0.borrow_ref_mut(cs); +//! let timer0 = timer0.as_mut().unwrap(); +//! +//! timer0.clear_interrupt(); +//! +//! // Counter value should be a very small number as the alarm triggered a +//! // counter reload to 0 and ETM stopped the counter quickly after +//! // esp_println::println!("counter in interrupt: {}", timer0.now()); +//! }); +//! } //! ``` use core::marker::PhantomData; @@ -662,12 +703,16 @@ pub mod etm { //! COMPx //! //! ## Example - //! ```no_run + //! ```rust, no_run + #![doc = crate::before_snippet!()] + //! # use esp_hal::timer::systimer::{etm::SysTimerEtmEvent, SystemTimer}; + //! # use fugit::ExtU32; //! let syst = SystemTimer::new(peripherals.SYSTIMER); //! let mut alarm0 = syst.alarm0.into_periodic(); //! alarm0.set_period(1.secs()); //! //! let timer_event = SysTimerEtmEvent::new(&mut alarm0); + //! # } //! ``` use super::*; diff --git a/esp-hal/src/timer/timg.rs b/esp-hal/src/timer/timg.rs index 53e2d76f5..abeb0eaf6 100644 --- a/esp-hal/src/timer/timg.rs +++ b/esp-hal/src/timer/timg.rs @@ -20,8 +20,12 @@ //! //! #### General-purpose Timer //! -//! ```no_run -//! let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks); +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use esp_hal::timer::timg::TimerGroup; +//! # use crate::esp_hal::prelude::_esp_hal_timer_Timer; +//! # use esp_hal::prelude::*; +//! let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks, None); //! let timer0 = timg0.timer0; //! //! // Get the current timestamp, in microseconds: @@ -34,12 +38,15 @@ //! while !timer0.is_interrupt_set() { //! // Wait //! } +//! # } //! ``` -//! +//! //! #### Watchdog Timer -//! -//! ```no_run -//! let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks); +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use esp_hal::timer::timg::TimerGroup; +//! # use esp_hal::prelude::*; +//! let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks, None); //! let mut wdt = timg0.wdt; //! //! wdt.set_timeout(5_000.millis()); @@ -48,6 +55,7 @@ //! loop { //! wdt.feed(); //! } +//! # } //! ``` use core::{ diff --git a/esp-hal/src/trace.rs b/esp-hal/src/trace.rs index 076e8e747..9cdaa3176 100644 --- a/esp-hal/src/trace.rs +++ b/esp-hal/src/trace.rs @@ -20,15 +20,18 @@ //! program execution. //! //! ## Example -//! ```no_run +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use esp_hal::trace::Trace; //! let mut trace = Trace::new(peripherals.TRACE0); -//! let buffer = unsafe { &mut BUFFER[..] }; -//! trace.start_trace(buffer); +//! let mut buffer = [0_u8; 1024]; +//! trace.start_trace(&mut buffer); //! // traced code -//! println!("Hello"); +//! //! // end traced code //! let res = trace.stop_trace().unwrap(); //! // transfer the trace result to the host and decode it there +//! # } //! ``` use crate::{ diff --git a/esp-hal/src/twai/filter.rs b/esp-hal/src/twai/filter.rs index 36aac7beb..6d19f3c92 100644 --- a/esp-hal/src/twai/filter.rs +++ b/esp-hal/src/twai/filter.rs @@ -89,7 +89,7 @@ impl SingleStandardFilter { /// /// Example matching only even IDs, allowing any rtr value and any payload /// data: - /// ``` + /// ```rust, ignore /// const FILTER: SingleStandardFilter = /// SingleStandardFilter::new(b"xxxxxxxxxx0", b"x", [b"xxxxxxxx", b"xxxxxxxx"]); /// ``` @@ -149,7 +149,7 @@ impl SingleStandardFilter { /// /// A filter that matches every standard id that is even, is not an rtr /// frame, with any bytes for the first two payload bytes. - /// ``` + /// ```rust, ignore /// let filter = twai::filter::SingleStandardFilter::new_from_code_mask( /// StandardId::new(0x000).unwrap(), /// StandardId::new(0x001).unwrap(), @@ -213,7 +213,7 @@ impl SingleExtendedFilter { /// /// # Examples /// A filter matching any odd extended IDs, with any rtr value. - /// ``` + /// ```rust, ignore /// const FILTER: twai::filter::SingleExtendedFilter = /// twai::filter::SingleExtendedFilter::new(b"xxxxxxxxxxxxxxxxxxxxxxxxxxxx1", b"x"); /// ``` @@ -304,7 +304,7 @@ impl DualStandardFilter { /// # Examples /// A filter that matches any standard id that ends with a 00 or a 11, with /// any RTR, and with any payload on the first filter. - /// ``` + /// ```rust, ignore /// const FILTER: twai::filter::DualStandardFilter = twai::filter::DualStandardFilter::new( /// b"xxxxxxxxx00", /// b"x", @@ -452,7 +452,7 @@ impl DualExtendedFilter { /// part of the id. For example this id matches: 0x000f000f, 0x000f000a, /// 0x0000000a, 0x0000000b. /// But it does not match: 0x000a000a - /// ``` + /// ```rust, ignore /// const FILTER: twai::filter::DualExtendedFilter = /// twai::filter::DualExtendedFilter::new([b"xxxxxxxxx0000xxx", b"xxxxxxxxx1111xxx"]); /// ``` diff --git a/esp-hal/src/twai/mod.rs b/esp-hal/src/twai/mod.rs index ca8ddc632..f444c5ad6 100644 --- a/esp-hal/src/twai/mod.rs +++ b/esp-hal/src/twai/mod.rs @@ -17,14 +17,26 @@ //! Format (29-bit) frame identifiers. //! //! ## Example -//! ```no_run +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use esp_hal::twai; +//! # use embedded_can::Id; +//! # use esp_hal::twai::filter::SingleStandardFilter; +//! # use esp_hal::twai::filter; +//! # use esp_hal::twai::TwaiConfiguration; +//! # use esp_hal::twai::BaudRate; +//! # use esp_hal::gpio::Io; +//! # use embedded_can::Frame; +//! # use core::option::Option::None; +//! # use nb::block; +//! # let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); //! // 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; +//! const CAN_BAUDRATE: twai::BaudRate = BaudRate::B1000K; //! //! // Begin configuring the TWAI peripheral. The peripheral is in a reset like //! // state that prevents transmission but allows configuration. @@ -37,43 +49,25 @@ //! None, //! ); //! -//! // Partially filter the incoming messages to reduce overhead of receiving undesired messages +//! // 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); +//! 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. +//! // 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(); //! } +//! # } //! ``` use core::marker::PhantomData; diff --git a/esp-hal/src/uart.rs b/esp-hal/src/uart.rs index d48a556ac..e2a1eb848 100644 --- a/esp-hal/src/uart.rs +++ b/esp-hal/src/uart.rs @@ -18,14 +18,20 @@ //! configured. Additionally, the transmit (TX) and receive (RX) pins can be //! specified. //! -//! ```no_run +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use core::option::Option::Some; +//! # use esp_hal::uart::{config::Config, TxRxPins, Uart}; +//! use esp_hal::gpio::Io; //! let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); //! let pins = TxRxPins::new_tx_rx(io.pins.gpio1, io.pins.gpio2); //! //! let mut uart1 = -//! Uart::new_with_config(peripherals.UART1, Config::default(), Some(pins), &clocks); +//! Uart::new_with_config(peripherals.UART1, Config::default(), Some(pins), +//! &clocks, None); +//! # } //! ``` -//! +//! //! ## Usage //! //! The UART driver implements a number of third-party traits, with the @@ -41,23 +47,47 @@ //! ### Examples //! //! #### Sending and Receiving Data -//! -//! ```no_run +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use esp_hal::uart::{config::Config, TxRxPins, Uart}; +//! use esp_hal::gpio::Io; +//! # let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); +//! # let pins = TxRxPins::new_tx_rx(io.pins.gpio1, io.pins.gpio2); +//! # let mut uart1 = Uart::new_with_config( +//! # peripherals.UART1, +//! # Config::default(), +//! # Some(pins), +//! # &clocks, +//! # None, +//! # ); //! // Write bytes out over the UART: -//! uart1.write_bytes("Hello, world!".as_bytes())?; +//! uart1.write_bytes("Hello, world!".as_bytes()).expect("write error!"); +//! # } //! ``` -//! +//! //! #### Splitting the UART into TX and RX Components -//! -//! ```no_run +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use esp_hal::uart::{config::Config, TxRxPins, Uart}; +//! use esp_hal::gpio::Io; +//! # let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); +//! # let pins = TxRxPins::new_tx_rx(io.pins.gpio1, io.pins.gpio2); +//! # let mut uart1 = Uart::new_with_config( +//! # peripherals.UART1, +//! # Config::default(), +//! # Some(pins), +//! # &clocks, +//! # None, +//! # ); //! // The UART can be split into separate Transmit and Receive components: -//! let (mut tx, rx) = uart1.split(); +//! let (mut tx, mut rx) = uart1.split(); //! //! // Each component can be used individually to interact with the UART: -//! tx.write_bytes(&[42u8])?; -//! let byte = rx.read_byte()?; +//! tx.write_bytes(&[42u8]).expect("write error!"); +//! let byte = rx.read_byte().expect("read error!"); +//! # } //! ``` -//! +//! //! [embedded-hal]: https://docs.rs/embedded-hal/latest/embedded_hal/ //! [embedded-io]: https://docs.rs/embedded-io/latest/embedded_io/ //! [embedded-hal-async]: https://docs.rs/embedded-hal-async/latest/embedded_hal_async/ @@ -466,13 +496,6 @@ where } /// Read a byte from the UART - /// - /// Example - /// - /// ```rust - /// let (_, mut rx) = serial.spilt(); - /// let byte = rx.read_byte().unwrap(); - /// ``` pub fn read_byte(&mut self) -> nb::Result { // On the ESP32-S2 we need to use PeriBus2 to read the FIFO: let offset = if cfg!(esp32s2) { 0x20C00000 } else { 0 }; diff --git a/esp-hal/src/usb_serial_jtag.rs b/esp-hal/src/usb_serial_jtag.rs index a2e509e32..9a8622c2b 100644 --- a/esp-hal/src/usb_serial_jtag.rs +++ b/esp-hal/src/usb_serial_jtag.rs @@ -41,24 +41,33 @@ //! //! ### Sending and Receiving Data //! -//! ```no_run +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! use esp_hal::usb_serial_jtag::UsbSerialJtag; +//! use core::option::Option::None; //! let mut usb_serial = UsbSerialJtag::new(peripherals.USB_DEVICE, None); //! //! // Write bytes out over the USB Serial/JTAG: -//! usb_serial.write_bytes("Hello, world!".as_bytes())?; +//! usb_serial.write_bytes("Hello, world!".as_bytes()).expect("write error!"); +//! } //! ``` -//! +//! //! ### Splitting the USB Serial/JTAG into TX and RX Components +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use esp_hal::usb_serial_jtag::UsbSerialJtag; +//! let mut usb_serial = UsbSerialJtag::new(peripherals.USB_DEVICE, None); +//! // The USB Serial/JTAG can be split into separate Transmit and Receive +//! // components: +//! let (mut tx, mut rx) = usb_serial.split(); //! -//! ```no_run -//! // The USB Serial/JTAG can be split into separate Transmit and Receive components: -//! let (mut tx, rx) = usb_serial.split(); -//! -//! // Each component can be used individually to interact with the USB Serial/JTAG: -//! tx.write_bytes(&[42u8])?; -//! let byte = rx.read_byte()?; +//! // Each component can be used individually to interact with the USB +//! // Serial/JTAG: +//! tx.write_bytes(&[42u8]).expect("write error!"); +//! let byte = rx.read_byte().expect("read error!"); +//! # } //! ``` -//! +//! //! [embedded-hal]: https://docs.rs/embedded-hal/latest/embedded_hal/ //! [embedded-io]: https://docs.rs/embedded-io/latest/embedded_io/ //! [embedded-hal-async]: https://docs.rs/embedded-hal-async/latest/embedded_hal_async/ diff --git a/examples/src/bin/embassy_i2s_read.rs b/examples/src/bin/embassy_i2s_read.rs index 00257731a..5bcf799ea 100644 --- a/examples/src/bin/embassy_i2s_read.rs +++ b/examples/src/bin/embassy_i2s_read.rs @@ -66,10 +66,8 @@ async fn main(_spawner: Spawner) { &clocks, ); - #[cfg(esp32)] - { - i2s.with_mclk(io.pins.gpio0); - } + #[cfg(not(features = "esp32"))] + let i2s = i2s.with_mclk(io.pins.gpio0); let i2s_rx = i2s .i2s_rx diff --git a/examples/src/bin/hmac.rs b/examples/src/bin/hmac.rs index 10392e5a2..3df3ef864 100644 --- a/examples/src/bin/hmac.rs +++ b/examples/src/bin/hmac.rs @@ -89,7 +89,6 @@ fn main() -> ! { let mut src = [0_u8; 1024]; rng.read(src.as_mut_slice()); - // println!("HMAC input {:02X?}", src); let mut output = [0u8; 32]; diff --git a/examples/src/bin/i2s_read.rs b/examples/src/bin/i2s_read.rs index d823e9025..746aec745 100644 --- a/examples/src/bin/i2s_read.rs +++ b/examples/src/bin/i2s_read.rs @@ -63,10 +63,8 @@ fn main() -> ! { &clocks, ); - #[cfg(esp32)] - { - i2s.with_mclk(io.pins.gpio0); - } + #[cfg(not(feature = "esp32"))] + let i2s = i2s.with_mclk(io.pins.gpio0); let mut i2s_rx = i2s .i2s_rx diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 9818878cb..720d9b37c 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -38,6 +38,8 @@ enum Cli { GenerateEfuseFields(GenerateEfuseFieldsArgs), /// Lint all packages in the workspace with clippy LintPackages(LintPackagesArgs), + /// Run doctests for specified chip and package. + RunDocTest(ExampleArgs), /// Run the given example for the specified chip. RunExample(ExampleArgs), /// Run all applicable tests or the specified test for a specified chip. @@ -155,6 +157,7 @@ fn main() -> Result<()> { Cli::FmtPackages(args) => fmt_packages(&workspace, args), Cli::GenerateEfuseFields(args) => generate_efuse_src(&workspace, args), Cli::LintPackages(args) => lint_packages(&workspace, args), + Cli::RunDocTest(args) => run_doctests(&workspace, args), Cli::RunElfs(args) => run_elfs(args), Cli::RunExample(args) => examples(&workspace, args, CargoAction::Run), Cli::RunTests(args) => tests(&workspace, args, CargoAction::Run), @@ -607,6 +610,33 @@ fn run_elfs(args: RunElfArgs) -> Result<()> { Ok(()) } +fn run_doctests(workspace: &Path, args: ExampleArgs) -> Result<()> { + let package_name = args.package.to_string(); + let package_path = xtask::windows_safe_path(&workspace.join(&package_name)); + + // Determine the appropriate build target for the given package and chip: + let target = target_triple(&args.package, &args.chip)?; + let features = vec![args.chip.to_string()]; + + // Build up an array of command-line arguments to pass to `cargo`: + let builder = CargoArgsBuilder::default() + .subcommand("test") + .arg("--doc") + .arg("-Zdoctest-xcompile") + .arg("-Zbuild-std=core,panic_abort") + .target(target) + .features(&features) + .arg("--release"); + + let args = builder.build(); + log::debug!("{args:#?}"); + + // Execute `cargo doc` from the package root: + xtask::cargo::run(&args, &package_path)?; + + Ok(()) +} + // ---------------------------------------------------------------------------- // Helper Functions