From e7161aa085bb145df6607eff5b2c2d0ed06acda1 Mon Sep 17 00:00:00 2001
From: Dario Nieuwenhuis <dirbaio@dirbaio.net>
Date: Wed, 22 May 2024 00:23:14 +0200
Subject: [PATCH] stm32/qspi: remove DMA generic param.

---
 embassy-stm32/src/qspi/mod.rs    | 317 ++++++++++++++++---------------
 examples/stm32f7/src/bin/qspi.rs |  13 +-
 2 files changed, 173 insertions(+), 157 deletions(-)

diff --git a/embassy-stm32/src/qspi/mod.rs b/embassy-stm32/src/qspi/mod.rs
index 0a4b4f074..a82e93b5b 100644
--- a/embassy-stm32/src/qspi/mod.rs
+++ b/embassy-stm32/src/qspi/mod.rs
@@ -4,11 +4,14 @@
 
 pub mod enums;
 
+use core::marker::PhantomData;
+
 use embassy_hal_internal::{into_ref, PeripheralRef};
 use enums::*;
 
-use crate::dma::Transfer;
-use crate::gpio::{AFType, AnyPin, Pull};
+use crate::dma::ChannelAndRequest;
+use crate::gpio::{AFType, AnyPin, Pull, Speed};
+use crate::mode::{Async, Blocking, Mode as PeriMode};
 use crate::pac::quadspi::Quadspi as Regs;
 use crate::rcc::RccPeripheral;
 use crate::{peripherals, Peripheral};
@@ -71,7 +74,7 @@ impl Default for Config {
 
 /// QSPI driver.
 #[allow(dead_code)]
-pub struct Qspi<'d, T: Instance, Dma> {
+pub struct Qspi<'d, T: Instance, M: PeriMode> {
     _peri: PeripheralRef<'d, T>,
     sck: Option<PeripheralRef<'d, AnyPin>>,
     d0: Option<PeripheralRef<'d, AnyPin>>,
@@ -79,93 +82,12 @@ pub struct Qspi<'d, T: Instance, Dma> {
     d2: Option<PeripheralRef<'d, AnyPin>>,
     d3: Option<PeripheralRef<'d, AnyPin>>,
     nss: Option<PeripheralRef<'d, AnyPin>>,
-    dma: PeripheralRef<'d, Dma>,
+    dma: Option<ChannelAndRequest<'d>>,
+    _phantom: PhantomData<M>,
     config: Config,
 }
 
-impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> {
-    /// Create a new QSPI driver for bank 1.
-    pub fn new_bk1(
-        peri: impl Peripheral<P = T> + 'd,
-        d0: impl Peripheral<P = impl BK1D0Pin<T>> + 'd,
-        d1: impl Peripheral<P = impl BK1D1Pin<T>> + 'd,
-        d2: impl Peripheral<P = impl BK1D2Pin<T>> + 'd,
-        d3: impl Peripheral<P = impl BK1D3Pin<T>> + 'd,
-        sck: impl Peripheral<P = impl SckPin<T>> + 'd,
-        nss: impl Peripheral<P = impl BK1NSSPin<T>> + 'd,
-        dma: impl Peripheral<P = Dma> + '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::Flash1,
-        )
-    }
-
-    /// Create a new QSPI driver for bank 2.
-    pub fn new_bk2(
-        peri: impl Peripheral<P = T> + 'd,
-        d0: impl Peripheral<P = impl BK2D0Pin<T>> + 'd,
-        d1: impl Peripheral<P = impl BK2D1Pin<T>> + 'd,
-        d2: impl Peripheral<P = impl BK2D2Pin<T>> + 'd,
-        d3: impl Peripheral<P = impl BK2D3Pin<T>> + 'd,
-        sck: impl Peripheral<P = impl SckPin<T>> + 'd,
-        nss: impl Peripheral<P = impl BK2NSSPin<T>> + 'd,
-        dma: impl Peripheral<P = Dma> + '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,
-        )
-    }
-
+impl<'d, T: Instance, M: PeriMode> Qspi<'d, T, M> {
     fn new_inner(
         peri: impl Peripheral<P = T> + 'd,
         d0: Option<PeripheralRef<'d, AnyPin>>,
@@ -174,11 +96,11 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> {
         d3: Option<PeripheralRef<'d, AnyPin>>,
         sck: Option<PeripheralRef<'d, AnyPin>>,
         nss: Option<PeripheralRef<'d, AnyPin>>,
-        dma: impl Peripheral<P = Dma> + 'd,
+        dma: Option<ChannelAndRequest<'d>>,
         config: Config,
         fsel: FlashSelection,
     ) -> Self {
-        into_ref!(peri, dma);
+        into_ref!(peri);
 
         T::enable_and_reset();
 
@@ -220,6 +142,7 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> {
             d3,
             nss,
             dma,
+            _phantom: PhantomData,
             config,
         }
     }
@@ -278,68 +201,6 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> {
         T::REGS.fcr().modify(|v| v.set_ctcf(true));
     }
 
-    /// Blocking read data, using DMA.
-    pub fn blocking_read_dma(&mut self, buf: &mut [u8], transaction: TransferConfig)
-    where
-        Dma: QuadDma<T>,
-    {
-        self.setup_transaction(QspiMode::IndirectWrite, &transaction, Some(buf.len()));
-
-        T::REGS.ccr().modify(|v| {
-            v.set_fmode(QspiMode::IndirectRead.into());
-        });
-        let current_ar = T::REGS.ar().read().address();
-        T::REGS.ar().write(|v| {
-            v.set_address(current_ar);
-        });
-
-        let request = self.dma.request();
-        let transfer = unsafe {
-            Transfer::new_read(
-                &mut self.dma,
-                request,
-                T::REGS.dr().as_ptr() as *mut u8,
-                buf,
-                Default::default(),
-            )
-        };
-
-        // STM32H7 does not have dmaen
-        #[cfg(not(stm32h7))]
-        T::REGS.cr().modify(|v| v.set_dmaen(true));
-
-        transfer.blocking_wait();
-    }
-
-    /// Blocking write data, using DMA.
-    pub fn blocking_write_dma(&mut self, buf: &[u8], transaction: TransferConfig)
-    where
-        Dma: QuadDma<T>,
-    {
-        self.setup_transaction(QspiMode::IndirectWrite, &transaction, Some(buf.len()));
-
-        T::REGS.ccr().modify(|v| {
-            v.set_fmode(QspiMode::IndirectWrite.into());
-        });
-
-        let request = self.dma.request();
-        let transfer = unsafe {
-            Transfer::new_write(
-                &mut self.dma,
-                request,
-                buf,
-                T::REGS.dr().as_ptr() as *mut u8,
-                Default::default(),
-            )
-        };
-
-        // STM32H7 does not have dmaen
-        #[cfg(not(stm32h7))]
-        T::REGS.cr().modify(|v| v.set_dmaen(true));
-
-        transfer.blocking_wait();
-    }
-
     fn setup_transaction(&mut self, fmode: QspiMode, transaction: &TransferConfig, data_len: Option<usize>) {
         T::REGS.fcr().modify(|v| {
             v.set_csmf(true);
@@ -373,6 +234,160 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> {
     }
 }
 
+impl<'d, T: Instance> Qspi<'d, T, Blocking> {
+    /// Create a new QSPI driver for bank 1, in blocking mode.
+    pub fn new_blocking_bank1(
+        peri: impl Peripheral<P = T> + 'd,
+        d0: impl Peripheral<P = impl BK1D0Pin<T>> + 'd,
+        d1: impl Peripheral<P = impl BK1D1Pin<T>> + 'd,
+        d2: impl Peripheral<P = impl BK1D2Pin<T>> + 'd,
+        d3: impl Peripheral<P = impl BK1D3Pin<T>> + 'd,
+        sck: impl Peripheral<P = impl SckPin<T>> + 'd,
+        nss: impl Peripheral<P = impl BK1NSSPin<T>> + '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!(sck, AFType::OutputPushPull, Speed::VeryHigh),
+            new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up),
+            None,
+            config,
+            FlashSelection::Flash1,
+        )
+    }
+
+    /// Create a new QSPI driver for bank 2, in blocking mode.
+    pub fn new_blocking_bank2(
+        peri: impl Peripheral<P = T> + 'd,
+        d0: impl Peripheral<P = impl BK2D0Pin<T>> + 'd,
+        d1: impl Peripheral<P = impl BK2D1Pin<T>> + 'd,
+        d2: impl Peripheral<P = impl BK2D2Pin<T>> + 'd,
+        d3: impl Peripheral<P = impl BK2D3Pin<T>> + 'd,
+        sck: impl Peripheral<P = impl SckPin<T>> + 'd,
+        nss: impl Peripheral<P = impl BK2NSSPin<T>> + '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!(sck, AFType::OutputPushPull, Speed::VeryHigh),
+            new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up),
+            None,
+            config,
+            FlashSelection::Flash2,
+        )
+    }
+}
+
+impl<'d, T: Instance> Qspi<'d, T, Async> {
+    /// Create a new QSPI driver for bank 1.
+    pub fn new_bank1(
+        peri: impl Peripheral<P = T> + 'd,
+        d0: impl Peripheral<P = impl BK1D0Pin<T>> + 'd,
+        d1: impl Peripheral<P = impl BK1D1Pin<T>> + 'd,
+        d2: impl Peripheral<P = impl BK1D2Pin<T>> + 'd,
+        d3: impl Peripheral<P = impl BK1D3Pin<T>> + 'd,
+        sck: impl Peripheral<P = impl SckPin<T>> + 'd,
+        nss: impl Peripheral<P = impl BK1NSSPin<T>> + 'd,
+        dma: impl Peripheral<P = impl QuadDma<T>> + '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!(sck, AFType::OutputPushPull, Speed::VeryHigh),
+            new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up),
+            new_dma!(dma),
+            config,
+            FlashSelection::Flash1,
+        )
+    }
+
+    /// Create a new QSPI driver for bank 2.
+    pub fn new_bank2(
+        peri: impl Peripheral<P = T> + 'd,
+        d0: impl Peripheral<P = impl BK2D0Pin<T>> + 'd,
+        d1: impl Peripheral<P = impl BK2D1Pin<T>> + 'd,
+        d2: impl Peripheral<P = impl BK2D2Pin<T>> + 'd,
+        d3: impl Peripheral<P = impl BK2D3Pin<T>> + 'd,
+        sck: impl Peripheral<P = impl SckPin<T>> + 'd,
+        nss: impl Peripheral<P = impl BK2NSSPin<T>> + 'd,
+        dma: impl Peripheral<P = impl QuadDma<T>> + '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!(sck, AFType::OutputPushPull, Speed::VeryHigh),
+            new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up),
+            new_dma!(dma),
+            config,
+            FlashSelection::Flash2,
+        )
+    }
+
+    /// Blocking read data, using DMA.
+    pub fn blocking_read_dma(&mut self, buf: &mut [u8], transaction: TransferConfig) {
+        self.setup_transaction(QspiMode::IndirectWrite, &transaction, Some(buf.len()));
+
+        T::REGS.ccr().modify(|v| {
+            v.set_fmode(QspiMode::IndirectRead.into());
+        });
+        let current_ar = T::REGS.ar().read().address();
+        T::REGS.ar().write(|v| {
+            v.set_address(current_ar);
+        });
+
+        let transfer = unsafe {
+            self.dma
+                .as_mut()
+                .unwrap()
+                .read(T::REGS.dr().as_ptr() as *mut u8, buf, Default::default())
+        };
+
+        // STM32H7 does not have dmaen
+        #[cfg(not(stm32h7))]
+        T::REGS.cr().modify(|v| v.set_dmaen(true));
+
+        transfer.blocking_wait();
+    }
+
+    /// Blocking write data, using DMA.
+    pub fn blocking_write_dma(&mut self, buf: &[u8], transaction: TransferConfig) {
+        self.setup_transaction(QspiMode::IndirectWrite, &transaction, Some(buf.len()));
+
+        T::REGS.ccr().modify(|v| {
+            v.set_fmode(QspiMode::IndirectWrite.into());
+        });
+
+        let transfer = unsafe {
+            self.dma
+                .as_mut()
+                .unwrap()
+                .write(buf, T::REGS.dr().as_ptr() as *mut u8, Default::default())
+        };
+
+        // STM32H7 does not have dmaen
+        #[cfg(not(stm32h7))]
+        T::REGS.cr().modify(|v| v.set_dmaen(true));
+
+        transfer.blocking_wait();
+    }
+}
+
 trait SealedInstance {
     const REGS: Regs;
 }
