From 245c895d090b93582e23fc1573b244bdc5087d72 Mon Sep 17 00:00:00 2001
From: Corey Schuhen <cschuhen@gmail.com>
Date: Thu, 30 May 2024 21:23:12 +1000
Subject: [PATCH 1/3] Remove generics for BXCAN.

---
 embassy-stm32/src/can/bxcan/mod.rs       | 296 +++++++++++++++--------
 embassy-stm32/src/can/bxcan/registers.rs |  12 +-
 tests/stm32/src/bin/can.rs               |   4 +-
 3 files changed, 200 insertions(+), 112 deletions(-)

diff --git a/embassy-stm32/src/can/bxcan/mod.rs b/embassy-stm32/src/can/bxcan/mod.rs
index 0ac4cdab6..4f516c917 100644
--- a/embassy-stm32/src/can/bxcan/mod.rs
+++ b/embassy-stm32/src/can/bxcan/mod.rs
@@ -5,6 +5,7 @@ use core::future::poll_fn;
 use core::marker::PhantomData;
 use core::task::Poll;
 
+use embassy_hal_internal::interrupt::InterruptExt;
 use embassy_hal_internal::{into_ref, PeripheralRef};
 use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
 use embassy_sync::channel::Channel;
@@ -154,7 +155,10 @@ impl<T: Instance> Drop for CanConfig<'_, T> {
 
 /// CAN driver
 pub struct Can<'d, T: Instance> {
-    peri: PeripheralRef<'d, T>,
+    _peri: PeripheralRef<'d, T>,
+    instance: &'d crate::pac::can::Can,
+    info: &'static Info,
+    state: &'static State,
 }
 
 /// Error returned by `try_write`
