From 803b76df86ed5eadfa3e0150bc5a3b129ae1f7c6 Mon Sep 17 00:00:00 2001
From: Andelf <andelf@gmail.com>
Date: Mon, 8 Apr 2024 01:23:49 +0800
Subject: [PATCH 1/6] Fix crash caused by using higher MSI on STM32WL

---
 embassy-stm32/src/rcc/l.rs | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/embassy-stm32/src/rcc/l.rs b/embassy-stm32/src/rcc/l.rs
index 9079ddd41..d40ea0c53 100644
--- a/embassy-stm32/src/rcc/l.rs
+++ b/embassy-stm32/src/rcc/l.rs
@@ -157,6 +157,13 @@ pub(crate) unsafe fn init(config: Config) {
         while RCC.cfgr().read().sws() != Sysclk::MSI {}
     }
 
+    #[cfg(stm32wl)]
+    {
+        // Set max latency
+        FLASH.acr().modify(|w| w.set_prften(true));
+        FLASH.acr().modify(|w| w.set_latency(2));
+    }
+
     // Set voltage scale
     #[cfg(any(stm32l0, stm32l1))]
     {

From 10ee1c1ae8cc7d1b561235c04b5dcc153b35e552 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Aur=C3=A9lien=20Jacobs?= <aurel@gnuage.org>
Date: Tue, 16 Apr 2024 23:36:47 +0200
Subject: [PATCH 2/6] stm32: ensure the core runs on HSI clock while setting up
 rcc

---
 embassy-stm32/src/rcc/f247.rs | 24 +++++++++++++++---------
 1 file changed, 15 insertions(+), 9 deletions(-)

diff --git a/embassy-stm32/src/rcc/f247.rs b/embassy-stm32/src/rcc/f247.rs
index 7b252870c..7b2d93027 100644
--- a/embassy-stm32/src/rcc/f247.rs
+++ b/embassy-stm32/src/rcc/f247.rs
@@ -146,17 +146,18 @@ pub(crate) unsafe fn init(config: Config) {
         while !PWR.csr1().read().odswrdy() {}
     }
 
+    // Turn on the HSI
+    RCC.cr().modify(|w| w.set_hsion(true));
+    while !RCC.cr().read().hsirdy() {}
+
+    // Use the HSI clock as system clock during the actual clock setup
+    RCC.cfgr().modify(|w| w.set_sw(Sysclk::HSI));
+    while RCC.cfgr().read().sws() != Sysclk::HSI {}
+
     // Configure HSI
     let hsi = match config.hsi {
-        false => {
-            RCC.cr().modify(|w| w.set_hsion(false));
-            None
-        }
-        true => {
-            RCC.cr().modify(|w| w.set_hsion(true));
-            while !RCC.cr().read().hsirdy() {}
-            Some(HSI_FREQ)
-        }
+        false => None,
+        true => Some(HSI_FREQ),
     };
 
     // Configure HSE
@@ -260,6 +261,11 @@ pub(crate) unsafe fn init(config: Config) {
     });
     while RCC.cfgr().read().sws() != config.sys {}
 
+    // Disable HSI if not used
+    if !config.hsi {
+        RCC.cr().modify(|w| w.set_hsion(false));
+    }
+
     config.mux.init();
 
     set_clocks!(

From 3e399a9690b1623ce43ea94bf626bda573fac38b Mon Sep 17 00:00:00 2001
From: Karun <karun@nautilusdefense.com>
Date: Tue, 14 May 2024 12:45:07 -0400
Subject: [PATCH 3/6] update to remove dma generics

---
 embassy-stm32/src/ospi/mod.rs | 899 ++++++++++++++++++----------------
 1 file changed, 478 insertions(+), 421 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<PeripheralRef<'d, AnyPin>>,
     d0: Option<PeripheralRef<'d, AnyPin>>,
@@ -167,259 +170,13 @@ pub struct Ospi<'d, T: Instance, Dma> {
     d7: Option<PeripheralRef<'d, AnyPin>>,
     nss: Option<PeripheralRef<'d, AnyPin>>,
     dqs: Option<PeripheralRef<'d, AnyPin>>,
-    dma: PeripheralRef<'d, Dma>,
+    dma: Option<ChannelAndRequest<'d>>,
+    _phantom: PhantomData<M>,
     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<P = T> + 'd,
-        sck: impl Peripheral<P = impl SckPin<T>> + 'd,
-        d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
-        d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
-        nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
-        dma: impl Peripheral<P = Dma> + '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<P = T> + 'd,
-        sck: impl Peripheral<P = impl SckPin<T>> + 'd,
-        d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
-        d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
-        nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
-        dma: impl Peripheral<P = Dma> + '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<P = T> + 'd,
-        sck: impl Peripheral<P = impl SckPin<T>> + 'd,
-        d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
-        d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
-        d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
-        d3: impl Peripheral<P = impl D3Pin<T>> + 'd,
-        nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
-        dma: impl Peripheral<P = Dma> + '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<P = T> + 'd,
-        sck: impl Peripheral<P = impl SckPin<T>> + 'd,
-        d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
-        d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
-        d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
-        d3: impl Peripheral<P = impl D3Pin<T>> + 'd,
-        d4: impl Peripheral<P = impl D4Pin<T>> + 'd,
-        d5: impl Peripheral<P = impl D5Pin<T>> + 'd,
-        d6: impl Peripheral<P = impl D6Pin<T>> + 'd,
-        d7: impl Peripheral<P = impl D7Pin<T>> + 'd,
-        nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
-        dma: impl Peripheral<P = Dma> + '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<P = T> + 'd,
-        sck: impl Peripheral<P = impl SckPin<T>> + 'd,
-        d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
-        d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
-        d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
-        d3: impl Peripheral<P = impl D3Pin<T>> + 'd,
-        d4: impl Peripheral<P = impl D4Pin<T>> + 'd,
-        d5: impl Peripheral<P = impl D5Pin<T>> + 'd,
-        d6: impl Peripheral<P = impl D6Pin<T>> + 'd,
-        d7: impl Peripheral<P = impl D7Pin<T>> + 'd,
-        nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
-        dma: impl Peripheral<P = Dma> + '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<P = T> + 'd,
         d0: Option<PeripheralRef<'d, AnyPin>>,
@@ -433,12 +190,12 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
         sck: Option<PeripheralRef<'d, AnyPin>>,
         nss: Option<PeripheralRef<'d, AnyPin>>,
         dqs: Option<PeripheralRef<'d, AnyPin>>,
-        dma: impl Peripheral<P = Dma> + 'd,
+        dma: Option<ChannelAndRequest<'d>>,
         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,170 +460,6 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
         Ok(())
     }
 
