diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index 76db0a76..ed5fa84d 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -719,12 +719,17 @@ fn main() { (("sdmmc", "D6"), quote!(crate::sdmmc::D6Pin)), (("sdmmc", "D6"), quote!(crate::sdmmc::D7Pin)), (("sdmmc", "D8"), quote!(crate::sdmmc::D8Pin)), - (("quadspi", "BK1_IO0"), quote!(crate::qspi::D0Pin)), - (("quadspi", "BK1_IO1"), quote!(crate::qspi::D1Pin)), - (("quadspi", "BK1_IO2"), quote!(crate::qspi::D2Pin)), - (("quadspi", "BK1_IO3"), quote!(crate::qspi::D3Pin)), + (("quadspi", "BK1_IO0"), quote!(crate::qspi::BK1D0Pin)), + (("quadspi", "BK1_IO1"), quote!(crate::qspi::BK1D1Pin)), + (("quadspi", "BK1_IO2"), quote!(crate::qspi::BK1D2Pin)), + (("quadspi", "BK1_IO3"), quote!(crate::qspi::BK1D3Pin)), + (("quadspi", "BK1_NCS"), quote!(crate::qspi::BK1NSSPin)), + (("quadspi", "BK2_IO0"), quote!(crate::qspi::BK2D0Pin)), + (("quadspi", "BK2_IO1"), quote!(crate::qspi::BK2D1Pin)), + (("quadspi", "BK2_IO2"), quote!(crate::qspi::BK2D2Pin)), + (("quadspi", "BK2_IO3"), quote!(crate::qspi::BK2D3Pin)), + (("quadspi", "BK2_NCS"), quote!(crate::qspi::BK2NSSPin)), (("quadspi", "CLK"), quote!(crate::qspi::SckPin)), - (("quadspi", "BK1_NCS"), quote!(crate::qspi::NSSPin)), ].into(); for p in METADATA.peripherals { diff --git a/embassy-stm32/src/qspi/enums.rs b/embassy-stm32/src/qspi/enums.rs index 2dbe2b06..0412d991 100644 --- a/embassy-stm32/src/qspi/enums.rs +++ b/embassy-stm32/src/qspi/enums.rs @@ -38,6 +38,22 @@ impl Into for QspiWidth { } } +#[allow(dead_code)] +#[derive(Copy, Clone)] +pub enum FlashSelection { + Flash1, + Flash2, +} + +impl Into for FlashSelection { + fn into(self) -> bool { + match self { + FlashSelection::Flash1 => false, + FlashSelection::Flash2 => true, + } + } +} + #[derive(Copy, Clone)] pub enum MemorySize { _1KiB, diff --git a/embassy-stm32/src/qspi/mod.rs b/embassy-stm32/src/qspi/mod.rs index 32382fb2..8fb7df64 100644 --- a/embassy-stm32/src/qspi/mod.rs +++ b/embassy-stm32/src/qspi/mod.rs @@ -7,7 +7,7 @@ use enums::*; use crate::dma::Transfer; use crate::gpio::sealed::AFType; -use crate::gpio::AnyPin; +use crate::gpio::{AnyPin, Pull}; use crate::pac::quadspi::Quadspi as Regs; use crate::rcc::RccPeripheral; use crate::{peripherals, Peripheral}; @@ -83,30 +83,30 @@ pub struct Qspi<'d, T: Instance, Dma> { } impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> { - pub fn new( + pub fn new_bk1( peri: impl Peripheral

+ 'd, - d0: impl Peripheral

> + 'd, - d1: impl Peripheral

> + 'd, - d2: impl Peripheral

> + 'd, - d3: impl Peripheral

> + 'd, + d0: impl Peripheral

> + 'd, + d1: impl Peripheral

> + 'd, + d2: impl Peripheral

> + 'd, + d3: impl Peripheral

> + 'd, sck: impl Peripheral

> + 'd, - nss: impl Peripheral

> + 'd, + nss: impl Peripheral

> + 'd, dma: impl Peripheral

+ 'd, config: Config, ) -> Self { into_ref!(peri, d0, d1, d2, d3, sck, nss); - sck.set_as_af(sck.af_num(), AFType::OutputPushPull); + sck.set_as_af_pull(sck.af_num(), AFType::OutputPushPull, Pull::None); sck.set_speed(crate::gpio::Speed::VeryHigh); - nss.set_as_af(nss.af_num(), AFType::OutputPushPull); + nss.set_as_af_pull(nss.af_num(), AFType::OutputPushPull, Pull::Up); nss.set_speed(crate::gpio::Speed::VeryHigh); - d0.set_as_af(d0.af_num(), AFType::OutputPushPull); + d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::None); d0.set_speed(crate::gpio::Speed::VeryHigh); - d1.set_as_af(d1.af_num(), AFType::OutputPushPull); + d1.set_as_af_pull(d1.af_num(), AFType::OutputPushPull, Pull::None); d1.set_speed(crate::gpio::Speed::VeryHigh); - d2.set_as_af(d2.af_num(), AFType::OutputPushPull); + d2.set_as_af_pull(d2.af_num(), AFType::OutputPushPull, Pull::None); d2.set_speed(crate::gpio::Speed::VeryHigh); - d3.set_as_af(d3.af_num(), AFType::OutputPushPull); + d3.set_as_af_pull(d3.af_num(), AFType::OutputPushPull, Pull::None); d3.set_speed(crate::gpio::Speed::VeryHigh); Self::new_inner( @@ -119,6 +119,47 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> { Some(nss.map_into()), dma, config, + FlashSelection::Flash2, + ) + } + + pub fn new_bk2( + peri: impl Peripheral

