From 3e399a9690b1623ce43ea94bf626bda573fac38b Mon Sep 17 00:00:00 2001 From: Karun Date: Tue, 14 May 2024 12:45:07 -0400 Subject: update to remove dma generics --- embassy-stm32/src/ospi/mod.rs | 817 ++++++++++++++++++++++-------------------- 1 file changed, 437 insertions(+), 380 deletions(-) diff --git a/embassy-stm32/src/ospi/mod.rs b/embassy-stm32/src/ospi/mod.rs index c25ac4d24..536da4ca0 100644 --- a/embassy-stm32/src/ospi/mod.rs +++ b/embassy-stm32/src/ospi/mod.rs @@ -5,13 +5,16 @@ pub mod enums; +use core::marker::PhantomData; + use embassy_embedded_hal::{GetConfig, SetConfig}; use embassy_hal_internal::{into_ref, PeripheralRef}; pub use enums::*; use stm32_metapac::octospi::vals::{PhaseMode, SizeInBits}; -use crate::dma::{word, Transfer}; -use crate::gpio::{AFType, AnyPin, Pull, SealedPin as _}; +use crate::dma::{word, ChannelAndRequest}; +use crate::gpio::{AFType, AnyPin, Pull, SealedPin as _, Speed}; +use crate::mode::{Async, Blocking, Mode as PeriMode}; use crate::pac::octospi::{vals, Octospi as Regs}; use crate::rcc::RccPeripheral; use crate::{peripherals, Peripheral}; @@ -154,7 +157,7 @@ pub enum OspiError { } /// OSPI driver. -pub struct Ospi<'d, T: Instance, Dma> { +pub struct Ospi<'d, T: Instance, M: PeriMode> { _peri: PeripheralRef<'d, T>, sck: Option>, d0: Option>, @@ -167,259 +170,13 @@ pub struct Ospi<'d, T: Instance, Dma> { d7: Option>, nss: Option>, dqs: Option>, - dma: PeripheralRef<'d, Dma>, + dma: Option>, + _phantom: PhantomData, config: Config, width: OspiWidth, } -impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> { - /// Create new OSPI driver for a single spi external chip - pub fn new_singlespi( - peri: impl Peripheral

+ 'd, - sck: impl Peripheral

> + 'd, - d0: impl Peripheral

> + 'd, - d1: impl Peripheral

> + 'd, - nss: impl Peripheral

> + 'd, - dma: impl Peripheral

+ 'd, - config: Config, - ) -> Self { - into_ref!(peri, sck, d0, d1, nss); - - sck.set_as_af_pull(sck.af_num(), AFType::OutputPushPull, Pull::None); - sck.set_speed(crate::gpio::Speed::VeryHigh); - nss.set_as_af_pull(nss.af_num(), AFType::OutputPushPull, Pull::Up); - nss.set_speed(crate::gpio::Speed::VeryHigh); - d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::None); - d0.set_speed(crate::gpio::Speed::VeryHigh); - d1.set_as_af_pull(d1.af_num(), AFType::Input, Pull::None); - d1.set_speed(crate::gpio::Speed::VeryHigh); - - Self::new_inner( - peri, - Some(d0.map_into()), - Some(d1.map_into()), - None, - None, - None, - None, - None, - None, - Some(sck.map_into()), - Some(nss.map_into()), - None, - dma, - config, - OspiWidth::SING, - false, - ) - } - - /// Create new OSPI driver for a dualspi external chip - pub fn new_dualspi( - peri: impl Peripheral

+ 'd, - sck: impl Peripheral

> + 'd, - d0: impl Peripheral

> + 'd, - d1: impl Peripheral

> + 'd, - nss: impl Peripheral

> + 'd, - dma: impl Peripheral