-    /// Blocking read with DMA transfer
-    pub fn blocking_read_dma<W: Word>(&mut self, buf: &mut [W], transaction: TransferConfig) -> Result<(), OspiError>
-    where
-        Dma: OctoDma<T>,
-    {
-        if buf.is_empty() {
-            return Err(OspiError::EmptyBuffer);
-        }
-
-        // Wait for peripheral to be free
-        while T::REGS.sr().read().busy() {}
-
-        self.configure_command(&transaction, Some(buf.len()))?;
-
-        let current_address = T::REGS.ar().read().address();
-        let current_instruction = T::REGS.ir().read().instruction();
-
-        // For a indirect read transaction, the transaction begins when the instruction/address is set
-        T::REGS.cr().modify(|v| v.set_fmode(vals::FunctionalMode::INDIRECTREAD));
-        if T::REGS.ccr().read().admode() == vals::PhaseMode::NONE {
-            T::REGS.ir().write(|v| v.set_instruction(current_instruction));
-        } else {
-            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(),
-            )
-        };
-
-        T::REGS.cr().modify(|w| w.set_dmaen(true));
-
-        transfer.blocking_wait();
-
-        finish_dma(T::REGS);
-
-        Ok(())
-    }
-
-    /// Blocking write with DMA transfer
-    pub fn blocking_write_dma<W: Word>(&mut self, buf: &[W], transaction: TransferConfig) -> Result<(), OspiError>
-    where
-        Dma: OctoDma<T>,
-    {
-        if buf.is_empty() {
-            return Err(OspiError::EmptyBuffer);
-        }
-
-        // Wait for peripheral to be free
-        while T::REGS.sr().read().busy() {}
-
-        self.configure_command(&transaction, Some(buf.len()))?;
-        T::REGS
-            .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(),
-            )
-        };
-
-        T::REGS.cr().modify(|w| w.set_dmaen(true));
-
-        transfer.blocking_wait();
-
-        finish_dma(T::REGS);
-
-        Ok(())
-    }
-
-    /// Asynchronous read from external device
-    pub async fn read<W: Word>(&mut self, buf: &mut [W], transaction: TransferConfig) -> Result<(), OspiError>
-    where
-        Dma: OctoDma<T>,
-    {
-        if buf.is_empty() {
-            return Err(OspiError::EmptyBuffer);
-        }
-
-        // Wait for peripheral to be free
-        while T::REGS.sr().read().busy() {}
-
-        self.configure_command(&transaction, Some(buf.len()))?;
-
-        let current_address = T::REGS.ar().read().address();
-        let current_instruction = T::REGS.ir().read().instruction();
-
-        // For a indirect read transaction, the transaction begins when the instruction/address is set
-        T::REGS.cr().modify(|v| v.set_fmode(vals::FunctionalMode::INDIRECTREAD));
-        if T::REGS.ccr().read().admode() == vals::PhaseMode::NONE {
-            T::REGS.ir().write(|v| v.set_instruction(current_instruction));
-        } else {
-            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(),
-            )
-        };
-
-        T::REGS.cr().modify(|w| w.set_dmaen(true));
-
-        transfer.await;
-
-        finish_dma(T::REGS);
-
-        Ok(())
-    }
-
-    /// Asynchronous write to external device
-    pub async fn write<W: Word>(&mut self, buf: &[W], transaction: TransferConfig) -> Result<(), OspiError>
-    where
-        Dma: OctoDma<T>,
-    {
-        if buf.is_empty() {
-            return Err(OspiError::EmptyBuffer);
-        }
-
-        // Wait for peripheral to be free
-        while T::REGS.sr().read().busy() {}
-
-        self.configure_command(&transaction, Some(buf.len()))?;
-        T::REGS
-            .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(),
-            )
-        };
-
-        T::REGS.cr().modify(|w| w.set_dmaen(true));
-
-        transfer.await;
-
-        finish_dma(T::REGS);
-
-        Ok(())
-    }
-
     /// Set new bus configuration
     pub fn set_config(&mut self, config: &Config) {
         // Wait for busy flag to clear
@@ -942,7 +536,470 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
     }
 }
 