diff --git a/examples/stm32f7/src/bin/qspi.rs b/examples/stm32f7/src/bin/qspi.rs
index 005694db3..90d319b7a 100644
--- a/examples/stm32f7/src/bin/qspi.rs
+++ b/examples/stm32f7/src/bin/qspi.rs
@@ -4,8 +4,9 @@
 
 use defmt::info;
 use embassy_executor::Spawner;
+use embassy_stm32::mode::Async;
 use embassy_stm32::qspi::enums::{AddressSize, ChipSelectHighTime, FIFOThresholdLevel, MemorySize, *};
-use embassy_stm32::qspi::{Config as QspiCfg, Instance, Qspi, QuadDma, TransferConfig};
+use embassy_stm32::qspi::{Config as QspiCfg, Instance, Qspi, TransferConfig};
 use embassy_stm32::time::mhz;
 use embassy_stm32::Config as StmCfg;
 use {defmt_rtt as _, panic_probe as _};
@@ -43,12 +44,12 @@ const MEMORY_ADDR: u32 = 0x00000000u32;
 /// Implementation of access to flash chip.
 /// Chip commands are hardcoded as it depends on used chip.
 /// This implementation is using chip GD25Q64C from Giga Device
-pub struct FlashMemory<I: Instance, D: QuadDma<I>> {
-    qspi: Qspi<'static, I, D>,
+pub struct FlashMemory<I: Instance> {
+    qspi: Qspi<'static, I, Async>,
 }
 
-impl<I: Instance, D: QuadDma<I>> FlashMemory<I, D> {
-    pub fn new(qspi: Qspi<'static, I, D>) -> Self {
+impl<I: Instance> FlashMemory<I> {
+    pub fn new(qspi: Qspi<'static, I, Async>) -> Self {
         let mut memory = Self { qspi };
 
         memory.reset_memory();
@@ -279,7 +280,7 @@ async fn main(_spawner: Spawner) -> ! {
         cs_high_time: ChipSelectHighTime::_1Cycle,
         fifo_threshold: FIFOThresholdLevel::_16Bytes,
     };
-    let driver = Qspi::new_bk1(
+    let driver = Qspi::new_bank1(
         p.QUADSPI, p.PF8, p.PF9, p.PE2, p.PF6, p.PF10, p.PB10, p.DMA2_CH7, config,
     );
     let mut flash = FlashMemory::new(driver);