From ca2eef5387b521a0ea95f26bae530d9bdfbba4d7 Mon Sep 17 00:00:00 2001
From: Dario Nieuwenhuis <dirbaio@dirbaio.net>
Date: Thu, 18 Apr 2024 19:08:24 +0200
Subject: [PATCH] stm32/spi: remove peripheral generic param.

---
 embassy-stm32/src/i2s.rs                      |  14 +-
 embassy-stm32/src/macros.rs                   |  25 ++
 embassy-stm32/src/spi/mod.rs                  | 237 +++++++++---------
 examples/stm32h7/src/bin/spi.rs               |   3 +-
 examples/stm32h7/src/bin/spi_bdma.rs          |   4 +-
 examples/stm32h7/src/bin/spi_dma.rs           |   4 +-
 examples/stm32h7rs/src/bin/spi.rs             |   3 +-
 examples/stm32h7rs/src/bin/spi_dma.rs         |   4 +-
 .../src/bin/spe_adin1110_http_server.rs       |   2 +-
 9 files changed, 161 insertions(+), 135 deletions(-)

diff --git a/embassy-stm32/src/i2s.rs b/embassy-stm32/src/i2s.rs
index 9b80dc1d0..c102c0035 100644
--- a/embassy-stm32/src/i2s.rs
+++ b/embassy-stm32/src/i2s.rs
@@ -153,17 +153,17 @@ impl Default for Config {
 }
 
 /// I2S driver.
-pub struct I2S<'d, T: Instance> {
-    _peri: Spi<'d, T, Async>,
+pub struct I2S<'d> {
+    _peri: Spi<'d, Async>,
     sd: Option<PeripheralRef<'d, AnyPin>>,
     ws: Option<PeripheralRef<'d, AnyPin>>,
     ck: Option<PeripheralRef<'d, AnyPin>>,
     mck: Option<PeripheralRef<'d, AnyPin>>,
 }
 