-impl<'d, T: Instance, Dma> Drop for Ospi<'d, T, Dma> {
+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<P = T> + 'd,
+        sck: impl Peripheral<P = impl SckPin<T>> + 'd,
+        d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
+        d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
+        nss: impl Peripheral<P = impl NSSPin<T>> + '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<P = T> + 'd,
+        sck: impl Peripheral<P = impl SckPin<T>> + 'd,
+        d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
+        d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
+        nss: impl Peripheral<P = impl NSSPin<T>> + '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<P = T> + 'd,
+        sck: impl Peripheral<P = impl SckPin<T>> + 'd,
+        d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
+        d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
+        d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
+        d3: impl Peripheral<P = impl D3Pin<T>> + 'd,
+        nss: impl Peripheral<P = impl NSSPin<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),
+            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<P = T> + 'd,
+        sck: impl Peripheral<P = impl SckPin<T>> + 'd,
+        d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
+        d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
+        d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
+        d3: impl Peripheral<P = impl D3Pin<T>> + 'd,
+        d4: impl Peripheral<P = impl D4Pin<T>> + 'd,
+        d5: impl Peripheral<P = impl D5Pin<T>> + 'd,
+        d6: impl Peripheral<P = impl D6Pin<T>> + 'd,
+        d7: impl Peripheral<P = impl D7Pin<T>> + 'd,
+        nss: impl Peripheral<P = impl NSSPin<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!(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<P = T> + 'd,
+        sck: impl Peripheral<P = impl SckPin<T>> + 'd,
+        d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
+        d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
+        d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
+        d3: impl Peripheral<P = impl D3Pin<T>> + 'd,
+        d4: impl Peripheral<P = impl D4Pin<T>> + 'd,
+        d5: impl Peripheral<P = impl D5Pin<T>> + 'd,
+        d6: impl Peripheral<P = impl D6Pin<T>> + 'd,
+        d7: impl Peripheral<P = impl D7Pin<T>> + 'd,
+        nss: impl Peripheral<P = impl NSSPin<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!(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<P = T> + 'd,
+        sck: impl Peripheral<P = impl SckPin<T>> + 'd,
+        d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
+        d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
+        nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
+        dma: impl Peripheral<P = impl OctoDma<T>> + '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<P = T> + 'd,
+        sck: impl Peripheral<P = impl SckPin<T>> + 'd,
+        d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
+        d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
+        nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
+        dma: impl Peripheral<P = impl OctoDma<T>> + '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<P = T> + 'd,
+        sck: impl Peripheral<P = impl SckPin<T>> + 'd,
+        d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
+        d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
+        d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
+        d3: impl Peripheral<P = impl D3Pin<T>> + 'd,
+        nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
+        dma: impl Peripheral<P = impl OctoDma<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),
+            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<P = T> + 'd,
+        sck: impl Peripheral<P = impl SckPin<T>> + 'd,
+        d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
+        d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
+        d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
+        d3: impl Peripheral<P = impl D3Pin<T>> + 'd,
+        d4: impl Peripheral<P = impl D4Pin<T>> + 'd,
+        d5: impl Peripheral<P = impl D5Pin<T>> + 'd,
+        d6: impl Peripheral<P = impl D6Pin<T>> + 'd,
+        d7: impl Peripheral<P = impl D7Pin<T>> + 'd,
+        nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
+        dma: impl Peripheral<P = impl OctoDma<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!(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<P = T> + 'd,
+        sck: impl Peripheral<P = impl SckPin<T>> + 'd,
+        d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
+        d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
+        d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
+        d3: impl Peripheral<P = impl D3Pin<T>> + 'd,
+        d4: impl Peripheral<P = impl D4Pin<T>> + 'd,
+        d5: impl Peripheral<P = impl D5Pin<T>> + 'd,
+        d6: impl Peripheral<P = impl D6Pin<T>> + 'd,
+        d7: impl Peripheral<P = impl D7Pin<T>> + 'd,
+        nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
+        dma: impl Peripheral<P = impl OctoDma<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!(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<W: Word>(&mut self, buf: &mut [W], transaction: TransferConfig) -> Result<(), OspiError> {
+        if buf.is_empty() {
+            return Err(OspiError::EmptyBuffer);
+        }
+
+        // Wait for peripheral to be free
+        while T::REGS.sr().read().busy() {}
+
+        self.configure_command(&transaction, Some(buf.len()))?;
+
+        let current_address = T::REGS.ar().read().address();
+        let current_instruction = T::REGS.ir().read().instruction();
+
+        // For a indirect read transaction, the transaction begins when the instruction/address is set
+        T::REGS.cr().modify(|v| v.set_fmode(vals::FunctionalMode::INDIRECTREAD));
+        if T::REGS.ccr().read().admode() == vals::PhaseMode::NONE {
+            T::REGS.ir().write(|v| v.set_instruction(current_instruction));
+        } else {
+            T::REGS.ar().write(|v| v.set_address(current_address));
+        }
+
+        let transfer = unsafe {
+            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));
+
+        transfer.blocking_wait();
+
+        finish_dma(T::REGS);
+
+        Ok(())
+    }
+
+    /// Blocking write with DMA transfer
+    pub fn blocking_write_dma<W: Word>(&mut self, buf: &[W], transaction: TransferConfig) -> Result<(), OspiError> {
+        if buf.is_empty() {
+            return Err(OspiError::EmptyBuffer);
+        }
+
+        // Wait for peripheral to be free
+        while T::REGS.sr().read().busy() {}
+
+        self.configure_command(&transaction, Some(buf.len()))?;
+        T::REGS
+            .cr()
+            .modify(|v| v.set_fmode(vals::FunctionalMode::INDIRECTWRITE));
+
+        let transfer = unsafe {
+            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));
+
+        transfer.blocking_wait();
+
+        finish_dma(T::REGS);
+
+        Ok(())
+    }
+
+    /// Asynchronous read from external device
+    pub async fn read<W: Word>(&mut self, buf: &mut [W], transaction: TransferConfig) -> Result<(), OspiError> {
+        if buf.is_empty() {
+            return Err(OspiError::EmptyBuffer);
+        }
+
+        // Wait for peripheral to be free
+        while T::REGS.sr().read().busy() {}
+
+        self.configure_command(&transaction, Some(buf.len()))?;
+
+        let current_address = T::REGS.ar().read().address();
+        let current_instruction = T::REGS.ir().read().instruction();
+
+        // For a indirect read transaction, the transaction begins when the instruction/address is set
+        T::REGS.cr().modify(|v| v.set_fmode(vals::FunctionalMode::INDIRECTREAD));
+        if T::REGS.ccr().read().admode() == vals::PhaseMode::NONE {
+            T::REGS.ir().write(|v| v.set_instruction(current_instruction));
+        } else {
+            T::REGS.ar().write(|v| v.set_address(current_address));
+        }
+
+        let transfer = unsafe {
+            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));
+
+        transfer.await;
+
+        finish_dma(T::REGS);
+
+        Ok(())
+    }
+
+    /// Asynchronous write to external device
+    pub async fn write<W: Word>(&mut self, buf: &[W], transaction: TransferConfig) -> Result<(), OspiError> {
+        if buf.is_empty() {
+            return Err(OspiError::EmptyBuffer);
+        }
+
+        // Wait for peripheral to be free
+        while T::REGS.sr().read().busy() {}
+
+        self.configure_command(&transaction, Some(buf.len()))?;
+        T::REGS
+            .cr()
+            .modify(|v| v.set_fmode(vals::FunctionalMode::INDIRECTWRITE));
+
+        let transfer = unsafe {
+            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));
+
+        transfer.await;
+
+        finish_dma(T::REGS);
+
+        Ok(())
+    }
+}
+
+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()