+ 'd, + d0: impl Peripheral

> + 'd, + d1: impl Peripheral

> + 'd, + d2: impl Peripheral

> + 'd, + d3: impl Peripheral

> + 'd, + sck: impl Peripheral

> + 'd, + nss: impl Peripheral

> + 'd, + dma: impl Peripheral

+ 'd, + config: Config, + ) -> Self { + into_ref!(peri, d0, d1, d2, d3, sck, 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()), + Some(sck.map_into()), + Some(nss.map_into()), + dma, + config, + FlashSelection::Flash2, ) } @@ -132,22 +173,40 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> { nss: Option>, dma: impl Peripheral

+ 'd, config: Config, + fsel: FlashSelection, ) -> Self { into_ref!(peri, dma); T::enable(); - T::REGS.cr().write(|w| w.set_fthres(config.fifo_threshold.into())); + T::reset(); while T::REGS.sr().read().busy() {} - T::REGS.cr().write(|w| { - w.set_prescaler(config.prescaler); + #[cfg(stm32h7)] + { + use stm32_metapac::quadspi::regs::Cr; + // Apply precautionary steps according to the errata... + T::REGS.cr().write_value(Cr(0)); + while T::REGS.sr().read().busy() {} + T::REGS.cr().write_value(Cr(0xFF000001)); + T::REGS.ccr().write(|w| w.set_frcm(true)); + T::REGS.ccr().write(|w| w.set_frcm(true)); + T::REGS.cr().write_value(Cr(0)); + while T::REGS.sr().read().busy() {} + } + + T::REGS.cr().modify(|w| { w.set_en(true); + //w.set_tcen(false); + w.set_sshift(false); + w.set_fthres(config.fifo_threshold.into()); + w.set_prescaler(config.prescaler); + w.set_fsel(fsel.into()); }); - T::REGS.dcr().write(|w| { + T::REGS.dcr().modify(|w| { w.set_fsize(config.memory_size.into()); w.set_csht(config.cs_high_time.into()); - w.set_ckmode(false); + w.set_ckmode(true); }); Self { @@ -164,6 +223,7 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> { } pub fn command(&mut self, transaction: TransferConfig) { + #[cfg(not(stm32h7))] T::REGS.cr().modify(|v| v.set_dmaen(false)); self.setup_transaction(QspiMode::IndirectWrite, &transaction); @@ -172,6 +232,7 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> { } pub fn blocking_read(&mut self, buf: &mut [u8], transaction: TransferConfig) { + #[cfg(not(stm32h7))] T::REGS.cr().modify(|v| v.set_dmaen(false)); self.setup_transaction(QspiMode::IndirectWrite, &transaction); @@ -195,7 +256,10 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> { } pub fn blocking_write(&mut self, buf: &[u8], transaction: TransferConfig) { + // STM32H7 does not have dmaen + #[cfg(not(stm32h7))] T::REGS.cr().modify(|v| v.set_dmaen(false)); + self.setup_transaction(QspiMode::IndirectWrite, &transaction); if let Some(len) = transaction.data_len { @@ -238,6 +302,8 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> { ) }; + // STM32H7 does not have dmaen + #[cfg(not(stm32h7))] T::REGS.cr().modify(|v| v.set_dmaen(true)); transfer.blocking_wait(); @@ -264,6 +330,8 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> { ) }; + // STM32H7 does not have dmaen + #[cfg(not(stm32h7))] T::REGS.cr().modify(|v| v.set_dmaen(true)); transfer.blocking_wait(); @@ -313,11 +381,17 @@ pub(crate) mod sealed { pub trait Instance: Peripheral

+ sealed::Instance + RccPeripheral {} pin_trait!(SckPin, Instance); -pin_trait!(D0Pin, Instance); -pin_trait!(D1Pin, Instance); -pin_trait!(D2Pin, Instance); -pin_trait!(D3Pin, Instance); -pin_trait!(NSSPin, Instance); +pin_trait!(BK1D0Pin, Instance); +pin_trait!(BK1D1Pin, Instance); +pin_trait!(BK1D2Pin, Instance); +pin_trait!(BK1D3Pin, Instance); +pin_trait!(BK1NSSPin, Instance); + +pin_trait!(BK2D0Pin, Instance); +pin_trait!(BK2D1Pin, Instance); +pin_trait!(BK2D2Pin, Instance); +pin_trait!(BK2D3Pin, Instance); +pin_trait!(BK2NSSPin, Instance); dma_trait!(QuadDma, Instance);