@@ -179,6 +183,8 @@ impl<'d, T: Instance> Can<'d, T> {
             + 'd,
     ) -> Self {
         into_ref!(peri, rx, tx);
+        let info = T::info();
+        let regs = &T::info().regs;
 
         rx.set_as_af(rx.af_num(), AFType::Input);
         tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
@@ -186,7 +192,7 @@ impl<'d, T: Instance> Can<'d, T> {
         T::enable_and_reset();
 
         {
-            T::regs().ier().write(|w| {
+            regs.0.ier().write(|w| {
                 w.set_errie(true);
                 w.set_fmpie(0, true);
                 w.set_fmpie(1, true);
@@ -197,7 +203,7 @@ impl<'d, T: Instance> Can<'d, T> {
                 w.set_lecie(true);
             });
 
-            T::regs().mcr().write(|w| {
+            regs.0.mcr().write(|w| {
                 // Enable timestamps on rx messages
 
                 w.set_ttcm(true);
@@ -205,17 +211,14 @@ impl<'d, T: Instance> Can<'d, T> {
         }
 
         unsafe {
-            T::TXInterrupt::unpend();
-            T::TXInterrupt::enable();
-
-            T::RX0Interrupt::unpend();
-            T::RX0Interrupt::enable();
-
-            T::RX1Interrupt::unpend();
-            T::RX1Interrupt::enable();
-
-            T::SCEInterrupt::unpend();
-            T::SCEInterrupt::enable();
+            info.tx_interrupt.unpend();
+            info.tx_interrupt.enable();
+            info.rx0_interrupt.unpend();
+            info.rx0_interrupt.enable();
+            info.rx1_interrupt.unpend();
+            info.rx1_interrupt.enable();
+            info.sce_interrupt.unpend();
+            info.sce_interrupt.enable();
         }
 
         rx.set_as_af(rx.af_num(), AFType::Input);
@@ -223,7 +226,12 @@ impl<'d, T: Instance> Can<'d, T> {
 
         Registers(T::regs()).leave_init_mode();
 
-        Self { peri }
+        Self {
+            _peri: peri,
+            instance: &T::info().regs.0,
+            info: T::info(),
+            state: T::state(),
+        }
     }
 
     /// Set CAN bit rate.
@@ -265,12 +273,12 @@ impl<'d, T: Instance> Can<'d, T> {
     /// Waking the peripheral manually does not trigger a wake-up interrupt.
     /// This will wait until the peripheral has acknowledged it has awoken from sleep mode
     pub fn wakeup(&mut self) {
-        Registers(T::regs()).wakeup()
+        self.info.regs.wakeup()
     }
 
     /// Check if the peripheral is currently in sleep mode
     pub fn is_sleeping(&self) -> bool {
-        T::regs().msr().read().slak()
+        self.info.regs.0.msr().read().slak()
     }
 
     /// Put the peripheral in sleep mode
@@ -282,11 +290,11 @@ impl<'d, T: Instance> Can<'d, T> {
     /// If the peripheral has automatic wakeup enabled, when a Start-of-Frame is detected
     /// the peripheral will automatically wake and receive the incoming message.
     pub async fn sleep(&mut self) {
-        T::regs().ier().modify(|i| i.set_slkie(true));
-        T::regs().mcr().modify(|m| m.set_sleep(true));
+        self.info.regs.0.ier().modify(|i| i.set_slkie(true));
+        self.info.regs.0.mcr().modify(|m| m.set_sleep(true));
 
         poll_fn(|cx| {
-            T::state().err_waker.register(cx.waker());
+            self.state.err_waker.register(cx.waker());
             if self.is_sleeping() {
                 Poll::Ready(())
             } else {
@@ -295,7 +303,7 @@ impl<'d, T: Instance> Can<'d, T> {
         })
         .await;
 
-        T::regs().ier().modify(|i| i.set_slkie(false));
+        self.info.regs.0.ier().modify(|i| i.set_slkie(false));
     }
 
     /// Enable FIFO scheduling of outgoing frames.
@@ -337,7 +345,13 @@ impl<'d, T: Instance> Can<'d, T> {
 
     /// Waits for a specific transmit mailbox to become empty
     pub async fn flush(&self, mb: Mailbox) {
-        CanTx::<T>::flush_inner(mb).await
+        CanTx {
+            _instance: &self.instance,
+            info: self.info,
+            state: self.state,
+        }
+        .flush_inner(mb)
+        .await;
     }
 
     /// Waits until any of the transmit mailboxes become empty
@@ -347,12 +361,24 @@ impl<'d, T: Instance> Can<'d, T> {
     /// This will happen if FIFO scheduling of outgoing frames is not enabled,
     /// and a frame with equal priority is already queued for transmission.
     pub async fn flush_any(&self) {
-        CanTx::<T>::flush_any_inner().await
+        CanTx {
+            _instance: &self.instance,
+            info: self.info,
+            state: self.state,
+        }
+        .flush_any_inner()
+        .await
     }
 
     /// Waits until all of the transmit mailboxes become empty
     pub async fn flush_all(&self) {
-        CanTx::<T>::flush_all_inner().await
+        CanTx {
+            _instance: &self.instance,
+            info: self.info,
+            state: self.state,
+        }
+        .flush_all_inner()
+        .await
     }
 
     /// Attempts to abort the sending of a frame that is pending in a mailbox.
@@ -363,12 +389,12 @@ impl<'d, T: Instance> Can<'d, T> {
     /// If there is a frame in the provided mailbox, and it is canceled successfully, this function
     /// returns `true`.
     pub fn abort(&mut self, mailbox: Mailbox) -> bool {
-        Registers(T::regs()).abort(mailbox)
+        self.info.regs.abort(mailbox)
     }
 
     /// Returns `true` if no frame is pending for transmission.
     pub fn is_transmitter_idle(&self) -> bool {
-        Registers(T::regs()).is_idle()
+        self.info.regs.is_idle()
     }
 
     /// Read a CAN frame.
@@ -377,31 +403,35 @@ impl<'d, T: Instance> Can<'d, T> {
     ///
     /// Returns a tuple of the time the message was received and the message frame
     pub async fn read(&mut self) -> Result<Envelope, BusError> {
-        T::state().rx_mode.read::<T>().await
+        self.state.rx_mode.read(self.info, self.state).await
     }
 
     /// Attempts to read a CAN frame without blocking.
     ///
     /// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue.
     pub fn try_read(&mut self) -> Result<Envelope, TryReadError> {
-        T::state().rx_mode.try_read::<T>()
+        self.state.rx_mode.try_read(self.info)
     }
 
     /// Waits while receive queue is empty.
     pub async fn wait_not_empty(&mut self) {
-        T::state().rx_mode.wait_not_empty::<T>().await
+        self.state.rx_mode.wait_not_empty(self.info, self.state).await
     }
 
     /// Split the CAN driver into transmit and receive halves.
     ///
     /// Useful for doing separate transmit/receive tasks.
-    pub fn split<'c>(&'c mut self) -> (CanTx<'d, T>, CanRx<'d, T>) {
+    pub fn split<'c>(&'c mut self) -> (CanTx<'d>, CanRx<'d>) {
         (
             CanTx {
-                _peri: unsafe { self.peri.clone_unchecked() },
+                _instance: &self.instance,
+                info: self.info,
+                state: self.state,
             },
             CanRx {
-                peri: unsafe { self.peri.clone_unchecked() },
+                instance: &self.instance,
+                info: self.info,
+                state: self.state,
             },
         )
     }
@@ -411,7 +441,7 @@ impl<'d, T: Instance> Can<'d, T> {
         &'c mut self,
         txb: &'static mut TxBuf<TX_BUF_SIZE>,
         rxb: &'static mut RxBuf<RX_BUF_SIZE>,
-    ) -> BufferedCan<'d, T, TX_BUF_SIZE, RX_BUF_SIZE> {
+    ) -> BufferedCan<'d, TX_BUF_SIZE, RX_BUF_SIZE> {
         let (tx, rx) = self.split();
         BufferedCan {
             tx: tx.buffered(txb),
@@ -426,17 +456,17 @@ impl<'d, T: FilterOwner> Can<'d, T> {
     /// To modify filters of a slave peripheral, `modify_filters` has to be called on the master
     /// peripheral instead.
     pub fn modify_filters(&mut self) -> MasterFilters<'_, T> {
-        unsafe { MasterFilters::new(T::regs()) }
+        unsafe { MasterFilters::new(self.info.regs.0) }
     }
 }
 
 /// Buffered CAN driver.
-pub struct BufferedCan<'d, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> {
-    tx: BufferedCanTx<'d, T, TX_BUF_SIZE>,
-    rx: BufferedCanRx<'d, T, RX_BUF_SIZE>,
+pub struct BufferedCan<'d, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> {
+    tx: BufferedCanTx<'d, TX_BUF_SIZE>,
+    rx: BufferedCanRx<'d, RX_BUF_SIZE>,
 }
 
-impl<'d, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCan<'d, T, TX_BUF_SIZE, RX_BUF_SIZE> {
+impl<'d, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCan<'d, TX_BUF_SIZE, RX_BUF_SIZE> {
     /// Async write frame to TX buffer.
     pub async fn write(&mut self, frame: &Frame) {
         self.tx.write(frame).await
@@ -471,18 +501,20 @@ impl<'d, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Buffer
 }
 
 /// CAN driver, transmit half.
-pub struct CanTx<'d, T: Instance> {
-    _peri: PeripheralRef<'d, T>,
+pub struct CanTx<'d> {
+    _instance: &'d crate::pac::can::Can,
+    info: &'static Info,
+    state: &'static State,
 }
 
-impl<'d, T: Instance> CanTx<'d, T> {
+impl<'d> CanTx<'d> {
     /// Queues the message to be sent.
     ///
     /// If the TX queue is full, this will wait until there is space, therefore exerting backpressure.
     pub async fn write(&mut self, frame: &Frame) -> TransmitStatus {
         poll_fn(|cx| {
-            T::state().tx_mode.register(cx.waker());
-            if let Ok(status) = Registers(T::regs()).transmit(frame) {
+            self.state.tx_mode.register(cx.waker());
+            if let Ok(status) = self.info.regs.transmit(frame) {
                 return Poll::Ready(status);
             }
 
@@ -501,13 +533,13 @@ impl<'d, T: Instance> CanTx<'d, T> {
     /// This is done to work around a hardware limitation that could lead to out-of-order delivery
     /// of frames with the same priority.
     pub fn try_write(&mut self, frame: &Frame) -> Result<TransmitStatus, TryWriteError> {
-        Registers(T::regs()).transmit(frame).map_err(|_| TryWriteError::Full)
+        self.info.regs.transmit(frame).map_err(|_| TryWriteError::Full)
     }
 
-    async fn flush_inner(mb: Mailbox) {
+    async fn flush_inner(&self, mb: Mailbox) {
         poll_fn(|cx| {
-            T::state().tx_mode.register(cx.waker());
-            if T::regs().tsr().read().tme(mb.index()) {
+            self.state.tx_mode.register(cx.waker());
+            if self.info.regs.0.tsr().read().tme(mb.index()) {
                 return Poll::Ready(());
             }
 
@@ -518,14 +550,14 @@ impl<'d, T: Instance> CanTx<'d, T> {
 
     /// Waits for a specific transmit mailbox to become empty
     pub async fn flush(&self, mb: Mailbox) {
-        Self::flush_inner(mb).await
+        self.flush_inner(mb).await
     }
 
-    async fn flush_any_inner() {
+    async fn flush_any_inner(&self) {
         poll_fn(|cx| {
-            T::state().tx_mode.register(cx.waker());
+            self.state.tx_mode.register(cx.waker());
 
-            let tsr = T::regs().tsr().read();
+            let tsr = self.info.regs.0.tsr().read();
             if tsr.tme(Mailbox::Mailbox0.index())
                 || tsr.tme(Mailbox::Mailbox1.index())
                 || tsr.tme(Mailbox::Mailbox2.index())
@@ -545,14 +577,14 @@ impl<'d, T: Instance> CanTx<'d, T> {
     /// This will happen if FIFO scheduling of outgoing frames is not enabled,
     /// and a frame with equal priority is already queued for transmission.
     pub async fn flush_any(&self) {
-        Self::flush_any_inner().await
+        self.flush_any_inner().await
     }
 
-    async fn flush_all_inner() {
+    async fn flush_all_inner(&self) {
         poll_fn(|cx| {
-            T::state().tx_mode.register(cx.waker());
+            self.state.tx_mode.register(cx.waker());
 
-            let tsr = T::regs().tsr().read();
+            let tsr = self.info.regs.0.tsr().read();
             if tsr.tme(Mailbox::Mailbox0.index())
                 && tsr.tme(Mailbox::Mailbox1.index())
                 && tsr.tme(Mailbox::Mailbox2.index())
@@ -567,7 +599,7 @@ impl<'d, T: Instance> CanTx<'d, T> {
 
     /// Waits until all of the transmit mailboxes become empty
     pub async fn flush_all(&self) {
-        Self::flush_all_inner().await
+        self.flush_all_inner().await
     }
 
     /// Attempts to abort the sending of a frame that is pending in a mailbox.
@@ -578,20 +610,20 @@ impl<'d, T: Instance> CanTx<'d, T> {
     /// If there is a frame in the provided mailbox, and it is canceled successfully, this function
     /// returns `true`.
     pub fn abort(&mut self, mailbox: Mailbox) -> bool {
-        Registers(T::regs()).abort(mailbox)
+        self.info.regs.abort(mailbox)
     }
 
     /// Returns `true` if no frame is pending for transmission.
     pub fn is_idle(&self) -> bool {
-        Registers(T::regs()).is_idle()
+        self.info.regs.is_idle()
     }
 
     /// Return a buffered instance of driver. User must supply Buffers
     pub fn buffered<const TX_BUF_SIZE: usize>(
         self,
         txb: &'static mut TxBuf<TX_BUF_SIZE>,
-    ) -> BufferedCanTx<'d, T, TX_BUF_SIZE> {
-        BufferedCanTx::new(self, txb)
+    ) -> BufferedCanTx<'d, TX_BUF_SIZE> {
+        BufferedCanTx::new(self.info, self.state, self, txb)
     }
 }
 
@@ -599,23 +631,35 @@ impl<'d, T: Instance> CanTx<'d, T> {
 pub type TxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Frame, BUF_SIZE>;
 
 /// Buffered CAN driver, transmit half.
-pub struct BufferedCanTx<'d, T: Instance, const TX_BUF_SIZE: usize> {
-    _tx: CanTx<'d, T>,
+pub struct BufferedCanTx<'d, const TX_BUF_SIZE: usize> {
+    info: &'static Info,
+    state: &'static State,
+    _tx: CanTx<'d>,
     tx_buf: &'static TxBuf<TX_BUF_SIZE>,
 }
 
-impl<'d, T: Instance, const TX_BUF_SIZE: usize> BufferedCanTx<'d, T, TX_BUF_SIZE> {
-    fn new(_tx: CanTx<'d, T>, tx_buf: &'static TxBuf<TX_BUF_SIZE>) -> Self {
-        Self { _tx, tx_buf }.setup()
+impl<'d, const TX_BUF_SIZE: usize> BufferedCanTx<'d, TX_BUF_SIZE> {
+    fn new(info: &'static Info, state: &'static State, _tx: CanTx<'d>, tx_buf: &'static TxBuf<TX_BUF_SIZE>) -> Self {
+        Self {
+            info,
+            state,
+            _tx,
+            tx_buf,
+        }
+        .setup()
     }
 
     fn setup(self) -> Self {
         // We don't want interrupts being processed while we change modes.
-        critical_section::with(|_| unsafe {
+        critical_section::with(|_| {
             let tx_inner = super::common::ClassicBufferedTxInner {
                 tx_receiver: self.tx_buf.receiver().into(),
             };
-            T::mut_state().tx_mode = TxMode::Buffered(tx_inner);
+            let state = self.state as *const State;
+            unsafe {
+                let mut_state = state as *mut State;
+                (*mut_state).tx_mode = TxMode::Buffered(tx_inner);
+            }
         });
         self
     }
@@ -623,60 +667,67 @@ impl<'d, T: Instance, const TX_BUF_SIZE: usize> BufferedCanTx<'d, T, TX_BUF_SIZE
     /// Async write frame to TX buffer.
     pub async fn write(&mut self, frame: &Frame) {
         self.tx_buf.send(*frame).await;
-        T::TXInterrupt::pend(); // Wake for Tx
+        let waker = self.info.tx_waker;
+        waker(); // Wake for Tx
     }
 
     /// Returns a sender that can be used for sending CAN frames.
     pub fn writer(&self) -> BufferedCanSender {
         BufferedCanSender {
             tx_buf: self.tx_buf.sender().into(),
-            waker: T::TXInterrupt::pend,
+            waker: self.info.tx_waker,
         }
     }
 }
 
-impl<'d, T: Instance, const TX_BUF_SIZE: usize> Drop for BufferedCanTx<'d, T, TX_BUF_SIZE> {
+impl<'d, const TX_BUF_SIZE: usize> Drop for BufferedCanTx<'d, TX_BUF_SIZE> {
     fn drop(&mut self) {
-        critical_section::with(|_| unsafe {
-            T::mut_state().tx_mode = TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new());
+        critical_section::with(|_| {
+            let state = self.state as *const State;
+            unsafe {
+                let mut_state = state as *mut State;
+                (*mut_state).tx_mode = TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new());
+            }
         });
     }
 }
 
 /// CAN driver, receive half.
 #[allow(dead_code)]
-pub struct CanRx<'d, T: Instance> {
-    peri: PeripheralRef<'d, T>,
+pub struct CanRx<'d> {
+    instance: &'d crate::pac::can::Can,
+    info: &'static Info,
+    state: &'static State,
 }
 
-impl<'d, T: Instance> CanRx<'d, T> {
+impl<'d> CanRx<'d> {
     /// Read a CAN frame.
     ///
     /// If no CAN frame is in the RX buffer, this will wait until there is one.
     ///
     /// Returns a tuple of the time the message was received and the message frame
     pub async fn read(&mut self) -> Result<Envelope, BusError> {
-        T::state().rx_mode.read::<T>().await
+        self.state.rx_mode.read(self.info, self.state).await
     }
 
     /// Attempts to read a CAN frame without blocking.
     ///
     /// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue.
     pub fn try_read(&mut self) -> Result<Envelope, TryReadError> {
-        T::state().rx_mode.try_read::<T>()
+        self.state.rx_mode.try_read(self.info)
     }
 
     /// Waits while receive queue is empty.
     pub async fn wait_not_empty(&mut self) {
-        T::state().rx_mode.wait_not_empty::<T>().await
+        self.state.rx_mode.wait_not_empty(self.info, self.state).await
     }
 
     /// Return a buffered instance of driver. User must supply Buffers
     pub fn buffered<const RX_BUF_SIZE: usize>(
         self,
         rxb: &'static mut RxBuf<RX_BUF_SIZE>,
-    ) -> BufferedCanRx<'d, T, RX_BUF_SIZE> {
-        BufferedCanRx::new(self, rxb)
+    ) -> BufferedCanRx<'d, RX_BUF_SIZE> {
+        BufferedCanRx::new(self.info, self.state, self, rxb)
     }
 }
 
@@ -684,23 +735,35 @@ impl<'d, T: Instance> CanRx<'d, T> {
 pub type RxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Result<Envelope, BusError>, BUF_SIZE>;
 
 /// CAN driver, receive half in Buffered mode.
-pub struct BufferedCanRx<'d, T: Instance, const RX_BUF_SIZE: usize> {
-    _rx: CanRx<'d, T>,
+pub struct BufferedCanRx<'d, const RX_BUF_SIZE: usize> {
+    info: &'static Info,
+    state: &'static State,
+    _rx: CanRx<'d>,
     rx_buf: &'static RxBuf<RX_BUF_SIZE>,
 }
 
-impl<'d, T: Instance, const RX_BUF_SIZE: usize> BufferedCanRx<'d, T, RX_BUF_SIZE> {
-    fn new(_rx: CanRx<'d, T>, rx_buf: &'static RxBuf<RX_BUF_SIZE>) -> Self {
-        BufferedCanRx { _rx, rx_buf }.setup()
+impl<'d, const RX_BUF_SIZE: usize> BufferedCanRx<'d, RX_BUF_SIZE> {
+    fn new(info: &'static Info, state: &'static State, _rx: CanRx<'d>, rx_buf: &'static RxBuf<RX_BUF_SIZE>) -> Self {
+        BufferedCanRx {
+            info,
+            state,
+            _rx,
+            rx_buf,
+        }
+        .setup()
     }
 
     fn setup(self) -> Self {
         // We don't want interrupts being processed while we change modes.
-        critical_section::with(|_| unsafe {
+        critical_section::with(|_| {
             let rx_inner = super::common::ClassicBufferedRxInner {
                 rx_sender: self.rx_buf.sender().into(),
             };
-            T::mut_state().rx_mode = RxMode::Buffered(rx_inner);
+            let state = self.state as *const State;
+            unsafe {
+                let mut_state = state as *mut State;
+                (*mut_state).rx_mode = RxMode::Buffered(rx_inner);
+            }
         });
         self
     }
@@ -714,7 +777,7 @@ impl<'d, T: Instance, const RX_BUF_SIZE: usize> BufferedCanRx<'d, T, RX_BUF_SIZE
     ///
     /// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue.
     pub fn try_read(&mut self) -> Result<Envelope, TryReadError> {
-        match &T::state().rx_mode {
+        match &self.state.rx_mode {
             RxMode::Buffered(_) => {
                 if let Ok(result) = self.rx_buf.try_receive() {
                     match result {
@@ -722,7 +785,7 @@ impl<'d, T: Instance, const RX_BUF_SIZE: usize> BufferedCanRx<'d, T, RX_BUF_SIZE
                         Err(e) => Err(TryReadError::BusError(e)),
                     }
                 } else {
-                    if let Some(err) = Registers(T::regs()).curr_error() {
+                    if let Some(err) = self.info.regs.curr_error() {
                         return Err(TryReadError::BusError(err));
                     } else {
                         Err(TryReadError::Empty)
@@ -746,10 +809,14 @@ impl<'d, T: Instance, const RX_BUF_SIZE: usize> BufferedCanRx<'d, T, RX_BUF_SIZE
     }
 }
 
-impl<'d, T: Instance, const RX_BUF_SIZE: usize> Drop for BufferedCanRx<'d, T, RX_BUF_SIZE> {
+impl<'d, const RX_BUF_SIZE: usize> Drop for BufferedCanRx<'d, RX_BUF_SIZE> {
     fn drop(&mut self) {
-        critical_section::with(|_| unsafe {
-            T::mut_state().rx_mode = RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new());
+        critical_section::with(|_| {
+            let state = self.state as *const State;
+            unsafe {
+                let mut_state = state as *mut State;
+                (*mut_state).rx_mode = RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new());
+            }
         });
     }
 }
@@ -839,13 +906,13 @@ impl RxMode {
         }
     }
 
-    pub async fn read<T: Instance>(&self) -> Result<Envelope, BusError> {
+    pub(crate) async fn read(&self, info: &Info, state: &State) -> Result<Envelope, BusError> {
         match self {
             Self::NonBuffered(waker) => {
                 poll_fn(|cx| {
-                    T::state().err_waker.register(cx.waker());
+                    state.err_waker.register(cx.waker());
                     waker.register(cx.waker());
-                    match self.try_read::<T>() {
+                    match self.try_read(info) {
                         Ok(result) => Poll::Ready(Ok(result)),
                         Err(TryReadError::Empty) => Poll::Pending,
                         Err(TryReadError::BusError(be)) => Poll::Ready(Err(be)),
@@ -858,17 +925,17 @@ impl RxMode {
             }
         }
     }
-    pub fn try_read<T: Instance>(&self) -> Result<Envelope, TryReadError> {
+    pub(crate) fn try_read(&self, info: &Info) -> Result<Envelope, TryReadError> {
         match self {
             Self::NonBuffered(_) => {
-                let registers = Registers(T::regs());
+                let registers = &info.regs;
                 if let Some(msg) = registers.receive_fifo(RxFifo::Fifo0) {
-                    T::regs().ier().write(|w| {
+                    registers.0.ier().write(|w| {
                         w.set_fmpie(0, true);
                     });
                     Ok(msg)
                 } else if let Some(msg) = registers.receive_fifo(RxFifo::Fifo1) {
-                    T::regs().ier().write(|w| {
+                    registers.0.ier().write(|w| {
                         w.set_fmpie(1, true);
                     });
                     Ok(msg)
@@ -883,12 +950,12 @@ impl RxMode {
             }
         }
     }
-    pub async fn wait_not_empty<T: Instance>(&self) {
-        match &T::state().rx_mode {
+    pub(crate) async fn wait_not_empty(&self, info: &Info, state: &State) {
+        match &state.rx_mode {
             Self::NonBuffered(waker) => {
                 poll_fn(|cx| {
                     waker.register(cx.waker());
-                    if Registers(T::regs()).receive_frame_available() {
+                    if info.regs.receive_frame_available() {
                         Poll::Ready(())
                     } else {
                         Poll::Pending
@@ -903,7 +970,7 @@ impl RxMode {
     }
 }
 
-enum TxMode {
+pub(crate) enum TxMode {
     NonBuffered(AtomicWaker),
     Buffered(super::common::ClassicBufferedTxInner),
 }
@@ -943,7 +1010,7 @@ impl TxMode {
     }
 }
 
-struct State {
+pub(crate) struct State {
     pub(crate) rx_mode: RxMode,
     pub(crate) tx_mode: TxMode,
     pub err_waker: AtomicWaker,
@@ -959,7 +1026,17 @@ impl State {
     }
 }
 
+pub(crate) struct Info {
+    regs: Registers,
+    tx_interrupt: crate::interrupt::Interrupt,
+    rx0_interrupt: crate::interrupt::Interrupt,
+    rx1_interrupt: crate::interrupt::Interrupt,
+    sce_interrupt: crate::interrupt::Interrupt,
+    tx_waker: fn(),
+}
+
 trait SealedInstance {
+    fn info() -> &'static Info;
     fn regs() -> crate::pac::can::Can;
     fn state() -> &'static State;
     unsafe fn mut_state() -> &'static mut State;
@@ -1012,6 +1089,17 @@ foreach_peripheral!(
     (can, $inst:ident) => {
         impl SealedInstance for peripherals::$inst {
 
+            fn info() -> &'static Info {
+                static INFO: Info = Info {
+                    regs: Registers(crate::pac::$inst),
+                    tx_interrupt: crate::_generated::peripheral_interrupts::$inst::TX::IRQ,
+                    rx0_interrupt: crate::_generated::peripheral_interrupts::$inst::RX0::IRQ,
+                    rx1_interrupt: crate::_generated::peripheral_interrupts::$inst::RX1::IRQ,
+                    sce_interrupt: crate::_generated::peripheral_interrupts::$inst::SCE::IRQ,
+                    tx_waker: crate::_generated::peripheral_interrupts::$inst::TX::pend,
+                };
+                &INFO
+            }
             fn regs() -> crate::pac::can::Can {
                 crate::pac::$inst
             }
diff --git a/embassy-stm32/src/can/bxcan/registers.rs b/embassy-stm32/src/can/bxcan/registers.rs
index ad27e0744..e7c7525d8 100644
--- a/embassy-stm32/src/can/bxcan/registers.rs
+++ b/embassy-stm32/src/can/bxcan/registers.rs
@@ -131,7 +131,7 @@ impl Registers {
     /// Note that this will not trigger [`Interrupt::Wakeup`], only reception of an incoming CAN
     /// frame will cause that interrupt.
     #[allow(dead_code)]
-    pub fn wakeup(&mut self) {
+    pub fn wakeup(&self) {
         self.0.mcr().modify(|reg| {
             reg.set_sleep(false);
             reg.set_inrq(false);
@@ -216,7 +216,7 @@ impl Registers {
     /// If FIFO scheduling is enabled, frames are transmitted in the order that they are passed to this function.
     ///
     /// If all transmit mailboxes are full, this function returns [`nb::Error::WouldBlock`].
-    pub fn transmit(&mut self, frame: &Frame) -> nb::Result<TransmitStatus, Infallible> {
+    pub fn transmit(&self, frame: &Frame) -> nb::Result<TransmitStatus, Infallible> {
         // Check if FIFO scheduling is enabled.
         let fifo_scheduling = self.0.mcr().read().txfp();
 
@@ -292,7 +292,7 @@ impl Registers {
         Ok(())
     }
 
-    fn write_mailbox(&mut self, idx: usize, frame: &Frame) {
+    fn write_mailbox(&self, idx: usize, frame: &Frame) {
         debug_assert!(idx < 3);
 
         let mb = self.0.tx(idx);
@@ -309,7 +309,7 @@ impl Registers {
         });
     }
 
-    fn read_pending_mailbox(&mut self, idx: usize) -> Option<Frame> {
+    fn read_pending_mailbox(&self, idx: usize) -> Option<Frame> {
         if self.abort_by_index(idx) {
             debug_assert!(idx < 3);
 
@@ -332,7 +332,7 @@ impl Registers {
     }
 
     /// Tries to abort a pending frame. Returns `true` when aborted.
-    fn abort_by_index(&mut self, idx: usize) -> bool {
+    fn abort_by_index(&self, idx: usize) -> bool {
         self.0.tsr().write(|reg| reg.set_abrq(idx, true));
 
         // Wait for the abort request to be finished.
@@ -351,7 +351,7 @@ impl Registers {
     ///
     /// If there is a frame in the provided mailbox, and it is canceled successfully, this function
     /// returns `true`.
-    pub fn abort(&mut self, mailbox: Mailbox) -> bool {
+    pub fn abort(&self, mailbox: Mailbox) -> bool {
         // If the mailbox is empty, the value of TXOKx depends on what happened with the previous
         // frame in that mailbox. Only call abort_by_index() if the mailbox is not empty.
         let tsr = self.0.tsr().read();
diff --git a/tests/stm32/src/bin/can.rs b/tests/stm32/src/bin/can.rs
index 004b1a729..f63076512 100644
--- a/tests/stm32/src/bin/can.rs
+++ b/tests/stm32/src/bin/can.rs
@@ -19,8 +19,8 @@ mod can_common;
 use can_common::*;
 
 type Can<'d> = embassy_stm32::can::Can<'d, embassy_stm32::peripherals::CAN1>;
-type CanTx<'d> = embassy_stm32::can::CanTx<'d, embassy_stm32::peripherals::CAN1>;
-type CanRx<'d> = embassy_stm32::can::CanRx<'d, embassy_stm32::peripherals::CAN1>;
+type CanTx<'d> = embassy_stm32::can::CanTx<'d>;
+type CanRx<'d> = embassy_stm32::can::CanRx<'d>;
 
 bind_interrupts!(struct Irqs {
     CAN1_RX0 => Rx0InterruptHandler<CAN1>;

From 7fd79857c339ccc55a4df606e25b432ada8f43a1 Mon Sep 17 00:00:00 2001
From: Corey Schuhen <corey@schuhen.net>
Date: Thu, 30 May 2024 22:00:02 +1000
Subject: [PATCH 2/3] Fix example.

---
 examples/stm32f7/src/bin/can.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/examples/stm32f7/src/bin/can.rs b/examples/stm32f7/src/bin/can.rs
index e32b4d3df..f4d6d8c19 100644
--- a/examples/stm32f7/src/bin/can.rs
+++ b/examples/stm32f7/src/bin/can.rs
@@ -24,7 +24,7 @@ bind_interrupts!(struct Irqs {
 });
 
 #[embassy_executor::task]
-pub async fn send_can_message(tx: &'static mut CanTx<'static, CAN3>) {
+pub async fn send_can_message(tx: &'static mut CanTx<'static>) {
     loop {
         let frame = Frame::new_data(unwrap!(StandardId::new(0 as _)), &[0]).unwrap();
         tx.write(&frame).await;
@@ -62,7 +62,7 @@ async fn main(spawner: Spawner) {
 
     let (tx, mut rx) = can.split();
 
-    static CAN_TX: StaticCell<CanTx<'static, CAN3>> = StaticCell::new();
+    static CAN_TX: StaticCell<CanTx<'static>> = StaticCell::new();
     let tx = CAN_TX.init(tx);
     spawner.spawn(send_can_message(tx)).unwrap();
 

From b4a2f7fb70ac3f0b0d9226ab5ff5aab7a5bf8649 Mon Sep 17 00:00:00 2001
From: Corey Schuhen <corey@schuhen.net>
Date: Thu, 30 May 2024 22:10:46 +1000
Subject: [PATCH 3/3] Use phantom for lifetime holder instead of not used
 pointer to pointer.

---
 embassy-stm32/src/can/bxcan/mod.rs | 16 +++++++---------
 1 file changed, 7 insertions(+), 9 deletions(-)

diff --git a/embassy-stm32/src/can/bxcan/mod.rs b/embassy-stm32/src/can/bxcan/mod.rs
index 4f516c917..c242aea2b 100644
--- a/embassy-stm32/src/can/bxcan/mod.rs
+++ b/embassy-stm32/src/can/bxcan/mod.rs
@@ -156,7 +156,6 @@ impl<T: Instance> Drop for CanConfig<'_, T> {
 /// CAN driver
 pub struct Can<'d, T: Instance> {
     _peri: PeripheralRef<'d, T>,
-    instance: &'d crate::pac::can::Can,
     info: &'static Info,
     state: &'static State,
 }
@@ -228,7 +227,6 @@ impl<'d, T: Instance> Can<'d, T> {
 
         Self {
             _peri: peri,
-            instance: &T::info().regs.0,
             info: T::info(),
             state: T::state(),
         }
@@ -346,7 +344,7 @@ impl<'d, T: Instance> Can<'d, T> {
     /// Waits for a specific transmit mailbox to become empty
     pub async fn flush(&self, mb: Mailbox) {
         CanTx {
-            _instance: &self.instance,
+            _phantom: PhantomData,
             info: self.info,
             state: self.state,
         }
@@ -362,7 +360,7 @@ impl<'d, T: Instance> Can<'d, T> {
     /// and a frame with equal priority is already queued for transmission.
     pub async fn flush_any(&self) {
         CanTx {
-            _instance: &self.instance,
+            _phantom: PhantomData,
             info: self.info,
             state: self.state,
         }
@@ -373,7 +371,7 @@ impl<'d, T: Instance> Can<'d, T> {
     /// Waits until all of the transmit mailboxes become empty
     pub async fn flush_all(&self) {
         CanTx {
-            _instance: &self.instance,
+            _phantom: PhantomData,
             info: self.info,
             state: self.state,
         }
@@ -424,12 +422,12 @@ impl<'d, T: Instance> Can<'d, T> {
     pub fn split<'c>(&'c mut self) -> (CanTx<'d>, CanRx<'d>) {
         (
             CanTx {
-                _instance: &self.instance,
+                _phantom: PhantomData,
                 info: self.info,
                 state: self.state,
             },
             CanRx {
-                instance: &self.instance,
+                _phantom: PhantomData,
                 info: self.info,
                 state: self.state,
             },
@@ -502,7 +500,7 @@ impl<'d, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCan<'d, TX_
 
 /// CAN driver, transmit half.
 pub struct CanTx<'d> {
-    _instance: &'d crate::pac::can::Can,
+    _phantom: PhantomData<&'d ()>,
     info: &'static Info,
     state: &'static State,
 }
@@ -695,7 +693,7 @@ impl<'d, const TX_BUF_SIZE: usize> Drop for BufferedCanTx<'d, TX_BUF_SIZE> {
 /// CAN driver, receive half.
 #[allow(dead_code)]
 pub struct CanRx<'d> {
-    instance: &'d crate::pac::can::Can,
+    _phantom: PhantomData<&'d ()>,
     info: &'static Info,
     state: &'static State,
 }