diff --git a/CHANGELOG.md b/CHANGELOG.md index 2bb28327361..b8251e576ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Add `WithDmaSpi3` to prelude for ESP32S3 (#623) - Add bare-bones PSRAM support for ESP32 (#506) - Add initial support for the ESP32-H2 (#513, #526, #527, #528, #530, #538, #544, #548, #551, #556, #560, #566, #549, #564, #569, #576, #577, #589, #591, #597) - Add bare-bones PSRAM support for ESP32-S3 (#517) diff --git a/esp-hal-common/src/prelude.rs b/esp-hal-common/src/prelude.rs index 1d95106dee2..8a156133e75 100644 --- a/esp-hal-common/src/prelude.rs +++ b/esp-hal-common/src/prelude.rs @@ -70,7 +70,7 @@ pub use crate::pulse_control::{ }; #[cfg(radio)] pub use crate::radio::RadioExt as _esp_hal_RadioExt; -#[cfg(any(esp32, esp32s2))] +#[cfg(any(esp32, esp32s2, esp32s3))] pub use crate::spi::dma::WithDmaSpi3 as _esp_hal_spi_dma_WithDmaSpi3; #[cfg(any(spi0, spi1, spi2, spi3))] pub use crate::spi::{ diff --git a/esp32s3-hal/examples/spi_loopback_dma_spi3.rs b/esp32s3-hal/examples/spi_loopback_dma_spi3.rs new file mode 100644 index 00000000000..f998bcd3dd6 --- /dev/null +++ b/esp32s3-hal/examples/spi_loopback_dma_spi3.rs @@ -0,0 +1,140 @@ +//! SPI loopback test using DMA. +//! +//! This example is a copy of `spi_loopback_dma.rs` with the only difference +//! that it uses SPI3 instead of SPI2. +//! +//! Folowing pins are used: +//! SCLK GPIO6 +//! MISO GPIO2 +//! MOSI GPIO7 +//! CS GPIO10 +//! +//! Depending on your target and the board you are using you have to change the +//! pins. +//! +//! This example transfers data via SPI. +//! Connect MISO and MOSI pins to see the outgoing data is read as incoming +//! data. + +#![no_std] +#![no_main] + +use esp32s3_hal::{ + clock::ClockControl, + dma::DmaPriority, + gdma::Gdma, + gpio::IO, + peripherals::Peripherals, + prelude::*, + spi::{Spi, SpiMode}, + timer::TimerGroup, + Delay, + Rtc, +}; +use esp_backtrace as _; +use esp_println::println; + +#[entry] +fn main() -> ! { + let peripherals = Peripherals::take(); + let mut system = peripherals.SYSTEM.split(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + // Disable the watchdog timers. For the ESP32-S3, this includes the Super WDT, + // the RTC WDT, and the TIMG WDTs. + let mut rtc = Rtc::new(peripherals.RTC_CNTL); + let timer_group0 = TimerGroup::new( + peripherals.TIMG0, + &clocks, + &mut system.peripheral_clock_control, + ); + let mut wdt0 = timer_group0.wdt; + let timer_group1 = TimerGroup::new( + peripherals.TIMG1, + &clocks, + &mut system.peripheral_clock_control, + ); + let mut wdt1 = timer_group1.wdt; + + rtc.swd.disable(); + rtc.rwdt.disable(); + wdt0.disable(); + wdt1.disable(); + + let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); + let sclk = io.pins.gpio6; + let miso = io.pins.gpio2; + let mosi = io.pins.gpio7; + let cs = io.pins.gpio10; + + let dma = Gdma::new(peripherals.DMA, &mut system.peripheral_clock_control); + let dma_channel = dma.channel0; + + let mut descriptors = [0u32; 8 * 3]; + let mut rx_descriptors = [0u32; 8 * 3]; + + let mut spi = Spi::new( + peripherals.SPI3, + sclk, + mosi, + miso, + cs, + 100u32.kHz(), + SpiMode::Mode0, + &mut system.peripheral_clock_control, + &clocks, + ) + .with_dma(dma_channel.configure( + false, + &mut descriptors, + &mut rx_descriptors, + DmaPriority::Priority0, + )); + + let mut delay = Delay::new(&clocks); + + // DMA buffer require a static life-time + let mut send = buffer1(); + let mut receive = buffer2(); + let mut i = 0; + + for (i, v) in send.iter_mut().enumerate() { + *v = (i % 255) as u8; + } + + loop { + send[0] = i; + send[send.len() - 1] = i; + i = i.wrapping_add(1); + + let transfer = spi.dma_transfer(send, receive).unwrap(); + // here we could do something else while DMA transfer is in progress + let mut i = 0; + // Check is_done until the transfer is almost done (32000 bytes at 100kHz is + // 2.56 seconds), then move to wait(). + while !transfer.is_done() && i < 10 { + delay.delay_ms(250u32); + i += 1; + } + // the buffers and spi is moved into the transfer and we can get it back via + // `wait` + (receive, send, spi) = transfer.wait(); + println!( + "{:x?} .. {:x?}", + &receive[..10], + &receive[receive.len() - 10..] + ); + + delay.delay_ms(250u32); + } +} + +fn buffer1() -> &'static mut [u8; 32000] { + static mut BUFFER: [u8; 32000] = [0u8; 32000]; + unsafe { &mut BUFFER } +} + +fn buffer2() -> &'static mut [u8; 32000] { + static mut BUFFER: [u8; 32000] = [0u8; 32000]; + unsafe { &mut BUFFER } +}