+ 'd, - config: Config, - ) -> Self { - into_ref!(peri, sck, d0, d1, nss); - - sck.set_as_af_pull(sck.af_num(), AFType::OutputPushPull, Pull::None); - sck.set_speed(crate::gpio::Speed::VeryHigh); - nss.set_as_af_pull(nss.af_num(), AFType::OutputPushPull, Pull::Up); - nss.set_speed(crate::gpio::Speed::VeryHigh); - d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::None); - d0.set_speed(crate::gpio::Speed::VeryHigh); - d1.set_as_af_pull(d1.af_num(), AFType::OutputPushPull, Pull::None); - d1.set_speed(crate::gpio::Speed::VeryHigh); - - Self::new_inner( - peri, - Some(d0.map_into()), - Some(d1.map_into()), - None, - None, - None, - None, - None, - None, - Some(sck.map_into()), - Some(nss.map_into()), - None, - dma, - config, - OspiWidth::DUAL, - false, - ) - } - - /// Create new OSPI driver for a quadspi external chip - pub fn new_quadspi( - peri: impl Peripheral

+ 'd, - sck: impl Peripheral

> + 'd, - d0: impl Peripheral

> + 'd, - d1: impl Peripheral

> + 'd, - d2: impl Peripheral

> + 'd, - d3: impl Peripheral

> + 'd, - nss: impl Peripheral

> + 'd, - dma: impl Peripheral

+ 'd, - config: Config, - ) -> Self { - into_ref!(peri, sck, d0, d1, d2, d3, nss); - - sck.set_as_af_pull(sck.af_num(), AFType::OutputPushPull, Pull::None); - sck.set_speed(crate::gpio::Speed::VeryHigh); - nss.set_as_af_pull(nss.af_num(), AFType::OutputPushPull, Pull::Up); - nss.set_speed(crate::gpio::Speed::VeryHigh); - d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::None); - d0.set_speed(crate::gpio::Speed::VeryHigh); - d1.set_as_af_pull(d1.af_num(), AFType::OutputPushPull, Pull::None); - d1.set_speed(crate::gpio::Speed::VeryHigh); - d2.set_as_af_pull(d2.af_num(), AFType::OutputPushPull, Pull::None); - d2.set_speed(crate::gpio::Speed::VeryHigh); - d3.set_as_af_pull(d3.af_num(), AFType::OutputPushPull, Pull::None); - d3.set_speed(crate::gpio::Speed::VeryHigh); - - Self::new_inner( - peri, - Some(d0.map_into()), - Some(d1.map_into()), - Some(d2.map_into()), - Some(d3.map_into()), - None, - None, - None, - None, - Some(sck.map_into()), - Some(nss.map_into()), - None, - dma, - config, - OspiWidth::QUAD, - false, - ) - } - - /// Create new OSPI driver for two quadspi external chips - pub fn new_dualquadspi( - peri: impl Peripheral

+ 'd, - sck: impl Peripheral

> + 'd, - d0: impl Peripheral

> + 'd, - d1: impl Peripheral

> + 'd, - d2: impl Peripheral

> + 'd, - d3: impl Peripheral

> + 'd, - d4: impl Peripheral

> + 'd, - d5: impl Peripheral

> + 'd, - d6: impl Peripheral

> + 'd, - d7: impl Peripheral

> + 'd, - nss: impl Peripheral

> + 'd, - dma: impl Peripheral

+ 'd, - config: Config, - ) -> Self { - into_ref!(peri, sck, d0, d1, d2, d3, d4, d5, d6, d7, nss); - - sck.set_as_af_pull(sck.af_num(), AFType::OutputPushPull, Pull::None); - sck.set_speed(crate::gpio::Speed::VeryHigh); - nss.set_as_af_pull(nss.af_num(), AFType::OutputPushPull, Pull::Up); - nss.set_speed(crate::gpio::Speed::VeryHigh); - d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::None); - d0.set_speed(crate::gpio::Speed::VeryHigh); - d1.set_as_af_pull(d1.af_num(), AFType::OutputPushPull, Pull::None); - d1.set_speed(crate::gpio::Speed::VeryHigh); - d2.set_as_af_pull(d2.af_num(), AFType::OutputPushPull, Pull::None); - d2.set_speed(crate::gpio::Speed::VeryHigh); - d3.set_as_af_pull(d3.af_num(), AFType::OutputPushPull, Pull::None); - d3.set_speed(crate::gpio::Speed::VeryHigh); - d4.set_as_af_pull(d4.af_num(), AFType::OutputPushPull, Pull::None); - d4.set_speed(crate::gpio::Speed::VeryHigh); - d5.set_as_af_pull(d5.af_num(), AFType::OutputPushPull, Pull::None); - d5.set_speed(crate::gpio::Speed::VeryHigh); - d6.set_as_af_pull(d6.af_num(), AFType::OutputPushPull, Pull::None); - d6.set_speed(crate::gpio::Speed::VeryHigh); - d7.set_as_af_pull(d7.af_num(), AFType::OutputPushPull, Pull::None); - d7.set_speed(crate::gpio::Speed::VeryHigh); - - Self::new_inner( - peri, - Some(d0.map_into()), - Some(d1.map_into()), - Some(d2.map_into()), - Some(d3.map_into()), - Some(d4.map_into()), - Some(d5.map_into()), - Some(d6.map_into()), - Some(d7.map_into()), - Some(sck.map_into()), - Some(nss.map_into()), - None, - dma, - config, - OspiWidth::QUAD, - true, - ) - } - - /// Create new OSPI driver for octospi external chips - pub fn new_octospi( - peri: impl Peripheral