From 24032d0853adc799588dbc84315b3e72ec5bf7b2 Mon Sep 17 00:00:00 2001
From: Ismet Handzic <ismet.handzic@gmail.com>
Date: Sat, 6 Apr 2024 11:33:58 -0400
Subject: [PATCH 4/6] Remove generics from embassy-rp

---
 embassy-rp/src/pwm.rs | 92 +++++++++++++++++++++++--------------------
 1 file changed, 50 insertions(+), 42 deletions(-)

diff --git a/embassy-rp/src/pwm.rs b/embassy-rp/src/pwm.rs
index a1f400cfb..2e5aebc57 100644
--- a/embassy-rp/src/pwm.rs
+++ b/embassy-rp/src/pwm.rs
@@ -81,24 +81,22 @@ impl From<InputMode> for Divmode {
 }
 
 /// PWM driver.
-pub struct Pwm<'d, T: Slice> {
-    inner: PeripheralRef<'d, T>,
+pub struct Pwm<'d> {
     pin_a: Option<PeripheralRef<'d, AnyPin>>,
     pin_b: Option<PeripheralRef<'d, AnyPin>>,
+    channel: usize,
 }
 
-impl<'d, T: Slice> Pwm<'d, T> {
+impl<'d> Pwm<'d> {
     fn new_inner(
-        inner: impl Peripheral<P = T> + 'd,
+        channel: usize,
         a: Option<PeripheralRef<'d, AnyPin>>,
         b: Option<PeripheralRef<'d, AnyPin>>,
         b_pull: Pull,
         config: Config,
         divmode: Divmode,
     ) -> Self {
-        into_ref!(inner);
-
-        let p = inner.regs();
+        let p = pac::PWM.ch(channel);
         p.csr().modify(|w| {
             w.set_divmode(divmode);
             w.set_en(false);
@@ -117,51 +115,66 @@ impl<'d, T: Slice> Pwm<'d, T> {
             });
         }
         Self {
-            inner,
+            // inner: p.into(),
             pin_a: a,
             pin_b: b,
+            channel,
         }
     }
 
     /// Create PWM driver without any configured pins.
     #[inline]
-    pub fn new_free(inner: impl Peripheral<P = T> + 'd, config: Config) -> Self {
-        Self::new_inner(inner, None, None, Pull::None, config, Divmode::DIV)
+    pub fn new_free<T: Slice>(channel: impl Peripheral<P = T> + 'd, config: Config) -> Self {
+        Self::new_inner(channel.number(), None, None, Pull::None, config, Divmode::DIV)
     }
 
     /// Create PWM driver with a single 'a' as output.
     #[inline]
-    pub fn new_output_a(
-        inner: impl Peripheral<P = T> + 'd,
+    pub fn new_output_a<T: Slice>(
+        channel: impl Peripheral<P = T> + 'd,
         a: impl Peripheral<P = impl ChannelAPin<T>> + 'd,
         config: Config,
     ) -> Self {
         into_ref!(a);
-        Self::new_inner(inner, Some(a.map_into()), None, Pull::None, config, Divmode::DIV)
+        Self::new_inner(
+            channel.number(),
+            Some(a.map_into()),
+            None,
+            Pull::None,
+            config,
+            Divmode::DIV,
+        )
     }
 
     /// Create PWM driver with a single 'b' pin as output.
     #[inline]
-    pub fn new_output_b(
-        inner: impl Peripheral<P = T> + 'd,
+    pub fn new_output_b<T: Slice>(
+        channel: impl Peripheral<P = T> + 'd,
         b: impl Peripheral<P = impl ChannelBPin<T>> + 'd,
         config: Config,
     ) -> Self {
         into_ref!(b);
-        Self::new_inner(inner, None, Some(b.map_into()), Pull::None, config, Divmode::DIV)
+        Self::new_inner(
+            channel.number(),
+            None,
+            Some(b.map_into()),
+            Pull::None,
+            config,
+            Divmode::DIV,
+        )
     }
 
     /// Create PWM driver with a 'a' and 'b' pins as output.
     #[inline]
-    pub fn new_output_ab(
-        inner: impl Peripheral<P = T> + 'd,
+    pub fn new_output_ab<T: Slice>(
+        channel: impl Peripheral<P = T> + 'd,
         a: impl Peripheral<P = impl ChannelAPin<T>> + 'd,
         b: impl Peripheral<P = impl ChannelBPin<T>> + 'd,
         config: Config,
     ) -> Self {
         into_ref!(a, b);
         Self::new_inner(
-            inner,
+            channel.number(),
             Some(a.map_into()),
             Some(b.map_into()),
             Pull::None,
@@ -172,21 +185,21 @@ impl<'d, T: Slice> Pwm<'d, T> {
 
     /// Create PWM driver with a single 'b' as input pin.
     #[inline]
-    pub fn new_input(
-        inner: impl Peripheral<P = T> + 'd,
+    pub fn new_input<T: Slice>(
+        channel: impl Peripheral<P = T> + 'd,
         b: impl Peripheral<P = impl ChannelBPin<T>> + 'd,
         b_pull: Pull,
         mode: InputMode,
         config: Config,
     ) -> Self {
         into_ref!(b);
-        Self::new_inner(inner, None, Some(b.map_into()), b_pull, config, mode.into())
+        Self::new_inner(channel.number(), None, Some(b.map_into()), b_pull, config, mode.into())
     }
 
     /// Create PWM driver with a 'a' and 'b' pins in the desired input mode.
     #[inline]
-    pub fn new_output_input(
-        inner: impl Peripheral<P = T> + 'd,
+    pub fn new_output_input<T: Slice>(
+        channel: impl Peripheral<P = T> + 'd,
         a: impl Peripheral<P = impl ChannelAPin<T>> + 'd,
         b: impl Peripheral<P = impl ChannelBPin<T>> + 'd,
         b_pull: Pull,
@@ -195,7 +208,7 @@ impl<'d, T: Slice> Pwm<'d, T> {
     ) -> Self {
         into_ref!(a, b);
         Self::new_inner(
-            inner,
+            channel.number(),
             Some(a.map_into()),
             Some(b.map_into()),
             b_pull,
@@ -206,7 +219,7 @@ impl<'d, T: Slice> Pwm<'d, T> {
 
     /// Set the PWM config.
     pub fn set_config(&mut self, config: &Config) {
-        Self::configure(self.inner.regs(), config);
+        Self::configure(pac::PWM.ch(self.channel), config);
     }
 
     fn configure(p: pac::pwm::Channel, config: &Config) {
@@ -228,22 +241,22 @@ impl<'d, T: Slice> Pwm<'d, T> {
         });
     }
 
-    /// Advances a slice’s output phase by one count while it is running
+    /// Advances a slice's output phase by one count while it is running
     /// by inserting a pulse into the clock enable. The counter
     /// will not count faster than once per cycle.
     #[inline]
     pub fn phase_advance(&mut self) {
-        let p = self.inner.regs();
+        let p = pac::PWM.ch(self.channel);
         p.csr().write_set(|w| w.set_ph_adv(true));
         while p.csr().read().ph_adv() {}
     }
 
-    /// Retards a slice’s output phase by one count while it is running
+    /// Retards a slice's output phase by one count while it is running
     /// by deleting a pulse from the clock enable. The counter will not
-    /// count backward when clock enable is permenantly low.
+    /// count backward when clock enable is permanently low.
     #[inline]
     pub fn phase_retard(&mut self) {
-        let p = self.inner.regs();
+        let p = pac::PWM.ch(self.channel);
         p.csr().write_set(|w| w.set_ph_ret(true));
         while p.csr().read().ph_ret() {}
     }
@@ -251,13 +264,13 @@ impl<'d, T: Slice> Pwm<'d, T> {
     /// Read PWM counter.
     #[inline]
     pub fn counter(&self) -> u16 {
-        self.inner.regs().ctr().read().ctr()
+        pac::PWM.ch(self.channel).ctr().read().ctr()
     }
 
     /// Write PWM counter.
     #[inline]
     pub fn set_counter(&self, ctr: u16) {
-        self.inner.regs().ctr().write(|w| w.set_ctr(ctr))
+        pac::PWM.ch(self.channel).ctr().write(|w| w.set_ctr(ctr))
     }
 
     /// Wait for channel interrupt.
@@ -281,7 +294,7 @@ impl<'d, T: Slice> Pwm<'d, T> {
 
     #[inline]
     fn bit(&self) -> u32 {
-        1 << self.inner.number() as usize
+        1 << self.channel as usize
     }
 }
 
@@ -291,7 +304,7 @@ pub struct PwmBatch(u32);
 impl PwmBatch {
     #[inline]
     /// Enable a PWM slice in this batch.
-    pub fn enable(&mut self, pwm: &Pwm<'_, impl Slice>) {
+    pub fn enable(&mut self, pwm: &Pwm<'_>) {
         self.0 |= pwm.bit();
     }
 
@@ -308,9 +321,9 @@ impl PwmBatch {
     }
 }
 
-impl<'d, T: Slice> Drop for Pwm<'d, T> {
+impl<'d> Drop for Pwm<'d> {
     fn drop(&mut self) {
-        self.inner.regs().csr().write_clear(|w| w.set_en(false));
+        pac::PWM.ch(self.channel).csr().write_clear(|w| w.set_en(false));
         if let Some(pin) = &self.pin_a {
             pin.gpio().ctrl().write(|w| w.set_funcsel(31));
         }
@@ -327,11 +340,6 @@ trait SealedSlice {}
 pub trait Slice: Peripheral<P = Self> + SealedSlice + Sized + 'static {
     /// Slice number.
     fn number(&self) -> u8;
-
-    /// Slice register block.
-    fn regs(&self) -> pac::pwm::Channel {
-        pac::PWM.ch(self.number() as _)
-    }
 }
 
 macro_rules! slice {

From e55f31bdc6882b6a6ac78a59aabf42ff9433f48d Mon Sep 17 00:00:00 2001
From: Dario Nieuwenhuis <dirbaio@dirbaio.net>
Date: Tue, 21 May 2024 23:41:45 +0200
Subject: [PATCH 5/6] rp/pwm: rename channel->slice in args, misc fix.

---
 embassy-rp/src/pwm.rs            | 61 ++++++++++++++++----------------
 examples/rp/src/bin/interrupt.rs |  3 +-
 2 files changed, 32 insertions(+), 32 deletions(-)

diff --git a/embassy-rp/src/pwm.rs b/embassy-rp/src/pwm.rs
index 2e5aebc57..20b5c4d58 100644
--- a/embassy-rp/src/pwm.rs
+++ b/embassy-rp/src/pwm.rs
@@ -84,19 +84,19 @@ impl From<InputMode> for Divmode {
 pub struct Pwm<'d> {
     pin_a: Option<PeripheralRef<'d, AnyPin>>,
     pin_b: Option<PeripheralRef<'d, AnyPin>>,
-    channel: usize,
+    slice: usize,
 }
 
 impl<'d> Pwm<'d> {
     fn new_inner(
-        channel: usize,
+        slice: usize,
         a: Option<PeripheralRef<'d, AnyPin>>,
         b: Option<PeripheralRef<'d, AnyPin>>,
         b_pull: Pull,
         config: Config,
         divmode: Divmode,
     ) -> Self {
-        let p = pac::PWM.ch(channel);
+        let p = pac::PWM.ch(slice);
         p.csr().modify(|w| {
             w.set_divmode(divmode);
             w.set_en(false);
@@ -118,26 +118,27 @@ impl<'d> Pwm<'d> {
             // inner: p.into(),
             pin_a: a,
             pin_b: b,
-            channel,
+            slice,
         }
     }
 
     /// Create PWM driver without any configured pins.
     #[inline]
-    pub fn new_free<T: Slice>(channel: impl Peripheral<P = T> + 'd, config: Config) -> Self {
-        Self::new_inner(channel.number(), None, None, Pull::None, config, Divmode::DIV)
+    pub fn new_free<T: Slice>(slice: impl Peripheral<P = T> + 'd, config: Config) -> Self {
+        into_ref!(slice);
+        Self::new_inner(slice.number(), None, None, Pull::None, config, Divmode::DIV)
     }
 
     /// Create PWM driver with a single 'a' as output.
     #[inline]
     pub fn new_output_a<T: Slice>(
-        channel: impl Peripheral<P = T> + 'd,
+        slice: impl Peripheral<P = T> + 'd,
         a: impl Peripheral<P = impl ChannelAPin<T>> + 'd,
         config: Config,
     ) -> Self {
-        into_ref!(a);
+        into_ref!(slice, a);
         Self::new_inner(
-            channel.number(),
+            slice.number(),
             Some(a.map_into()),
             None,
             Pull::None,
@@ -149,13 +150,13 @@ impl<'d> Pwm<'d> {
     /// Create PWM driver with a single 'b' pin as output.
     #[inline]
     pub fn new_output_b<T: Slice>(
-        channel: impl Peripheral<P = T> + 'd,
+        slice: impl Peripheral<P = T> + 'd,
         b: impl Peripheral<P = impl ChannelBPin<T>> + 'd,
         config: Config,
     ) -> Self {
-        into_ref!(b);
+        into_ref!(slice, b);
         Self::new_inner(
-            channel.number(),
+            slice.number(),
             None,
             Some(b.map_into()),
             Pull::None,
@@ -167,14 +168,14 @@ impl<'d> Pwm<'d> {
     /// Create PWM driver with a 'a' and 'b' pins as output.
     #[inline]
     pub fn new_output_ab<T: Slice>(
-        channel: impl Peripheral<P = T> + 'd,
+        slice: impl Peripheral<P = T> + 'd,
         a: impl Peripheral<P = impl ChannelAPin<T>> + 'd,
         b: impl Peripheral<P = impl ChannelBPin<T>> + 'd,
         config: Config,
     ) -> Self {
-        into_ref!(a, b);
+        into_ref!(slice, a, b);
         Self::new_inner(
-            channel.number(),
+            slice.number(),
             Some(a.map_into()),
             Some(b.map_into()),
             Pull::None,
@@ -186,29 +187,29 @@ impl<'d> Pwm<'d> {
     /// Create PWM driver with a single 'b' as input pin.
     #[inline]
     pub fn new_input<T: Slice>(
-        channel: impl Peripheral<P = T> + 'd,
+        slice: impl Peripheral<P = T> + 'd,
         b: impl Peripheral<P = impl ChannelBPin<T>> + 'd,
         b_pull: Pull,
         mode: InputMode,
         config: Config,
     ) -> Self {
-        into_ref!(b);
-        Self::new_inner(channel.number(), None, Some(b.map_into()), b_pull, config, mode.into())
+        into_ref!(slice, b);
+        Self::new_inner(slice.number(), None, Some(b.map_into()), b_pull, config, mode.into())
     }
 
     /// Create PWM driver with a 'a' and 'b' pins in the desired input mode.
     #[inline]
     pub fn new_output_input<T: Slice>(
-        channel: impl Peripheral<P = T> + 'd,
+        slice: impl Peripheral<P = T> + 'd,
         a: impl Peripheral<P = impl ChannelAPin<T>> + 'd,
         b: impl Peripheral<P = impl ChannelBPin<T>> + 'd,
         b_pull: Pull,
         mode: InputMode,
         config: Config,
     ) -> Self {
-        into_ref!(a, b);
+        into_ref!(slice, a, b);
         Self::new_inner(
-            channel.number(),
+            slice.number(),
             Some(a.map_into()),
             Some(b.map_into()),
             b_pull,
@@ -219,7 +220,7 @@ impl<'d> Pwm<'d> {
 
     /// Set the PWM config.
     pub fn set_config(&mut self, config: &Config) {
-        Self::configure(pac::PWM.ch(self.channel), config);
+        Self::configure(pac::PWM.ch(self.slice), config);
     }
 
     fn configure(p: pac::pwm::Channel, config: &Config) {
@@ -246,7 +247,7 @@ impl<'d> Pwm<'d> {
     /// will not count faster than once per cycle.
     #[inline]
     pub fn phase_advance(&mut self) {
-        let p = pac::PWM.ch(self.channel);
+        let p = pac::PWM.ch(self.slice);
         p.csr().write_set(|w| w.set_ph_adv(true));
         while p.csr().read().ph_adv() {}
     }
@@ -256,7 +257,7 @@ impl<'d> Pwm<'d> {
     /// count backward when clock enable is permanently low.
     #[inline]
     pub fn phase_retard(&mut self) {
-        let p = pac::PWM.ch(self.channel);
+        let p = pac::PWM.ch(self.slice);
         p.csr().write_set(|w| w.set_ph_ret(true));
         while p.csr().read().ph_ret() {}
     }
@@ -264,13 +265,13 @@ impl<'d> Pwm<'d> {
     /// Read PWM counter.
     #[inline]
     pub fn counter(&self) -> u16 {
-        pac::PWM.ch(self.channel).ctr().read().ctr()
+        pac::PWM.ch(self.slice).ctr().read().ctr()
     }
 
     /// Write PWM counter.
     #[inline]
     pub fn set_counter(&self, ctr: u16) {
-        pac::PWM.ch(self.channel).ctr().write(|w| w.set_ctr(ctr))
+        pac::PWM.ch(self.slice).ctr().write(|w| w.set_ctr(ctr))
     }
 
     /// Wait for channel interrupt.
@@ -294,7 +295,7 @@ impl<'d> Pwm<'d> {
 
     #[inline]
     fn bit(&self) -> u32 {
-        1 << self.channel as usize
+        1 << self.slice as usize
     }
 }
 
@@ -323,7 +324,7 @@ impl PwmBatch {
 
 impl<'d> Drop for Pwm<'d> {
     fn drop(&mut self) {
-        pac::PWM.ch(self.channel).csr().write_clear(|w| w.set_en(false));
+        pac::PWM.ch(self.slice).csr().write_clear(|w| w.set_en(false));
         if let Some(pin) = &self.pin_a {
             pin.gpio().ctrl().write(|w| w.set_funcsel(31));
         }
@@ -339,14 +340,14 @@ trait SealedSlice {}
 #[allow(private_bounds)]
 pub trait Slice: Peripheral<P = Self> + SealedSlice + Sized + 'static {
     /// Slice number.
-    fn number(&self) -> u8;
+    fn number(&self) -> usize;
 }
 
 macro_rules! slice {
     ($name:ident, $num:expr) => {
         impl SealedSlice for peripherals::$name {}
         impl Slice for peripherals::$name {
-            fn number(&self) -> u8 {
+            fn number(&self) -> usize {
                 $num
             }
         }
diff --git a/examples/rp/src/bin/interrupt.rs b/examples/rp/src/bin/interrupt.rs
index d334d35d7..5b9d7027e 100644
--- a/examples/rp/src/bin/interrupt.rs
+++ b/examples/rp/src/bin/interrupt.rs
@@ -15,7 +15,6 @@ use embassy_executor::Spawner;
 use embassy_rp::adc::{self, Adc, Blocking};
 use embassy_rp::gpio::Pull;
 use embassy_rp::interrupt;
-use embassy_rp::peripherals::PWM_SLICE4;
 use embassy_rp::pwm::{Config, Pwm};
 use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
 use embassy_sync::blocking_mutex::Mutex;
@@ -26,7 +25,7 @@ use static_cell::StaticCell;
 use {defmt_rtt as _, panic_probe as _};
 
 static COUNTER: AtomicU32 = AtomicU32::new(0);
-static PWM: Mutex<CriticalSectionRawMutex, RefCell<Option<Pwm<PWM_SLICE4>>>> = Mutex::new(RefCell::new(None));
+static PWM: Mutex<CriticalSectionRawMutex, RefCell<Option<Pwm>>> = Mutex::new(RefCell::new(None));
 static ADC: Mutex<CriticalSectionRawMutex, RefCell<Option<(Adc<Blocking>, adc::Channel)>>> =
     Mutex::new(RefCell::new(None));
 static ADC_VALUES: Channel<CriticalSectionRawMutex, u16, 2048> = Channel::new();

From 3b0102363632d72f31e276bf4a8606706fa0b5fc Mon Sep 17 00:00:00 2001
From: Dario Nieuwenhuis <dirbaio@dirbaio.net>
Date: Tue, 21 May 2024 23:45:01 +0200
Subject: [PATCH 6/6] Remove "cargo install probe-rs", point users to probe.rs
 instead.

Fixes #2965
---
 README.md       | 7 +------
 cyw43/README.md | 2 +-
 2 files changed, 2 insertions(+), 7 deletions(-)

diff --git a/README.md b/README.md
index ffc7899d7..65ccaa967 100644
--- a/README.md
+++ b/README.md
@@ -100,12 +100,7 @@ Examples are found in the `examples/` folder separated by the chip manufacturer
 
 ### Running examples
 
-- Install `probe-rs`.
-
-```bash
-cargo install probe-rs --features cli
-```
-
+- Install `probe-rs` following the instructions at <https://probe.rs>.
 - Change directory to the sample's base directory. For example:
 
 ```bash
diff --git a/cyw43/README.md b/cyw43/README.md
index dabdf0471..5b4a5d789 100644
--- a/cyw43/README.md
+++ b/cyw43/README.md
@@ -23,7 +23,7 @@ TODO:
 
 ## Running the examples
 
-- `cargo install probe-rs --features cli`
+- Install `probe-rs` following the instructions at <https://probe.rs>.
 - `cd examples/rp`
 ### Example 1: Scan the wifi stations
 - `cargo run --release --bin wifi_scan`