diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index a465fccd8..e18b16935 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -57,6 +57,8 @@ pub mod ipcc; pub mod low_power; #[cfg(opamp)] pub mod opamp; +#[cfg(octospi)] +pub mod ospi; #[cfg(quadspi)] pub mod qspi; #[cfg(rng)] diff --git a/embassy-stm32/src/ospi/mod.rs b/embassy-stm32/src/ospi/mod.rs new file mode 100644 index 000000000..44824e42a --- /dev/null +++ b/embassy-stm32/src/ospi/mod.rs @@ -0,0 +1,178 @@ +//! OCTOSPI Serial Peripheral Interface +//! + +#![macro_use] + +use core::ptr; + +use embassy_embedded_hal::SetConfig; +use embassy_futures::join::join; +use embassy_hal_internal::{into_ref, PeripheralRef}; +pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; + +use crate::dma::{slice_ptr_parts, word, Transfer}; +use crate::gpio::sealed::{AFType, Pin as _}; +use crate::gpio::{AnyPin, Pull}; +use crate::pac::octospi::{regs, vals, Octospi as Regs}; +use crate::rcc::RccPeripheral; +use crate::time::Hertz; +use crate::{peripherals, Peripheral}; + +pub struct Config; + +pub struct Ospi<'d, T: Instance, Dma> { + _peri: PeripheralRef<'d, T>, + sck: Option>, + d0: Option>, + d1: Option>, + d2: Option>, + d3: Option>, + d4: Option>, + d5: Option>, + d6: Option>, + d7: Option>, + nss: Option>, + dqs: Option>, + dma: PeripheralRef<'d, Dma>, + config: Config, +} + +impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> { + /// 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, + ) + } + + fn new_inner( + peri: impl Peripheral

+ 'd, + d0: Option>, + d1: Option>, + d2: Option>, + d3: Option>, + d4: Option>, + d5: Option>, + d6: Option>, + d7: Option>, + sck: Option>, + nss: Option>, + dqs: Option>, + dma: impl Peripheral

+ 'd, + config: Config, + ) -> Self { + into_ref!(peri, dma); + + T::enable_and_reset(); + T::REGS.sr().read().busy(); + + T::REGS.cr().modify(|w| { + w.set_en(true); + }); + + #[cfg(octospi_v1)] + { + T::REGS.ccr().modify(|w| { + w.set_imode(vals::PhaseMode::TWOLINES); + w.set_admode(vals::PhaseMode::TWOLINES); + w.set_abmode(vals::PhaseMode::TWOLINES); + w.set_dmode(vals::PhaseMode::TWOLINES); + }); + T::REGS.wccr().modify(|w| { + w.set_imode(vals::PhaseMode::TWOLINES); + w.set_admode(vals::PhaseMode::TWOLINES); + w.set_abmode(vals::PhaseMode::TWOLINES); + w.set_dmode(vals::PhaseMode::TWOLINES); + }); + } + + // + + // while T::REGS::sr().read().busy() {} + + Self { + _peri: peri, + sck, + d0, + d1, + d2, + d3, + d4, + d5, + d6, + d7, + nss, + dqs, + dma, + config, + } + } +} + +pub(crate) mod sealed { + use super::*; + + pub trait Instance { + const REGS: Regs; + } +} + +/// OSPI instance trait. +pub trait Instance: Peripheral

+ sealed::Instance + RccPeripheral {} + +pin_trait!(SckPin, Instance); +pin_trait!(NckPin, Instance); +pin_trait!(D0Pin, Instance); +pin_trait!(D1Pin, Instance); +pin_trait!(D2Pin, Instance); +pin_trait!(D3Pin, Instance); +pin_trait!(D4Pin, Instance); +pin_trait!(D5Pin, Instance); +pin_trait!(D6Pin, Instance); +pin_trait!(D7Pin, Instance); +pin_trait!(DQSPin, Instance); +pin_trait!(NSSPin, Instance); + +dma_trait!(OctoDma, Instance); + +foreach_peripheral!( + (octospi, $inst:ident) => { + impl sealed::Instance for peripherals::$inst { + const REGS: Regs = crate::pac::$inst; + } + + impl Instance for peripherals::$inst {} + }; +);