+ 'd, - sck: impl Peripheral

> + 'd, - d0: impl Peripheral

> + 'd, - d1: impl Peripheral

> + 'd, - d2: impl Peripheral

> + 'd, - d3: impl Peripheral

> + 'd, - d4: impl Peripheral

> + 'd, - d5: impl Peripheral

> + 'd, - d6: impl Peripheral

> + 'd, - d7: impl Peripheral

> + 'd, - nss: impl Peripheral

> + 'd, - dma: impl Peripheral

+ 'd, - config: Config, - ) -> Self { - into_ref!(peri, sck, d0, d1, d2, d3, d4, d5, d6, d7, nss); - - sck.set_as_af_pull(sck.af_num(), AFType::OutputPushPull, Pull::None); - sck.set_speed(crate::gpio::Speed::VeryHigh); - nss.set_as_af_pull(nss.af_num(), AFType::OutputPushPull, Pull::Up); - nss.set_speed(crate::gpio::Speed::VeryHigh); - d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::None); - d0.set_speed(crate::gpio::Speed::VeryHigh); - d1.set_as_af_pull(d1.af_num(), AFType::OutputPushPull, Pull::None); - d1.set_speed(crate::gpio::Speed::VeryHigh); - d2.set_as_af_pull(d2.af_num(), AFType::OutputPushPull, Pull::None); - d2.set_speed(crate::gpio::Speed::VeryHigh); - d3.set_as_af_pull(d3.af_num(), AFType::OutputPushPull, Pull::None); - d3.set_speed(crate::gpio::Speed::VeryHigh); - d4.set_as_af_pull(d4.af_num(), AFType::OutputPushPull, Pull::None); - d4.set_speed(crate::gpio::Speed::VeryHigh); - d5.set_as_af_pull(d5.af_num(), AFType::OutputPushPull, Pull::None); - d5.set_speed(crate::gpio::Speed::VeryHigh); - d6.set_as_af_pull(d6.af_num(), AFType::OutputPushPull, Pull::None); - d6.set_speed(crate::gpio::Speed::VeryHigh); - d7.set_as_af_pull(d7.af_num(), AFType::OutputPushPull, Pull::None); - d7.set_speed(crate::gpio::Speed::VeryHigh); - - Self::new_inner( - peri, - Some(d0.map_into()), - Some(d1.map_into()), - Some(d2.map_into()), - Some(d3.map_into()), - Some(d4.map_into()), - Some(d5.map_into()), - Some(d6.map_into()), - Some(d7.map_into()), - Some(sck.map_into()), - Some(nss.map_into()), - None, - dma, - config, - OspiWidth::OCTO, - false, - ) - } - +impl<'d, T: Instance, M: PeriMode> Ospi<'d, T, M> { fn new_inner( peri: impl Peripheral

+ 'd, d0: Option>, @@ -433,12 +190,12 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> { sck: Option>, nss: Option>, dqs: Option>, - dma: impl Peripheral