-impl<'d, T: Instance> I2S<'d, T> {
+impl<'d> I2S<'d> {
     /// Note: Full-Duplex modes are not supported at this time
-    pub fn new(
+    pub fn new<T: Instance>(
         peri: impl Peripheral<P = T> + 'd,
         sd: impl Peripheral<P = impl MosiPin<T>> + 'd,
         ws: impl Peripheral<P = impl WsPin<T>> + 'd,
@@ -208,7 +208,7 @@ impl<'d, T: Instance> I2S<'d, T> {
             // rate to reach the proper audio sample frequency. The ODD bit in the SPI_I2SPR
             // register also has to be defined.
 
-            T::REGS.i2spr().modify(|w| {
+            spi.regs.i2spr().modify(|w| {
                 w.set_i2sdiv(div);
                 w.set_odd(match odd {
                     true => Odd::ODD,
@@ -235,7 +235,7 @@ impl<'d, T: Instance> I2S<'d, T> {
 
             // 5. The I2SE bit in SPI_I2SCFGR register must be set.
 
-            T::REGS.i2scfgr().modify(|w| {
+            spi.regs.i2scfgr().modify(|w| {
                 w.set_ckpol(config.clock_polarity.ckpol());
 
                 w.set_i2smod(true);
@@ -276,7 +276,7 @@ impl<'d, T: Instance> I2S<'d, T> {
     }
 }
 
-impl<'d, T: Instance> Drop for I2S<'d, T> {
+impl<'d> Drop for I2S<'d> {
     fn drop(&mut self) {
         self.sd.as_ref().map(|x| x.set_as_disconnected());
         self.ws.as_ref().map(|x| x.set_as_disconnected());
diff --git a/embassy-stm32/src/macros.rs b/embassy-stm32/src/macros.rs
index 02dce1266..9c459a932 100644
--- a/embassy-stm32/src/macros.rs
+++ b/embassy-stm32/src/macros.rs
@@ -1,5 +1,30 @@
 #![macro_use]
 
+macro_rules! peri_trait {
+    () => {
+        #[allow(private_interfaces)]
+        pub(crate) trait SealedInstance {
+            const INFO: Info;
+            const STATE: &'static State;
+        }
+
+        /// SPI instance trait.
+        #[allow(private_bounds)]
+        pub trait Instance: Peripheral<P = Self> + SealedInstance + RccPeripheral {}
+    };
+}
+
+macro_rules! peri_trait_impl {
+    ($instance:ident, $info:expr) => {
+        #[allow(private_interfaces)]
+        impl SealedInstance for crate::peripherals::$instance {
+            const INFO: Info = $info;
+            const STATE: &'static State = &State::new();
+        }
+        impl Instance for crate::peripherals::$instance {}
+    };
+}
+
 macro_rules! pin_trait {
     ($signal:ident, $instance:path $(, $mode:path)?) => {
         #[doc = concat!(stringify!($signal), " pin trait")]
diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs
index c39ef1913..5a2ee105d 100644
--- a/embassy-stm32/src/spi/mod.rs
+++ b/embassy-stm32/src/spi/mod.rs
@@ -6,16 +6,16 @@ use core::ptr;
 
 use embassy_embedded_hal::SetConfig;
 use embassy_futures::join::join;
-use embassy_hal_internal::{into_ref, PeripheralRef};
+use embassy_hal_internal::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, ChannelAndRequest};
 use crate::gpio::{AFType, AnyPin, Pull, SealedPin as _, Speed};
 use crate::mode::{Async, Blocking, Mode as PeriMode};
 use crate::pac::spi::{regs, vals, Spi as Regs};
-use crate::rcc::RccPeripheral;
+use crate::rcc::{ClockEnableBit, RccPeripheral};
 use crate::time::Hertz;
-use crate::{peripherals, Peripheral};
+use crate::Peripheral;
 
 /// SPI error.
 #[derive(Debug, PartialEq, Eq)]
@@ -92,8 +92,10 @@ impl Config {
     }
 }
 /// SPI driver.
-pub struct Spi<'d, T: Instance, M: PeriMode> {
-    _peri: PeripheralRef<'d, T>,
+pub struct Spi<'d, M: PeriMode> {
+    pub(crate) regs: Regs,
+    enable_bit: ClockEnableBit,
+    kernel_clock: Hertz,
     sck: Option<PeripheralRef<'d, AnyPin>>,
     mosi: Option<PeripheralRef<'d, AnyPin>>,
     miso: Option<PeripheralRef<'d, AnyPin>>,
@@ -103,9 +105,9 @@ pub struct Spi<'d, T: Instance, M: PeriMode> {
     current_word_size: word_impl::Config,
 }
 
-impl<'d, T: Instance, M: PeriMode> Spi<'d, T, M> {
-    fn new_inner(
-        peri: impl Peripheral<P = T> + 'd,
+impl<'d, M: PeriMode> Spi<'d, M> {
+    fn new_inner<T: Instance>(
+        _peri: impl Peripheral<P = T> + 'd,
         sck: Option<PeripheralRef<'d, AnyPin>>,
         mosi: Option<PeripheralRef<'d, AnyPin>>,
         miso: Option<PeripheralRef<'d, AnyPin>>,
@@ -113,11 +115,9 @@ impl<'d, T: Instance, M: PeriMode> Spi<'d, T, M> {
         rx_dma: Option<ChannelAndRequest<'d>>,
         config: Config,
     ) -> Self {
-        into_ref!(peri);
-
-        let pclk = T::frequency();
-        let freq = config.frequency;
-        let br = compute_baud_rate(pclk, freq);
+        let regs = T::INFO.regs;
+        let kernel_clock = T::frequency();
+        let br = compute_baud_rate(kernel_clock, config.frequency);
 
         let cpha = config.raw_phase();
         let cpol = config.raw_polarity();
@@ -128,10 +128,10 @@ impl<'d, T: Instance, M: PeriMode> Spi<'d, T, M> {
 
         #[cfg(any(spi_v1, spi_f1))]
         {
-            T::REGS.cr2().modify(|w| {
+            regs.cr2().modify(|w| {
                 w.set_ssoe(false);
             });
-            T::REGS.cr1().modify(|w| {
+            regs.cr1().modify(|w| {
                 w.set_cpha(cpha);
                 w.set_cpol(cpol);
 
@@ -151,13 +151,13 @@ impl<'d, T: Instance, M: PeriMode> Spi<'d, T, M> {
         }
         #[cfg(spi_v2)]
         {
-            T::REGS.cr2().modify(|w| {
+            regs.cr2().modify(|w| {
                 let (ds, frxth) = <u8 as SealedWord>::CONFIG;
                 w.set_frxth(frxth);
                 w.set_ds(ds);
                 w.set_ssoe(false);
             });
-            T::REGS.cr1().modify(|w| {
+            regs.cr1().modify(|w| {
                 w.set_cpha(cpha);
                 w.set_cpol(cpol);
 
@@ -173,8 +173,8 @@ impl<'d, T: Instance, M: PeriMode> Spi<'d, T, M> {
         }
         #[cfg(any(spi_v3, spi_v4, spi_v5))]
         {
-            T::REGS.ifcr().write(|w| w.0 = 0xffff_ffff);
-            T::REGS.cfg2().modify(|w| {
+            regs.ifcr().write(|w| w.0 = 0xffff_ffff);
+            regs.cfg2().modify(|w| {
                 //w.set_ssoe(true);
                 w.set_ssoe(false);
                 w.set_cpha(cpha);
@@ -189,23 +189,25 @@ impl<'d, T: Instance, M: PeriMode> Spi<'d, T, M> {
                 w.set_afcntr(true);
                 w.set_ssiop(vals::Ssiop::ACTIVEHIGH);
             });
-            T::REGS.cfg1().modify(|w| {
+            regs.cfg1().modify(|w| {
                 w.set_crcen(false);
                 w.set_mbr(br);
                 w.set_dsize(<u8 as SealedWord>::CONFIG);
                 w.set_fthlv(vals::Fthlv::ONEFRAME);
             });
-            T::REGS.cr2().modify(|w| {
+            regs.cr2().modify(|w| {
                 w.set_tsize(0);
             });
-            T::REGS.cr1().modify(|w| {
+            regs.cr1().modify(|w| {
                 w.set_ssi(false);
                 w.set_spe(true);
             });
         }
 
         Self {
-            _peri: peri,
+            regs,
+            enable_bit: T::enable_bit(),
+            kernel_clock,
             sck,
             mosi,
             miso,
@@ -223,12 +225,10 @@ impl<'d, T: Instance, M: PeriMode> Spi<'d, T, M> {
 
         let lsbfirst = config.raw_byte_order();
 
-        let pclk = T::frequency();
-        let freq = config.frequency;
-        let br = compute_baud_rate(pclk, freq);
+        let br = compute_baud_rate(self.kernel_clock, config.frequency);
 
         #[cfg(any(spi_v1, spi_f1, spi_v2))]
-        T::REGS.cr1().modify(|w| {
+        self.regs.cr1().modify(|w| {
             w.set_cpha(cpha);
             w.set_cpol(cpol);
             w.set_br(br);
@@ -237,12 +237,12 @@ impl<'d, T: Instance, M: PeriMode> Spi<'d, T, M> {
 
         #[cfg(any(spi_v3, spi_v4, spi_v5))]
         {
-            T::REGS.cfg2().modify(|w| {
+            self.regs.cfg2().modify(|w| {
                 w.set_cpha(cpha);
                 w.set_cpol(cpol);
                 w.set_lsbfirst(lsbfirst);
             });
-            T::REGS.cfg1().modify(|w| {
+            self.regs.cfg1().modify(|w| {
                 w.set_mbr(br);
             });
         }
@@ -252,11 +252,11 @@ impl<'d, T: Instance, M: PeriMode> Spi<'d, T, M> {
     /// Get current SPI configuration.
     pub fn get_current_config(&self) -> Config {
         #[cfg(any(spi_v1, spi_f1, spi_v2))]
-        let cfg = T::REGS.cr1().read();
+        let cfg = self.regs.cr1().read();
         #[cfg(any(spi_v3, spi_v4, spi_v5))]
-        let cfg = T::REGS.cfg2().read();
+        let cfg = self.regs.cfg2().read();
         #[cfg(any(spi_v3, spi_v4, spi_v5))]
-        let cfg1 = T::REGS.cfg1().read();
+        let cfg1 = self.regs.cfg1().read();
 
         let polarity = if cfg.cpol() == vals::Cpol::IDLELOW {
             Polarity::IdleLow
@@ -280,8 +280,7 @@ impl<'d, T: Instance, M: PeriMode> Spi<'d, T, M> {
         #[cfg(any(spi_v3, spi_v4, spi_v5))]
         let br = cfg1.mbr();
 
-        let pclk = T::frequency();
-        let frequency = compute_frequency(pclk, br);
+        let frequency = compute_frequency(self.kernel_clock, br);
 
         Config {
             mode: Mode { polarity, phase },
@@ -297,40 +296,40 @@ impl<'d, T: Instance, M: PeriMode> Spi<'d, T, M> {
 
         #[cfg(any(spi_v1, spi_f1))]
         {
-            T::REGS.cr1().modify(|reg| {
+            self.regs.cr1().modify(|reg| {
                 reg.set_spe(false);
                 reg.set_dff(word_size)
             });
-            T::REGS.cr1().modify(|reg| {
+            self.regs.cr1().modify(|reg| {
                 reg.set_spe(true);
             });
         }
         #[cfg(spi_v2)]
         {
-            T::REGS.cr1().modify(|w| {
+            self.regs.cr1().modify(|w| {
                 w.set_spe(false);
             });
-            T::REGS.cr2().modify(|w| {
+            self.regs.cr2().modify(|w| {
                 w.set_frxth(word_size.1);
                 w.set_ds(word_size.0);
             });
-            T::REGS.cr1().modify(|w| {
+            self.regs.cr1().modify(|w| {
                 w.set_spe(true);
             });
         }
         #[cfg(any(spi_v3, spi_v4, spi_v5))]
         {
-            T::REGS.cr1().modify(|w| {
+            self.regs.cr1().modify(|w| {
                 w.set_csusp(true);
             });
-            while T::REGS.sr().read().eot() {}
-            T::REGS.cr1().modify(|w| {
+            while self.regs.sr().read().eot() {}
+            self.regs.cr1().modify(|w| {
                 w.set_spe(false);
             });
-            T::REGS.cfg1().modify(|w| {
+            self.regs.cfg1().modify(|w| {
                 w.set_dsize(word_size);
             });
-            T::REGS.cr1().modify(|w| {
+            self.regs.cr1().modify(|w| {
                 w.set_csusp(false);
                 w.set_spe(true);
             });
@@ -341,22 +340,22 @@ impl<'d, T: Instance, M: PeriMode> Spi<'d, T, M> {
 
     /// Blocking write.
     pub fn blocking_write<W: Word>(&mut self, words: &[W]) -> Result<(), Error> {
-        T::REGS.cr1().modify(|w| w.set_spe(true));
-        flush_rx_fifo(T::REGS);
+        self.regs.cr1().modify(|w| w.set_spe(true));
+        flush_rx_fifo(self.regs);
         self.set_word_size(W::CONFIG);
         for word in words.iter() {
-            let _ = transfer_word(T::REGS, *word)?;
+            let _ = transfer_word(self.regs, *word)?;
         }
         Ok(())
     }
 
     /// Blocking read.
     pub fn blocking_read<W: Word>(&mut self, words: &mut [W]) -> Result<(), Error> {
-        T::REGS.cr1().modify(|w| w.set_spe(true));
-        flush_rx_fifo(T::REGS);
+        self.regs.cr1().modify(|w| w.set_spe(true));
+        flush_rx_fifo(self.regs);
         self.set_word_size(W::CONFIG);
         for word in words.iter_mut() {
-            *word = transfer_word(T::REGS, W::default())?;
+            *word = transfer_word(self.regs, W::default())?;
         }
         Ok(())
     }
@@ -365,11 +364,11 @@ impl<'d, T: Instance, M: PeriMode> Spi<'d, T, M> {
     ///
     /// This writes the contents of `data` on MOSI, and puts the received data on MISO in `data`, at the same time.
     pub fn blocking_transfer_in_place<W: Word>(&mut self, words: &mut [W]) -> Result<(), Error> {
-        T::REGS.cr1().modify(|w| w.set_spe(true));
-        flush_rx_fifo(T::REGS);
+        self.regs.cr1().modify(|w| w.set_spe(true));
+        flush_rx_fifo(self.regs);
         self.set_word_size(W::CONFIG);
         for word in words.iter_mut() {
-            *word = transfer_word(T::REGS, *word)?;
+            *word = transfer_word(self.regs, *word)?;
         }
         Ok(())
     }
@@ -381,13 +380,13 @@ impl<'d, T: Instance, M: PeriMode> Spi<'d, T, M> {
     /// The transfer runs for `max(read.len(), write.len())` bytes. If `read` is shorter extra bytes are ignored.
     /// If `write` is shorter it is padded with zero bytes.
     pub fn blocking_transfer<W: Word>(&mut self, read: &mut [W], write: &[W]) -> Result<(), Error> {
-        T::REGS.cr1().modify(|w| w.set_spe(true));
-        flush_rx_fifo(T::REGS);
+        self.regs.cr1().modify(|w| w.set_spe(true));
+        flush_rx_fifo(self.regs);
         self.set_word_size(W::CONFIG);
         let len = read.len().max(write.len());
         for i in 0..len {
             let wb = write.get(i).copied().unwrap_or_default();
-            let rb = transfer_word(T::REGS, wb)?;
+            let rb = transfer_word(self.regs, wb)?;
             if let Some(r) = read.get_mut(i) {
                 *r = rb;
             }
@@ -396,9 +395,9 @@ impl<'d, T: Instance, M: PeriMode> Spi<'d, T, M> {
     }
 }
 
-impl<'d, T: Instance> Spi<'d, T, Blocking> {
+impl<'d> Spi<'d, Blocking> {
     /// Create a new blocking SPI driver.
-    pub fn new_blocking(
+    pub fn new_blocking<T: Instance>(
         peri: impl Peripheral<P = T> + 'd,
         sck: impl Peripheral<P = impl SckPin<T>> + 'd,
         mosi: impl Peripheral<P = impl MosiPin<T>> + 'd,
@@ -417,7 +416,7 @@ impl<'d, T: Instance> Spi<'d, T, Blocking> {
     }
 
     /// Create a new blocking SPI driver, in RX-only mode (only MISO pin, no MOSI).
-    pub fn new_blocking_rxonly(
+    pub fn new_blocking_rxonly<T: Instance>(
         peri: impl Peripheral<P = T> + 'd,
         sck: impl Peripheral<P = impl SckPin<T>> + 'd,
         miso: impl Peripheral<P = impl MisoPin<T>> + 'd,
@@ -435,7 +434,7 @@ impl<'d, T: Instance> Spi<'d, T, Blocking> {
     }
 
     /// Create a new blocking SPI driver, in TX-only mode (only MOSI pin, no MISO).
-    pub fn new_blocking_txonly(
+    pub fn new_blocking_txonly<T: Instance>(
         peri: impl Peripheral<P = T> + 'd,
         sck: impl Peripheral<P = impl SckPin<T>> + 'd,
         mosi: impl Peripheral<P = impl MosiPin<T>> + 'd,
@@ -455,7 +454,7 @@ impl<'d, T: Instance> Spi<'d, T, Blocking> {
     /// Create a new SPI driver, in TX-only mode, without SCK pin.
     ///
     /// This can be useful for bit-banging non-SPI protocols.
-    pub fn new_blocking_txonly_nosck(
+    pub fn new_blocking_txonly_nosck<T: Instance>(
         peri: impl Peripheral<P = T> + 'd,
         mosi: impl Peripheral<P = impl MosiPin<T>> + 'd,
         config: Config,
@@ -472,9 +471,9 @@ impl<'d, T: Instance> Spi<'d, T, Blocking> {
     }
 }
 
-impl<'d, T: Instance> Spi<'d, T, Async> {
+impl<'d> Spi<'d, Async> {
     /// Create a new SPI driver.
-    pub fn new(
+    pub fn new<T: Instance>(
         peri: impl Peripheral<P = T> + 'd,
         sck: impl Peripheral<P = impl SckPin<T>> + 'd,
         mosi: impl Peripheral<P = impl MosiPin<T>> + 'd,
@@ -495,7 +494,7 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
     }
 
     /// Create a new SPI driver, in RX-only mode (only MISO pin, no MOSI).
-    pub fn new_rxonly(
+    pub fn new_rxonly<T: Instance>(
         peri: impl Peripheral<P = T> + 'd,
         sck: impl Peripheral<P = impl SckPin<T>> + 'd,
         miso: impl Peripheral<P = impl MisoPin<T>> + 'd,
@@ -514,7 +513,7 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
     }
 
     /// Create a new SPI driver, in TX-only mode (only MOSI pin, no MISO).
-    pub fn new_txonly(
+    pub fn new_txonly<T: Instance>(
         peri: impl Peripheral<P = T> + 'd,
         sck: impl Peripheral<P = impl SckPin<T>> + 'd,
         mosi: impl Peripheral<P = impl MosiPin<T>> + 'd,
@@ -535,7 +534,7 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
     /// Create a new SPI driver, in TX-only mode, without SCK pin.
     ///
     /// This can be useful for bit-banging non-SPI protocols.
-    pub fn new_txonly_nosck(
+    pub fn new_txonly_nosck<T: Instance>(
         peri: impl Peripheral<P = T> + 'd,
         mosi: impl Peripheral<P = impl MosiPin<T>> + 'd,
         tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd,
@@ -554,7 +553,7 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
 
     #[cfg(stm32wl)]
     /// Useful for on chip peripherals like SUBGHZ which are hardwired.
-    pub fn new_subghz(
+    pub fn new_subghz<T: Instance>(
         peri: impl Peripheral<P = T> + 'd,
         tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd,
         rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd,
@@ -562,7 +561,7 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
         // see RM0453 rev 1 section 7.2.13 page 291
         // The SUBGHZSPI_SCK frequency is obtained by PCLK3 divided by two.
         // The SUBGHZSPI_SCK clock maximum speed must not exceed 16 MHz.
-        let pclk3_freq = <peripherals::SUBGHZSPI as crate::rcc::SealedRccPeripheral>::frequency().0;
+        let pclk3_freq = <crate::peripherals::SUBGHZSPI as crate::rcc::SealedRccPeripheral>::frequency().0;
         let freq = Hertz(core::cmp::min(pclk3_freq / 2, 16_000_000));
         let mut config = Config::default();
         config.mode = MODE_0;
@@ -573,7 +572,7 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
     }
 
     #[allow(dead_code)]
-    pub(crate) fn new_internal(
+    pub(crate) fn new_internal<T: Instance>(
         peri: impl Peripheral<P = T> + 'd,
         tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd,
         rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd,
@@ -589,25 +588,25 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
         }
 
         self.set_word_size(W::CONFIG);
-        T::REGS.cr1().modify(|w| {
+        self.regs.cr1().modify(|w| {
             w.set_spe(false);
         });
 
-        let tx_dst = T::REGS.tx_ptr();
+        let tx_dst = self.regs.tx_ptr();
         let tx_f = unsafe { self.tx_dma.as_mut().unwrap().write(data, tx_dst, Default::default()) };
 
-        set_txdmaen(T::REGS, true);
-        T::REGS.cr1().modify(|w| {
+        set_txdmaen(self.regs, true);
+        self.regs.cr1().modify(|w| {
             w.set_spe(true);
         });
         #[cfg(any(spi_v3, spi_v4, spi_v5))]
-        T::REGS.cr1().modify(|w| {
+        self.regs.cr1().modify(|w| {
             w.set_cstart(true);
         });
 
         tx_f.await;
 
-        finish_dma(T::REGS);
+        finish_dma(self.regs);
 
         Ok(())
     }
@@ -619,22 +618,22 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
         }
 
         self.set_word_size(W::CONFIG);
-        T::REGS.cr1().modify(|w| {
+        self.regs.cr1().modify(|w| {
             w.set_spe(false);
         });
 
         // SPIv3 clears rxfifo on SPE=0
         #[cfg(not(any(spi_v3, spi_v4, spi_v5)))]
-        flush_rx_fifo(T::REGS);
+        flush_rx_fifo(self.regs);
 
-        set_rxdmaen(T::REGS, true);
+        set_rxdmaen(self.regs, true);
 
         let clock_byte_count = data.len();
 
-        let rx_src = T::REGS.rx_ptr();
+        let rx_src = self.regs.rx_ptr();
         let rx_f = unsafe { self.rx_dma.as_mut().unwrap().read(rx_src, data, Default::default()) };
 
-        let tx_dst = T::REGS.tx_ptr();
+        let tx_dst = self.regs.tx_ptr();
         let clock_byte = 0x00u8;
         let tx_f = unsafe {
             self.tx_dma
@@ -643,18 +642,18 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
                 .write_repeated(&clock_byte, clock_byte_count, tx_dst, Default::default())
         };
 
-        set_txdmaen(T::REGS, true);
-        T::REGS.cr1().modify(|w| {
+        set_txdmaen(self.regs, true);
+        self.regs.cr1().modify(|w| {
             w.set_spe(true);
         });
         #[cfg(any(spi_v3, spi_v4, spi_v5))]
-        T::REGS.cr1().modify(|w| {
+        self.regs.cr1().modify(|w| {
             w.set_cstart(true);
         });
 
         join(tx_f, rx_f).await;
 
-        finish_dma(T::REGS);
+        finish_dma(self.regs);
 
         Ok(())
     }
@@ -668,20 +667,20 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
         }
 
         self.set_word_size(W::CONFIG);
-        T::REGS.cr1().modify(|w| {
+        self.regs.cr1().modify(|w| {
             w.set_spe(false);
         });
 
         // SPIv3 clears rxfifo on SPE=0
         #[cfg(not(any(spi_v3, spi_v4, spi_v5)))]
-        flush_rx_fifo(T::REGS);
+        flush_rx_fifo(self.regs);
 
-        set_rxdmaen(T::REGS, true);
+        set_rxdmaen(self.regs, true);
 
-        let rx_src = T::REGS.rx_ptr();
+        let rx_src = self.regs.rx_ptr();
         let rx_f = unsafe { self.rx_dma.as_mut().unwrap().read_raw(rx_src, read, Default::default()) };
 
-        let tx_dst = T::REGS.tx_ptr();
+        let tx_dst = self.regs.tx_ptr();
         let tx_f = unsafe {
             self.tx_dma
                 .as_mut()
@@ -689,18 +688,18 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
                 .write_raw(write, tx_dst, Default::default())
         };
 
-        set_txdmaen(T::REGS, true);
-        T::REGS.cr1().modify(|w| {
+        set_txdmaen(self.regs, true);
+        self.regs.cr1().modify(|w| {
             w.set_spe(true);
         });
         #[cfg(any(spi_v3, spi_v4, spi_v5))]
-        T::REGS.cr1().modify(|w| {
+        self.regs.cr1().modify(|w| {
             w.set_cstart(true);
         });
 
         join(tx_f, rx_f).await;
 
-        finish_dma(T::REGS);
+        finish_dma(self.regs);
 
         Ok(())
     }
@@ -723,13 +722,13 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
     }
 }
 
-impl<'d, T: Instance, M: PeriMode> Drop for Spi<'d, T, M> {
+impl<'d, M: PeriMode> Drop for Spi<'d, M> {
     fn drop(&mut self) {
         self.sck.as_ref().map(|x| x.set_as_disconnected());
         self.mosi.as_ref().map(|x| x.set_as_disconnected());
         self.miso.as_ref().map(|x| x.set_as_disconnected());
 
-        T::disable();
+        self.enable_bit.disable();
     }
 }
 
@@ -738,8 +737,8 @@ use vals::Br;
 #[cfg(any(spi_v3, spi_v4, spi_v5))]
 use vals::Mbr as Br;
 
-fn compute_baud_rate(clocks: Hertz, freq: Hertz) -> Br {
-    let val = match clocks.0 / freq.0 {
+fn compute_baud_rate(kernel_clock: Hertz, freq: Hertz) -> Br {
+    let val = match kernel_clock.0 / freq.0 {
         0 => panic!("You are trying to reach a frequency higher than the clock"),
         1..=2 => 0b000,
         3..=5 => 0b001,
@@ -754,7 +753,7 @@ fn compute_baud_rate(clocks: Hertz, freq: Hertz) -> Br {
     Br::from_bits(val)
 }
 
-fn compute_frequency(clocks: Hertz, br: Br) -> Hertz {
+fn compute_frequency(kernel_clock: Hertz, br: Br) -> Hertz {
     let div: u16 = match br {
         Br::DIV2 => 2,
         Br::DIV4 => 4,
@@ -766,7 +765,7 @@ fn compute_frequency(clocks: Hertz, br: Br) -> Hertz {
         Br::DIV256 => 256,
     };
 
-    clocks / div
+    kernel_clock / div
 }
 
 trait RegsExt {
@@ -941,7 +940,7 @@ fn transfer_word<W: Word>(regs: Regs, tx_word: W) -> Result<W, Error> {
 // some marker traits. For details, see https://github.com/rust-embedded/embedded-hal/pull/289
 macro_rules! impl_blocking {
     ($w:ident) => {
-        impl<'d, T: Instance, M: PeriMode> embedded_hal_02::blocking::spi::Write<$w> for Spi<'d, T, M> {
+        impl<'d, M: PeriMode> embedded_hal_02::blocking::spi::Write<$w> for Spi<'d, M> {
             type Error = Error;
 
             fn write(&mut self, words: &[$w]) -> Result<(), Self::Error> {
@@ -949,7 +948,7 @@ macro_rules! impl_blocking {
             }
         }
 
-        impl<'d, T: Instance, M: PeriMode> embedded_hal_02::blocking::spi::Transfer<$w> for Spi<'d, T, M> {
+        impl<'d, M: PeriMode> embedded_hal_02::blocking::spi::Transfer<$w> for Spi<'d, M> {
             type Error = Error;
 
             fn transfer<'w>(&mut self, words: &'w mut [$w]) -> Result<&'w [$w], Self::Error> {
@@ -963,11 +962,11 @@ macro_rules! impl_blocking {
 impl_blocking!(u8);
 impl_blocking!(u16);
 
-impl<'d, T: Instance, M: PeriMode> embedded_hal_1::spi::ErrorType for Spi<'d, T, M> {
+impl<'d, M: PeriMode> embedded_hal_1::spi::ErrorType for Spi<'d, M> {
     type Error = Error;
 }
 
-impl<'d, T: Instance, W: Word, M: PeriMode> embedded_hal_1::spi::SpiBus<W> for Spi<'d, T, M> {
+impl<'d, W: Word, M: PeriMode> embedded_hal_1::spi::SpiBus<W> for Spi<'d, M> {
     fn flush(&mut self) -> Result<(), Self::Error> {
         Ok(())
     }
@@ -1000,7 +999,7 @@ impl embedded_hal_1::spi::Error for Error {
     }
 }
 
-impl<'d, T: Instance, W: Word> embedded_hal_async::spi::SpiBus<W> for Spi<'d, T, Async> {
+impl<'d, W: Word> embedded_hal_async::spi::SpiBus<W> for Spi<'d, Async> {
     async fn flush(&mut self) -> Result<(), Self::Error> {
         Ok(())
     }
@@ -1022,10 +1021,6 @@ impl<'d, T: Instance, W: Word> embedded_hal_async::spi::SpiBus<W> for Spi<'d, T,
     }
 }
 
-pub(crate) trait SealedInstance {
-    const REGS: Regs;
-}
-
 trait SealedWord {
     const CONFIG: word_impl::Config;
 }
@@ -1111,9 +1106,19 @@ mod word_impl {
     impl_word!(u32, 32 - 1);
 }
 
-/// SPI instance trait.
-#[allow(private_bounds)]
-pub trait Instance: Peripheral<P = Self> + SealedInstance + RccPeripheral {}
+struct Info {
+    regs: Regs,
+}
+
+struct State {}
+
+impl State {
+    const fn new() -> Self {
+        Self {}
+    }
+}
+
+peri_trait!();
 
 pin_trait!(SckPin, Instance);
 pin_trait!(MosiPin, Instance);
@@ -1127,15 +1132,13 @@ dma_trait!(TxDma, Instance);
 
 foreach_peripheral!(
     (spi, $inst:ident) => {
-        impl SealedInstance for peripherals::$inst {
-            const REGS: Regs = crate::pac::$inst;
-        }
-
-        impl Instance for peripherals::$inst {}
+        peri_trait_impl!($inst, Info {
+            regs: crate::pac::$inst,
+        });
     };
 );
 
-impl<'d, T: Instance, M: PeriMode> SetConfig for Spi<'d, T, M> {
+impl<'d, M: PeriMode> SetConfig for Spi<'d, M> {
     type Config = Config;
     type ConfigError = ();
     fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> {
diff --git a/examples/stm32h7/src/bin/spi.rs b/examples/stm32h7/src/bin/spi.rs
index aaebdc346..ad4a8aaf7 100644
--- a/examples/stm32h7/src/bin/spi.rs
+++ b/examples/stm32h7/src/bin/spi.rs
@@ -8,7 +8,6 @@ use cortex_m_rt::entry;
 use defmt::*;
 use embassy_executor::Executor;
 use embassy_stm32::mode::Blocking;
-use embassy_stm32::peripherals::SPI3;
 use embassy_stm32::time::mhz;
 use embassy_stm32::{spi, Config};
 use heapless::String;
@@ -16,7 +15,7 @@ use static_cell::StaticCell;
 use {defmt_rtt as _, panic_probe as _};
 
 #[embassy_executor::task]
-async fn main_task(mut spi: spi::Spi<'static, SPI3, Blocking>) {
+async fn main_task(mut spi: spi::Spi<'static, Blocking>) {
     for n in 0u32.. {
         let mut write: String<128> = String::new();
         core::write!(&mut write, "Hello DMA World {}!\r\n", n).unwrap();
diff --git a/examples/stm32h7/src/bin/spi_bdma.rs b/examples/stm32h7/src/bin/spi_bdma.rs
index f968df4a7..b2e941078 100644
--- a/examples/stm32h7/src/bin/spi_bdma.rs
+++ b/examples/stm32h7/src/bin/spi_bdma.rs
@@ -9,7 +9,7 @@ use defmt::*;
 use embassy_executor::Executor;
 use embassy_stm32::mode::Async;
 use embassy_stm32::time::mhz;
-use embassy_stm32::{peripherals, spi, Config};
+use embassy_stm32::{spi, Config};
 use heapless::String;
 use static_cell::StaticCell;
 use {defmt_rtt as _, panic_probe as _};
@@ -19,7 +19,7 @@ use {defmt_rtt as _, panic_probe as _};
 static mut RAM_D3: [u8; 64 * 1024] = [0u8; 64 * 1024];
 
 #[embassy_executor::task]
-async fn main_task(mut spi: spi::Spi<'static, peripherals::SPI6, Async>) {
+async fn main_task(mut spi: spi::Spi<'static, Async>) {
     let read_buffer = unsafe { &mut RAM_D3[0..128] };
     let write_buffer = unsafe { &mut RAM_D3[128..256] };
 
diff --git a/examples/stm32h7/src/bin/spi_dma.rs b/examples/stm32h7/src/bin/spi_dma.rs
index 3d3c724eb..731c7fef5 100644
--- a/examples/stm32h7/src/bin/spi_dma.rs
+++ b/examples/stm32h7/src/bin/spi_dma.rs
@@ -9,13 +9,13 @@ use defmt::*;
 use embassy_executor::Executor;
 use embassy_stm32::mode::Async;
 use embassy_stm32::time::mhz;
-use embassy_stm32::{peripherals, spi, Config};
+use embassy_stm32::{spi, Config};
 use heapless::String;
 use static_cell::StaticCell;
 use {defmt_rtt as _, panic_probe as _};
 
 #[embassy_executor::task]
-async fn main_task(mut spi: spi::Spi<'static, peripherals::SPI3, Async>) {
+async fn main_task(mut spi: spi::Spi<'static, Async>) {
     for n in 0u32.. {
         let mut write: String<128> = String::new();
         let mut read = [0; 128];
diff --git a/examples/stm32h7rs/src/bin/spi.rs b/examples/stm32h7rs/src/bin/spi.rs
index a7767876d..8d6ccc58b 100644
--- a/examples/stm32h7rs/src/bin/spi.rs
+++ b/examples/stm32h7rs/src/bin/spi.rs
@@ -8,7 +8,6 @@ use cortex_m_rt::entry;
 use defmt::*;
 use embassy_executor::Executor;
 use embassy_stm32::mode::Blocking;
-use embassy_stm32::peripherals::SPI3;
 use embassy_stm32::spi;
 use embassy_stm32::time::mhz;
 use heapless::String;
@@ -16,7 +15,7 @@ use static_cell::StaticCell;
 use {defmt_rtt as _, panic_probe as _};
 
 #[embassy_executor::task]
-async fn main_task(mut spi: spi::Spi<'static, SPI3, Blocking>) {
+async fn main_task(mut spi: spi::Spi<'static, Blocking>) {
     for n in 0u32.. {
         let mut write: String<128> = String::new();
         core::write!(&mut write, "Hello DMA World {}!\r\n", n).unwrap();
diff --git a/examples/stm32h7rs/src/bin/spi_dma.rs b/examples/stm32h7rs/src/bin/spi_dma.rs
index 26b5d6751..cb305351b 100644
--- a/examples/stm32h7rs/src/bin/spi_dma.rs
+++ b/examples/stm32h7rs/src/bin/spi_dma.rs
@@ -8,14 +8,14 @@ use cortex_m_rt::entry;
 use defmt::*;
 use embassy_executor::Executor;
 use embassy_stm32::mode::Async;
+use embassy_stm32::spi;
 use embassy_stm32::time::mhz;
-use embassy_stm32::{peripherals, spi};
 use heapless::String;
 use static_cell::StaticCell;
 use {defmt_rtt as _, panic_probe as _};
 
 #[embassy_executor::task]
-async fn main_task(mut spi: spi::Spi<'static, peripherals::SPI3, Async>) {
+async fn main_task(mut spi: spi::Spi<'static, Async>) {
     for n in 0u32.. {
         let mut write: String<128> = String::new();
         let mut read = [0; 128];
diff --git a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs
index 694629ede..985ac8171 100644
--- a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs
+++ b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs
@@ -55,7 +55,7 @@ const IP_ADDRESS: Ipv4Cidr = Ipv4Cidr::new(Ipv4Address([192, 168, 1, 5]), 24);
 // Listen port for the webserver
 const HTTP_LISTEN_PORT: u16 = 80;
 
-pub type SpeSpi = Spi<'static, peripherals::SPI2, Async>;
+pub type SpeSpi = Spi<'static, Async>;
 pub type SpeSpiCs = ExclusiveDevice<SpeSpi, Output<'static>, Delay>;
 pub type SpeInt = exti::ExtiInput<'static>;
 pub type SpeRst = Output<'static>;