+ 'd, + dma: Option>, config: Config, width: OspiWidth, dual_quad: bool, ) -> Self { - into_ref!(peri, dma); + into_ref!(peri); // System configuration T::enable_and_reset(); @@ -519,6 +276,7 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> { nss, dqs, dma, + _phantom: PhantomData, config, width, } @@ -702,11 +460,410 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> { Ok(()) } + /// Set new bus configuration + pub fn set_config(&mut self, config: &Config) { + // Wait for busy flag to clear + while T::REGS.sr().read().busy() {} + + // Disable DMA channel while configuring the peripheral + T::REGS.cr().modify(|w| { + w.set_dmaen(false); + }); + + // Device configuration + T::REGS.dcr1().modify(|w| { + w.set_devsize(config.device_size.into()); + w.set_mtyp(vals::MemType::from_bits(config.memory_type.into())); + w.set_csht(config.chip_select_high_time.into()); + w.set_dlybyp(config.delay_block_bypass); + w.set_frck(false); + w.set_ckmode(config.clock_mode); + }); + + T::REGS.dcr2().modify(|w| { + w.set_wrapsize(config.wrap_size.into()); + }); + + T::REGS.dcr3().modify(|w| { + w.set_csbound(config.chip_select_boundary); + #[cfg(octospi_v1)] + { + w.set_maxtran(config.max_transfer); + } + }); + + T::REGS.dcr4().modify(|w| { + w.set_refresh(config.refresh); + }); + + T::REGS.cr().modify(|w| { + w.set_fthres(vals::Threshold(config.fifo_threshold.into())); + }); + + // Wait for busy flag to clear + while T::REGS.sr().read().busy() {} + + T::REGS.dcr2().modify(|w| { + w.set_prescaler(config.clock_prescaler); + }); + + T::REGS.tcr().modify(|w| { + w.set_sshift(match config.sample_shifting { + true => vals::SampleShift::HALFCYCLE, + false => vals::SampleShift::NONE, + }); + w.set_dhqc(config.delay_hold_quarter_cycle); + }); + + // Enable peripheral + T::REGS.cr().modify(|w| { + w.set_en(true); + }); + + // Free running clock needs to be set after peripheral enable + if config.free_running_clock { + T::REGS.dcr1().modify(|w| { + w.set_frck(config.free_running_clock); + }); + } + + self.config = *config; + } + + /// Get current configuration + pub fn get_config(&self) -> Config { + self.config + } +} + +impl<'d, T: Instance> Ospi<'d, T, Blocking> { + /// Create new blocking OSPI driver for a single spi external chip + pub fn new_blocking_singlespi( + peri: impl Peripheral

+ 'd, + sck: impl Peripheral

> + 'd, + d0: impl Peripheral

> + 'd, + d1: impl Peripheral

> + 'd, + nss: impl Peripheral

> + 'd, + config: Config, + ) -> Self { + Self::new_inner( + peri, + new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d1, AFType::Input, Speed::VeryHigh), + None, + None, + None, + None, + None, + None, + new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up), + None, + None, + config, + OspiWidth::SING, + false, + ) + } + + /// Create new blocking OSPI driver for a dualspi external chip + pub fn new_blocking_dualspi( + peri: impl Peripheral

+ 'd, + sck: impl Peripheral

> + 'd, + d0: impl Peripheral

> + 'd, + d1: impl Peripheral

> + 'd, + nss: impl Peripheral

> + 'd, + config: Config, + ) -> Self { + Self::new_inner( + peri, + new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh), + None, + None, + None, + None, + None, + None, + new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up), + None, + None, + config, + OspiWidth::DUAL, + false, + ) + } + + /// Create new blocking OSPI driver for a quadspi external chip + pub fn new_blocking_quadspi( + peri: impl Peripheral

+ 'd, + sck: impl Peripheral

> + 'd, + d0: impl Peripheral

> + 'd, + d1: impl Peripheral

> + 'd, + d2: impl Peripheral

> + 'd, + d3: impl Peripheral

> + 'd, + nss: impl Peripheral

> + 'd, + config: Config, + ) -> Self { + Self::new_inner( + peri, + new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d2, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d3, AFType::OutputPushPull, Speed::VeryHigh), + None, + None, + None, + None, + new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up), + None, + None, + config, + OspiWidth::QUAD, + false, + ) + } + + /// Create new blocking OSPI driver for two quadspi external chips + pub fn new_blocking_dualquadspi( + peri: impl Peripheral

+ 'd, + sck: impl Peripheral

> + 'd, + d0: impl Peripheral

> + 'd, + d1: impl Peripheral

> + 'd, + d2: impl Peripheral

> + 'd, + d3: impl Peripheral

> + 'd, + d4: impl Peripheral

> + 'd, + d5: impl Peripheral

> + 'd, + d6: impl Peripheral

> + 'd, + d7: impl Peripheral

> + 'd, + nss: impl Peripheral

> + 'd, + config: Config, + ) -> Self { + Self::new_inner( + peri, + new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d2, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d3, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d4, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d5, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d6, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d7, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up), + None, + None, + config, + OspiWidth::QUAD, + true, + ) + } + + /// Create new blocking OSPI driver for octospi external chips + pub fn new_blocking_octospi( + peri: impl Peripheral

+ 'd, + sck: impl Peripheral

> + 'd, + d0: impl Peripheral

> + 'd, + d1: impl Peripheral

> + 'd, + d2: impl Peripheral

> + 'd, + d3: impl Peripheral

> + 'd, + d4: impl Peripheral

> + 'd, + d5: impl Peripheral

> + 'd, + d6: impl Peripheral

> + 'd, + d7: impl Peripheral

> + 'd, + nss: impl Peripheral

> + 'd, + config: Config, + ) -> Self { + Self::new_inner( + peri, + new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d2, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d3, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d4, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d5, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d6, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d7, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up), + None, + None, + config, + OspiWidth::OCTO, + false, + ) + } +} + +impl<'d, T: Instance> Ospi<'d, T, Async> { + /// Create new blocking OSPI driver for a single spi external chip + pub fn new_singlespi( + peri: impl Peripheral

+ 'd, + sck: impl Peripheral

> + 'd, + d0: impl Peripheral

> + 'd, + d1: impl Peripheral

> + 'd, + nss: impl Peripheral

> + 'd, + dma: impl Peripheral

> + 'd, + config: Config, + ) -> Self { + Self::new_inner( + peri, + new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d1, AFType::Input, Speed::VeryHigh), + None, + None, + None, + None, + None, + None, + new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up), + None, + new_dma!(dma), + config, + OspiWidth::SING, + false, + ) + } + + /// Create new blocking OSPI driver for a dualspi external chip + pub fn new_dualspi( + peri: impl Peripheral

+ 'd, + sck: impl Peripheral

> + 'd, + d0: impl Peripheral

> + 'd, + d1: impl Peripheral

> + 'd, + nss: impl Peripheral

> + 'd, + dma: impl Peripheral

> + 'd, + config: Config, + ) -> Self { + Self::new_inner( + peri, + new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh), + None, + None, + None, + None, + None, + None, + new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up), + None, + new_dma!(dma), + config, + OspiWidth::DUAL, + false, + ) + } + + /// Create new blocking OSPI driver for a quadspi external chip + pub fn new_quadspi( + peri: impl Peripheral

+ 'd, + sck: impl Peripheral

> + 'd, + d0: impl Peripheral

> + 'd, + d1: impl Peripheral

> + 'd, + d2: impl Peripheral

> + 'd, + d3: impl Peripheral

> + 'd, + nss: impl Peripheral

> + 'd, + dma: impl Peripheral

> + 'd, + config: Config, + ) -> Self { + Self::new_inner( + peri, + new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d2, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d3, AFType::OutputPushPull, Speed::VeryHigh), + None, + None, + None, + None, + new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up), + None, + new_dma!(dma), + config, + OspiWidth::QUAD, + false, + ) + } + + /// Create new blocking OSPI driver for two quadspi external chips + pub fn new_dualquadspi( + peri: impl Peripheral

+ 'd, + sck: impl Peripheral

> + 'd, + d0: impl Peripheral

> + 'd, + d1: impl Peripheral

> + 'd, + d2: impl Peripheral

> + 'd, + d3: impl Peripheral

> + 'd, + d4: impl Peripheral

> + 'd, + d5: impl Peripheral

> + 'd, + d6: impl Peripheral

> + 'd, + d7: impl Peripheral

> + 'd, + nss: impl Peripheral

> + 'd, + dma: impl Peripheral

> + 'd, + config: Config, + ) -> Self { + Self::new_inner( + peri, + new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d2, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d3, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d4, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d5, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d6, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d7, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up), + None, + new_dma!(dma), + config, + OspiWidth::QUAD, + true, + ) + } + + /// Create new blocking OSPI driver for octospi external chips + pub fn new_octospi( + peri: impl Peripheral

+ 'd, + sck: impl Peripheral

> + 'd, + d0: impl Peripheral

> + 'd, + d1: impl Peripheral

> + 'd, + d2: impl Peripheral

> + 'd, + d3: impl Peripheral

> + 'd, + d4: impl Peripheral

> + 'd, + d5: impl Peripheral

> + 'd, + d6: impl Peripheral

> + 'd, + d7: impl Peripheral

> + 'd, + nss: impl Peripheral

> + 'd, + dma: impl Peripheral

> + 'd, + config: Config, + ) -> Self { + Self::new_inner( + peri, + new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d2, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d3, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d4, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d5, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d6, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(d7, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh), + new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up), + None, + new_dma!(dma), + config, + OspiWidth::OCTO, + false, + ) + } + /// Blocking read with DMA transfer - pub fn blocking_read_dma(&mut self, buf: &mut [W], transaction: TransferConfig) -> Result<(), OspiError> - where - Dma: OctoDma, - { + pub fn blocking_read_dma(&mut self, buf: &mut [W], transaction: TransferConfig) -> Result<(), OspiError> { if buf.is_empty() { return Err(OspiError::EmptyBuffer); } @@ -727,15 +884,11 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> { T::REGS.ar().write(|v| v.set_address(current_address)); } - let request = self.dma.request(); let transfer = unsafe { - Transfer::new_read( - &mut self.dma, - request, - T::REGS.dr().as_ptr() as *mut W, - buf, - Default::default(), - ) + self.dma + .as_mut() + .unwrap() + .read(T::REGS.dr().as_ptr() as *mut W, buf, Default::default()) }; T::REGS.cr().modify(|w| w.set_dmaen(true)); @@ -748,10 +901,7 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> { } /// Blocking write with DMA transfer - pub fn blocking_write_dma(&mut self, buf: &[W], transaction: TransferConfig) -> Result<(), OspiError> - where - Dma: OctoDma, - { + pub fn blocking_write_dma(&mut self, buf: &[W], transaction: TransferConfig) -> Result<(), OspiError> { if buf.is_empty() { return Err(OspiError::EmptyBuffer); } @@ -764,15 +914,11 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> { .cr() .modify(|v| v.set_fmode(vals::FunctionalMode::INDIRECTWRITE)); - let request = self.dma.request(); let transfer = unsafe { - Transfer::new_write( - &mut self.dma, - request, - buf, - T::REGS.dr().as_ptr() as *mut W, - Default::default(), - ) + self.dma + .as_mut() + .unwrap() + .write(buf, T::REGS.dr().as_ptr() as *mut W, Default::default()) }; T::REGS.cr().modify(|w| w.set_dmaen(true)); @@ -785,10 +931,7 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> { } /// Asynchronous read from external device - pub async fn read(&mut self, buf: &mut [W], transaction: TransferConfig) -> Result<(), OspiError> - where - Dma: OctoDma, - { + pub async fn read(&mut self, buf: &mut [W], transaction: TransferConfig) -> Result<(), OspiError> { if buf.is_empty() { return Err(OspiError::EmptyBuffer); } @@ -809,15 +952,11 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> { T::REGS.ar().write(|v| v.set_address(current_address)); } - let request = self.dma.request(); let transfer = unsafe { - Transfer::new_read( - &mut self.dma, - request, - T::REGS.dr().as_ptr() as *mut W, - buf, - Default::default(), - ) + self.dma + .as_mut() + .unwrap() + .read(T::REGS.dr().as_ptr() as *mut W, buf, Default::default()) }; T::REGS.cr().modify(|w| w.set_dmaen(true)); @@ -830,10 +969,7 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> { } /// Asynchronous write to external device - pub async fn write(&mut self, buf: &[W], transaction: TransferConfig) -> Result<(), OspiError> - where - Dma: OctoDma, - { + pub async fn write(&mut self, buf: &[W], transaction: TransferConfig) -> Result<(), OspiError> { if buf.is_empty() { return Err(OspiError::EmptyBuffer); } @@ -846,15 +982,11 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> { .cr() .modify(|v| v.set_fmode(vals::FunctionalMode::INDIRECTWRITE)); - let request = self.dma.request(); let transfer = unsafe { - Transfer::new_write( - &mut self.dma, - request, - buf, - T::REGS.dr().as_ptr() as *mut W, - Default::default(), - ) + self.dma + .as_mut() + .unwrap() + .write(buf, T::REGS.dr().as_ptr() as *mut W, Default::default()) }; T::REGS.cr().modify(|w| w.set_dmaen(true)); @@ -865,84 +997,9 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> { Ok(()) } - - /// Set new bus configuration - pub fn set_config(&mut self, config: &Config) { - // Wait for busy flag to clear - while T::REGS.sr().read().busy() {} - - // Disable DMA channel while configuring the peripheral - T::REGS.cr().modify(|w| { - w.set_dmaen(false); - }); - - // Device configuration - T::REGS.dcr1().modify(|w| { - w.set_devsize(config.device_size.into()); - w.set_mtyp(vals::MemType::from_bits(config.memory_type.into())); - w.set_csht(config.chip_select_high_time.into()); - w.set_dlybyp(config.delay_block_bypass); - w.set_frck(false); - w.set_ckmode(config.clock_mode); - }); - - T::REGS.dcr2().modify(|w| { - w.set_wrapsize(config.wrap_size.into()); - }); - - T::REGS.dcr3().modify(|w| { - w.set_csbound(config.chip_select_boundary); - #[cfg(octospi_v1)] - { - w.set_maxtran(config.max_transfer); - } - }); - - T::REGS.dcr4().modify(|w| { - w.set_refresh(config.refresh); - }); - - T::REGS.cr().modify(|w| { - w.set_fthres(vals::Threshold(config.fifo_threshold.into())); - }); - - // Wait for busy flag to clear - while T::REGS.sr().read().busy() {} - - T::REGS.dcr2().modify(|w| { - w.set_prescaler(config.clock_prescaler); - }); - - T::REGS.tcr().modify(|w| { - w.set_sshift(match config.sample_shifting { - true => vals::SampleShift::HALFCYCLE, - false => vals::SampleShift::NONE, - }); - w.set_dhqc(config.delay_hold_quarter_cycle); - }); - - // Enable peripheral - T::REGS.cr().modify(|w| { - w.set_en(true); - }); - - // Free running clock needs to be set after peripheral enable - if config.free_running_clock { - T::REGS.dcr1().modify(|w| { - w.set_frck(config.free_running_clock); - }); - } - - self.config = *config; - } - - /// Get current configuration - pub fn get_config(&self) -> Config { - self.config - } } -impl<'d, T: Instance, Dma> Drop for Ospi<'d, T, Dma> { +impl<'d, T: Instance, M: PeriMode> Drop for Ospi<'d, T, M> { fn drop(&mut self) { self.sck.as_ref().map(|x| x.set_as_disconnected()); self.d0.as_ref().map(|x| x.set_as_disconnected()); @@ -1005,7 +1062,7 @@ foreach_peripheral!( }; ); -impl<'d, T: Instance, Dma> SetConfig for Ospi<'d, T, Dma> { +impl<'d, T: Instance, M: PeriMode> SetConfig for Ospi<'d, T, M> { type Config = Config; type ConfigError = (); fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> { @@ -1014,7 +1071,7 @@ impl<'d, T: Instance, Dma> SetConfig for Ospi<'d, T, Dma> { } } -impl<'d, T: Instance, Dma> GetConfig for Ospi<'d, T, Dma> { +impl<'d, T: Instance, M: PeriMode> GetConfig for Ospi<'d, T, M> { type Config = Config; fn get_config(&self) -> Self::Config { self.get_config() -- cgit