diff --git a/embassy-stm32/src/can/bx/filter.rs b/embassy-stm32/src/can/bx/filter.rs index c149d37ea..64f020fc7 100644 --- a/embassy-stm32/src/can/bx/filter.rs +++ b/embassy-stm32/src/can/bx/filter.rs @@ -2,7 +2,6 @@ use core::marker::PhantomData; -use crate::can::bx::pac::can::RegisterBlock; use crate::can::bx::{ExtendedId, Fifo, FilterOwner, Id, Instance, MasterInstance, StandardId}; const F32_RTR: u32 = 0b010; // set the RTR bit to match remote frames @@ -213,19 +212,18 @@ pub struct MasterFilters<'a, I: FilterOwner> { /// On chips with splittable filter banks, this value can be dynamic. bank_count: u8, _can: PhantomData<&'a mut I>, + canregs: crate::pac::can::Can, } // NOTE: This type mutably borrows the CAN instance and has unique access to the registers while it // exists. impl MasterFilters<'_, I> { - pub(crate) unsafe fn new() -> Self { - let can = &*I::REGISTERS; - + pub(crate) unsafe fn new(canregs: crate::pac::can::Can) -> Self { // Enable initialization mode. - can.fmr.modify(|_, w| w.finit().set_bit()); + canregs.fmr().modify(|reg| reg.set_finit(true)); // Read the filter split value. - let bank_count = can.fmr.read().can2sb().bits(); + let bank_count = canregs.fmr().read().can2sb(); // (Reset value of CAN2SB is 0x0E, 14, which, in devices with 14 filter banks, assigns all // of them to the master peripheral, and in devices with 28, assigns them 50/50 to @@ -234,18 +232,15 @@ impl MasterFilters<'_, I> { Self { bank_count, _can: PhantomData, + canregs, } } - fn registers(&self) -> &RegisterBlock { - unsafe { &*I::REGISTERS } - } - - fn banks_imm(&self) -> FilterBanks<'_> { + fn banks_imm(&self) -> FilterBanks { FilterBanks { start_idx: 0, bank_count: self.bank_count, - can: self.registers(), + canregs: self.canregs, } } @@ -296,9 +291,7 @@ impl MasterFilters<'_, I> { /// Sets the index at which the filter banks owned by the slave peripheral start. pub fn set_split(&mut self, split_index: u8) -> &mut Self { assert!(split_index <= I::NUM_FILTER_BANKS); - self.registers() - .fmr - .modify(|_, w| unsafe { w.can2sb().bits(split_index) }); + self.canregs.fmr().modify(|reg| reg.set_can2sb(split_index)); self.bank_count = split_index; self } @@ -310,6 +303,7 @@ impl MasterFilters<'_, I> { start_idx: self.bank_count, bank_count: I::NUM_FILTER_BANKS - self.bank_count, _can: PhantomData, + canregs: self.canregs, } } } @@ -317,10 +311,8 @@ impl MasterFilters<'_, I> { impl Drop for MasterFilters<'_, I> { #[inline] fn drop(&mut self) { - let can = self.registers(); - // Leave initialization mode. - can.fmr.modify(|_, w| w.finit().clear_bit()); + self.canregs.fmr().modify(|regs| regs.set_finit(false)); } } @@ -329,18 +321,15 @@ pub struct SlaveFilters<'a, I: Instance> { start_idx: u8, bank_count: u8, _can: PhantomData<&'a mut I>, + canregs: crate::pac::can::Can, } impl SlaveFilters<'_, I> { - fn registers(&self) -> &RegisterBlock { - unsafe { &*I::REGISTERS } - } - - fn banks_imm(&self) -> FilterBanks<'_> { + fn banks_imm(&self) -> FilterBanks { FilterBanks { start_idx: self.start_idx, bank_count: self.bank_count, - can: self.registers(), + canregs: self.canregs, } } @@ -381,20 +370,22 @@ impl SlaveFilters<'_, I> { } } -struct FilterBanks<'a> { +struct FilterBanks { start_idx: u8, bank_count: u8, - can: &'a RegisterBlock, + canregs: crate::pac::can::Can, } -impl FilterBanks<'_> { +impl FilterBanks { fn clear(&mut self) { let mask = filter_bitmask(self.start_idx, self.bank_count); - self.can.fa1r.modify(|r, w| { - let bits = r.bits(); - // Clear all bits in `mask`. - unsafe { w.bits(bits & !mask) } + self.canregs.fa1r().modify(|reg| { + for i in 0..28usize { + if (0x01u32 << i) & mask != 0 { + reg.set_fact(i, false); + } + } }); } @@ -404,8 +395,7 @@ impl FilterBanks<'_> { fn disable(&mut self, index: u8) { self.assert_bank_index(index); - - self.can.fa1r.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << index)) }) + self.canregs.fa1r().modify(|reg| reg.set_fact(index as usize, false)) } fn enable(&mut self, index: u8, fifo: Fifo, config: BankConfig) { @@ -413,27 +403,11 @@ impl FilterBanks<'_> { // Configure mode. let mode = matches!(config, BankConfig::List16(_) | BankConfig::List32(_)); - self.can.fm1r.modify(|r, w| { - let mut bits = r.bits(); - if mode { - bits |= 1 << index; - } else { - bits &= !(1 << index); - } - unsafe { w.bits(bits) } - }); + self.canregs.fm1r().modify(|reg| reg.set_fbm(index as usize, mode)); // Configure scale. let scale = matches!(config, BankConfig::List32(_) | BankConfig::Mask32(_)); - self.can.fs1r.modify(|r, w| { - let mut bits = r.bits(); - if scale { - bits |= 1 << index; - } else { - bits &= !(1 << index); - } - unsafe { w.bits(bits) } - }); + self.canregs.fs1r().modify(|reg| reg.set_fsc(index as usize, scale)); // Configure filter register. let (fxr1, fxr2); @@ -455,22 +429,23 @@ impl FilterBanks<'_> { fxr2 = a.mask; } }; - let bank = &self.can.fb[usize::from(index)]; - bank.fr1.write(|w| unsafe { w.bits(fxr1) }); - bank.fr2.write(|w| unsafe { w.bits(fxr2) }); + let bank = self.canregs.fb(index as usize); + bank.fr1().write(|w| w.0 = fxr1); + bank.fr2().write(|w| w.0 = fxr2); // Assign to the right FIFO - self.can.ffa1r.modify(|r, w| unsafe { - let mut bits = r.bits(); - match fifo { - Fifo::Fifo0 => bits &= !(1 << index), - Fifo::Fifo1 => bits |= 1 << index, - } - w.bits(bits) + self.canregs.ffa1r().modify(|reg| { + reg.set_ffa( + index as usize, + match fifo { + Fifo::Fifo0 => false, + Fifo::Fifo1 => true, + }, + ) }); // Set active. - self.can.fa1r.modify(|r, w| unsafe { w.bits(r.bits() | (1 << index)) }) + self.canregs.fa1r().modify(|reg| reg.set_fact(index as usize, true)) } } diff --git a/embassy-stm32/src/can/bx/frame.rs b/embassy-stm32/src/can/bx/frame.rs index 2a51d1b15..828f375be 100644 --- a/embassy-stm32/src/can/bx/frame.rs +++ b/embassy-stm32/src/can/bx/frame.rs @@ -1,5 +1,4 @@ #[cfg(test)] - use core::cmp::Ordering; use core::ops::{Deref, DerefMut}; diff --git a/embassy-stm32/src/can/bx/mod.rs b/embassy-stm32/src/can/bx/mod.rs index c5801abec..eee8a33a6 100644 --- a/embassy-stm32/src/can/bx/mod.rs +++ b/embassy-stm32/src/can/bx/mod.rs @@ -35,7 +35,6 @@ use core::cmp::{Ord, Ordering}; use core::convert::{Infallible, TryInto}; use core::marker::PhantomData; use core::mem; -use core::ptr::NonNull; pub use id::{ExtendedId, Id, StandardId}; @@ -125,7 +124,7 @@ pub struct OverrunError { /// priority than remote frames. #[derive(Clone, Copy, Debug, PartialEq, Eq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] -struct IdReg(u32); +pub(crate) struct IdReg(u32); impl IdReg { const STANDARD_SHIFT: u32 = 21; @@ -243,23 +242,25 @@ impl CanConfig<'_, I> { /// /// Then copy the `CAN_BUS_TIME` register value from the table and pass it as the `btr` /// parameter to this method. - pub fn set_bit_timing(self, btr: u32) -> Self { - self.can.set_bit_timing(btr); + pub fn set_bit_timing(self, bt: crate::can::util::NominalBitTiming) -> Self { + self.can.set_bit_timing(bt); self } /// Enables or disables loopback mode: Internally connects the TX and RX /// signals together. pub fn set_loopback(self, enabled: bool) -> Self { - let can = self.can.registers(); - can.btr.modify(|_, w| w.lbkm().bit(enabled)); + self.can.canregs.btr().modify(|reg| reg.set_lbkm(enabled)); self } /// Enables or disables silent mode: Disconnects the TX signal from the pin. pub fn set_silent(self, enabled: bool) -> Self { - let can = self.can.registers(); - can.btr.modify(|_, w| w.silm().bit(enabled)); + let mode = match enabled { + false => stm32_metapac::can::vals::Silm::NORMAL, + true => stm32_metapac::can::vals::Silm::SILENT, + }; + self.can.canregs.btr().modify(|reg| reg.set_silm(mode)); self } @@ -270,8 +271,7 @@ impl CanConfig<'_, I> { /// /// Automatic retransmission is enabled by default. pub fn set_automatic_retransmit(self, enabled: bool) -> Self { - let can = self.can.registers(); - can.mcr.modify(|_, w| w.nart().bit(!enabled)); + self.can.canregs.mcr().modify(|reg| reg.set_nart(enabled)); self } @@ -304,11 +304,13 @@ impl CanConfig<'_, I> { /// Leaves initialization mode, enters sleep mode. fn leave_init_mode(&mut self) { - let can = self.can.registers(); - can.mcr.modify(|_, w| w.sleep().set_bit().inrq().clear_bit()); + self.can.canregs.mcr().modify(|reg| { + reg.set_sleep(true); + reg.set_inrq(false); + }); loop { - let msr = can.msr.read(); - if msr.slak().bit_is_set() && msr.inak().bit_is_clear() { + let msr = self.can.canregs.msr().read(); + if msr.slak() && !msr.inak() { break; } } @@ -341,23 +343,24 @@ impl CanBuilder { /// /// Then copy the `CAN_BUS_TIME` register value from the table and pass it as the `btr` /// parameter to this method. - pub fn set_bit_timing(mut self, btr: u32) -> Self { - self.can.set_bit_timing(btr); + pub fn set_bit_timing(mut self, bt: crate::can::util::NominalBitTiming) -> Self { + self.can.set_bit_timing(bt); self } - /// Enables or disables loopback mode: Internally connects the TX and RX /// signals together. pub fn set_loopback(self, enabled: bool) -> Self { - let can = self.can.registers(); - can.btr.modify(|_, w| w.lbkm().bit(enabled)); + self.can.canregs.btr().modify(|reg| reg.set_lbkm(enabled)); self } /// Enables or disables silent mode: Disconnects the TX signal from the pin. pub fn set_silent(self, enabled: bool) -> Self { - let can = self.can.registers(); - can.btr.modify(|_, w| w.silm().bit(enabled)); + let mode = match enabled { + false => stm32_metapac::can::vals::Silm::NORMAL, + true => stm32_metapac::can::vals::Silm::SILENT, + }; + self.can.canregs.btr().modify(|reg| reg.set_silm(mode)); self } @@ -368,8 +371,7 @@ impl CanBuilder { /// /// Automatic retransmission is enabled by default. pub fn set_automatic_retransmit(self, enabled: bool) -> Self { - let can = self.can.registers(); - can.mcr.modify(|_, w| w.nart().bit(!enabled)); + self.can.canregs.mcr().modify(|reg| reg.set_nart(enabled)); self } @@ -403,11 +405,13 @@ impl CanBuilder { /// Leaves initialization mode, enters sleep mode. fn leave_init_mode(&mut self) { - let can = self.can.registers(); - can.mcr.modify(|_, w| w.sleep().set_bit().inrq().clear_bit()); + self.can.canregs.mcr().modify(|reg| { + reg.set_sleep(true); + reg.set_inrq(false); + }); loop { - let msr = can.msr.read(); - if msr.slak().bit_is_set() && msr.inak().bit_is_clear() { + let msr = self.can.canregs.msr().read(); + if msr.slak() && !msr.inak() { break; } } @@ -417,6 +421,7 @@ impl CanBuilder { /// Interface to a bxCAN peripheral. pub struct Can { instance: I, + canregs: crate::pac::can::Can, } impl Can @@ -424,15 +429,18 @@ where I: Instance, { /// Creates a [`CanBuilder`] for constructing a CAN interface. - pub fn builder(instance: I) -> CanBuilder { - let can_builder = CanBuilder { can: Can { instance } }; + pub fn builder(instance: I, canregs: crate::pac::can::Can) -> CanBuilder { + let can_builder = CanBuilder { + can: Can { instance, canregs }, + }; - let can_reg = can_builder.can.registers(); - // Enter init mode. - can_reg.mcr.modify(|_, w| w.sleep().clear_bit().inrq().set_bit()); + canregs.mcr().modify(|reg| { + reg.set_sleep(false); + reg.set_inrq(true); + }); loop { - let msr = can_reg.msr.read(); - if msr.slak().bit_is_clear() && msr.inak().bit_is_set() { + let msr = canregs.msr().read(); + if !msr.slak() && msr.inak() { break; } } @@ -440,18 +448,16 @@ where can_builder } - fn registers(&self) -> &RegisterBlock { - unsafe { &*I::REGISTERS } - } - - fn set_bit_timing(&mut self, btr: u32) { - // Mask of all non-reserved BTR bits, except the mode flags. - const MASK: u32 = 0x037F_03FF; - - let can = self.registers(); - can.btr.modify(|r, w| unsafe { - let mode_bits = r.bits() & 0xC000_0000; - w.bits(mode_bits | (btr & MASK)) + fn set_bit_timing(&mut self, bt: crate::can::util::NominalBitTiming) { + let prescaler = u16::from(bt.prescaler) & 0x1FF; + let seg1 = u8::from(bt.seg1); + let seg2 = u8::from(bt.seg2) & 0x7F; + let sync_jump_width = u8::from(bt.sync_jump_width) & 0x7F; + self.canregs.btr().modify(|reg| { + reg.set_brp(prescaler - 1); + reg.set_ts(0, seg1 - 1); + reg.set_ts(1, seg2 - 1); + reg.set_sjw(sync_jump_width - 1); }); } @@ -467,7 +473,7 @@ where /// The peripheral is disabled by setting `RESET` in `CAN_MCR`, which causes the peripheral to /// enter sleep mode. pub fn free(self) -> I { - self.registers().mcr.write(|w| w.reset().set_bit()); + self.canregs.mcr().write(|reg| reg.set_reset(true)); self.instance } @@ -475,13 +481,13 @@ where /// /// Calling this method will enter initialization mode. pub fn modify_config(&mut self) -> CanConfig<'_, I> { - let can = self.registers(); - - // Enter init mode. - can.mcr.modify(|_, w| w.sleep().clear_bit().inrq().set_bit()); + self.canregs.mcr().modify(|reg| { + reg.set_sleep(false); + reg.set_inrq(true); + }); loop { - let msr = can.msr.read(); - if msr.slak().bit_is_clear() && msr.inak().bit_is_set() { + let msr = self.canregs.msr().read(); + if !msr.slak() && msr.inak() { break; } } @@ -497,8 +503,7 @@ where /// receive the frame. If enabled, [`Interrupt::Wakeup`] will also be triggered by the incoming /// frame. pub fn set_automatic_wakeup(&mut self, enabled: bool) { - let can = self.registers(); - can.mcr.modify(|_, w| w.awum().bit(enabled)); + self.canregs.mcr().modify(|reg| reg.set_awum(enabled)); } /// Leaves initialization mode and enables the peripheral (non-blocking version). @@ -510,10 +515,12 @@ where /// in the background. The peripheral is enabled and ready to use when this method returns /// successfully. pub fn enable_non_blocking(&mut self) -> nb::Result<(), Infallible> { - let can = self.registers(); - let msr = can.msr.read(); - if msr.slak().bit_is_set() { - can.mcr.modify(|_, w| w.abom().set_bit().sleep().clear_bit()); + let msr = self.canregs.msr().read(); + if msr.slak() { + self.canregs.mcr().modify(|reg| { + reg.set_abom(true); + reg.set_sleep(false); + }); Err(nb::Error::WouldBlock) } else { Ok(()) @@ -524,11 +531,13 @@ where /// /// While in sleep mode, an incoming CAN frame will trigger [`Interrupt::Wakeup`] if enabled. pub fn sleep(&mut self) { - let can = self.registers(); - can.mcr.modify(|_, w| w.sleep().set_bit().inrq().clear_bit()); + self.canregs.mcr().modify(|reg| { + reg.set_sleep(true); + reg.set_inrq(false); + }); loop { - let msr = can.msr.read(); - if msr.slak().bit_is_set() && msr.inak().bit_is_clear() { + let msr = self.canregs.msr().read(); + if msr.slak() && !msr.inak() { break; } } @@ -539,11 +548,13 @@ where /// Note that this will not trigger [`Interrupt::Wakeup`], only reception of an incoming CAN /// frame will cause that interrupt. pub fn wakeup(&mut self) { - let can = self.registers(); - can.mcr.modify(|_, w| w.sleep().clear_bit().inrq().clear_bit()); + self.canregs.mcr().modify(|reg| { + reg.set_sleep(false); + reg.set_inrq(false); + }); loop { - let msr = can.msr.read(); - if msr.slak().bit_is_clear() && msr.inak().bit_is_clear() { + let msr = self.canregs.msr().read(); + if !msr.slak() && !msr.inak() { break; } } @@ -560,13 +571,13 @@ where /// [`TransmitStatus::dequeued_frame`]. pub fn transmit(&mut self, frame: &Frame) -> nb::Result { // Safety: We have a `&mut self` and have unique access to the peripheral. - unsafe { Tx::::conjure().transmit(frame) } + unsafe { Tx::::conjure(self.canregs).transmit(frame) } } /// Returns `true` if no frame is pending for transmission. pub fn is_transmitter_idle(&self) -> bool { // Safety: Read-only operation. - unsafe { Tx::::conjure().is_idle() } + unsafe { Tx::::conjure(self.canregs).is_idle() } } /// Attempts to abort the sending of a frame that is pending in a mailbox. @@ -578,7 +589,7 @@ where /// returns `true`. pub fn abort(&mut self, mailbox: Mailbox) -> bool { // Safety: We have a `&mut self` and have unique access to the peripheral. - unsafe { Tx::::conjure().abort(mailbox) } + unsafe { Tx::::conjure(self.canregs).abort(mailbox) } } /// Returns a received frame if available. @@ -589,8 +600,8 @@ where /// Returns `Err` when a frame was lost due to buffer overrun. pub fn receive(&mut self) -> nb::Result { // Safety: We have a `&mut self` and have unique access to the peripheral. - let mut rx0 = unsafe { Rx0::::conjure() }; - let mut rx1 = unsafe { Rx1::::conjure() }; + let mut rx0 = unsafe { Rx0::::conjure(self.canregs) }; + let mut rx1 = unsafe { Rx1::::conjure(self.canregs) }; match rx0.receive() { Err(nb::Error::WouldBlock) => rx1.receive(), @@ -599,30 +610,35 @@ where } /// Returns a reference to the RX FIFO 0. - pub fn rx0(&mut self) -> &mut Rx0 { + pub fn rx0(&mut self) -> Rx0 { // Safety: We take `&mut self` and the return value lifetimes are tied to `self`'s lifetime. - unsafe { Rx0::conjure_by_ref() } + unsafe { Rx0::conjure(self.canregs) } } /// Returns a reference to the RX FIFO 1. - pub fn rx1(&mut self) -> &mut Rx1 { + pub fn rx1(&mut self) -> Rx1 { // Safety: We take `&mut self` and the return value lifetimes are tied to `self`'s lifetime. - unsafe { Rx1::conjure_by_ref() } + unsafe { Rx1::conjure(self.canregs) } } - /// Splits this `Can` instance into transmitting and receiving halves, by reference. - pub fn split_by_ref(&mut self) -> (&mut Tx, &mut Rx0, &mut Rx1) { + pub fn split_by_ref(&mut self) -> (Tx, Rx0, Rx1) { // Safety: We take `&mut self` and the return value lifetimes are tied to `self`'s lifetime. - let tx = unsafe { Tx::conjure_by_ref() }; - let rx0 = unsafe { Rx0::conjure_by_ref() }; - let rx1 = unsafe { Rx1::conjure_by_ref() }; + let tx = unsafe { Tx::conjure(self.canregs) }; + let rx0 = unsafe { Rx0::conjure(self.canregs) }; + let rx1 = unsafe { Rx1::conjure(self.canregs) }; (tx, rx0, rx1) } /// Consumes this `Can` instance and splits it into transmitting and receiving halves. pub fn split(self) -> (Tx, Rx0, Rx1) { // Safety: `Self` is not `Copy` and is destroyed by moving it into this method. - unsafe { (Tx::conjure(), Rx0::conjure(), Rx1::conjure()) } + unsafe { + ( + Tx::conjure(self.canregs), + Rx0::conjure(self.canregs), + Rx1::conjure(self.canregs), + ) + } } } @@ -632,46 +648,25 @@ impl Can { /// 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<'_, I> { - unsafe { MasterFilters::new() } + unsafe { MasterFilters::new(self.canregs) } } } /// Interface to the CAN transmitter part. pub struct Tx { _can: PhantomData, -} - -#[inline] -const fn ok_mask(idx: usize) -> u32 { - 0x02 << (8 * idx) -} - -#[inline] -const fn abort_mask(idx: usize) -> u32 { - 0x80 << (8 * idx) + canregs: crate::pac::can::Can, } impl Tx where I: Instance, { - unsafe fn conjure() -> Self { - Self { _can: PhantomData } - } - - /// Creates a `&mut Self` out of thin air. - /// - /// This is only safe if it is the only way to access a `Tx`. - unsafe fn conjure_by_ref<'a>() -> &'a mut Self { - // Cause out of bounds access when `Self` is not zero-sized. - [()][core::mem::size_of::()]; - - // Any aligned pointer is valid for ZSTs. - &mut *NonNull::dangling().as_ptr() - } - - fn registers(&self) -> &RegisterBlock { - unsafe { &*I::REGISTERS } + unsafe fn conjure(canregs: crate::pac::can::Can) -> Self { + Self { + _can: PhantomData, + canregs, + } } /// Puts a CAN frame in a transmit mailbox for transmission on the bus. @@ -684,13 +679,11 @@ where /// cancelled and `frame` is enqueued instead. The frame that was replaced is returned as /// [`TransmitStatus::dequeued_frame`]. pub fn transmit(&mut self, frame: &Frame) -> nb::Result { - let can = self.registers(); - // Get the index of the next free mailbox or the one with the lowest priority. - let tsr = can.tsr.read(); - let idx = tsr.code().bits() as usize; + let tsr = self.canregs.tsr().read(); + let idx = tsr.code() as usize; - let frame_is_pending = tsr.tme0().bit_is_clear() || tsr.tme1().bit_is_clear() || tsr.tme2().bit_is_clear(); + let frame_is_pending = !tsr.tme(0) || !tsr.tme(1) || !tsr.tme(2); let pending_frame = if frame_is_pending { // High priority frames are transmitted first by the mailbox system. // Frames with identical identifier shall be transmitted in FIFO order. @@ -701,8 +694,7 @@ where self.check_priority(1, frame.id)?; self.check_priority(2, frame.id)?; - let all_frames_are_pending = - tsr.tme0().bit_is_clear() && tsr.tme1().bit_is_clear() && tsr.tme2().bit_is_clear(); + let all_frames_are_pending = !tsr.tme(0) && !tsr.tme(1) && !tsr.tme(2); if all_frames_are_pending { // No free mailbox is available. This can only happen when three frames with // ascending priority (descending IDs) were requested for transmission and all @@ -735,15 +727,14 @@ where /// Returns `Ok` when the mailbox is free or if it contains pending frame with a /// lower priority (higher ID) than the identifier `id`. fn check_priority(&self, idx: usize, id: IdReg) -> nb::Result<(), Infallible> { - let can = self.registers(); - // Read the pending frame's id to check its priority. assert!(idx < 3); - let tir = &can.tx[idx].tir.read(); + let tir = &self.canregs.tx(idx).tir().read(); + //let tir = &can.tx[idx].tir.read(); // Check the priority by comparing the identifiers. But first make sure the // frame has not finished the transmission (`TXRQ` == 0) in the meantime. - if tir.txrq().bit_is_set() && id <= IdReg::from_register(tir.bits()) { + if tir.txrq() && id <= IdReg::from_register(tir.0) { // There's a mailbox whose priority is higher or equal // the priority of the new frame. return Err(nb::Error::WouldBlock); @@ -753,33 +744,34 @@ where } fn write_mailbox(&mut self, idx: usize, frame: &Frame) { - let can = self.registers(); - debug_assert!(idx < 3); - let mb = unsafe { &can.tx.get_unchecked(idx) }; - mb.tdtr.write(|w| unsafe { w.dlc().bits(frame.dlc() as u8) }); - mb.tdlr - .write(|w| unsafe { w.bits(u32::from_ne_bytes(frame.data.bytes[0..4].try_into().unwrap())) }); - mb.tdhr - .write(|w| unsafe { w.bits(u32::from_ne_bytes(frame.data.bytes[4..8].try_into().unwrap())) }); - mb.tir.write(|w| unsafe { w.bits(frame.id.0).txrq().set_bit() }); + let mb = self.canregs.tx(idx); + mb.tdtr().write(|w| w.set_dlc(frame.dlc() as u8)); + + mb.tdlr() + .write(|w| w.0 = u32::from_ne_bytes(frame.data.bytes[0..4].try_into().unwrap())); + mb.tdhr() + .write(|w| w.0 = u32::from_ne_bytes(frame.data.bytes[4..8].try_into().unwrap())); + mb.tir().write(|w| { + w.0 = frame.id.0; + w.set_txrq(true); + }); } fn read_pending_mailbox(&mut self, idx: usize) -> Option { if self.abort_by_index(idx) { - let can = self.registers(); debug_assert!(idx < 3); - let mb = unsafe { &can.tx.get_unchecked(idx) }; + let mb = self.canregs.tx(idx); // Read back the pending frame. let mut pending_frame = Frame { - id: IdReg(mb.tir.read().bits()), + id: IdReg(mb.tir().read().0), data: Data::empty(), }; - pending_frame.data.bytes[0..4].copy_from_slice(&mb.tdlr.read().bits().to_ne_bytes()); - pending_frame.data.bytes[4..8].copy_from_slice(&mb.tdhr.read().bits().to_ne_bytes()); - pending_frame.data.len = mb.tdtr.read().dlc().bits(); + pending_frame.data.bytes[0..4].copy_from_slice(&mb.tdlr().read().0.to_ne_bytes()); + pending_frame.data.bytes[4..8].copy_from_slice(&mb.tdhr().read().0.to_ne_bytes()); + pending_frame.data.len = mb.tdtr().read().dlc(); Some(pending_frame) } else { @@ -793,15 +785,13 @@ where /// Tries to abort a pending frame. Returns `true` when aborted. fn abort_by_index(&mut self, idx: usize) -> bool { - let can = self.registers(); - - can.tsr.write(|w| unsafe { w.bits(abort_mask(idx)) }); + self.canregs.tsr().write(|reg| reg.set_abrq(idx, true)); // Wait for the abort request to be finished. loop { - let tsr = can.tsr.read().bits(); - if tsr & abort_mask(idx) == 0 { - break tsr & ok_mask(idx) == 0; + let tsr = self.canregs.tsr().read(); + if false == tsr.abrq(idx) { + break tsr.txok(idx) == false; } } } @@ -816,11 +806,11 @@ where pub fn abort(&mut 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.registers().tsr.read(); + let tsr = self.canregs.tsr().read(); let mailbox_empty = match mailbox { - Mailbox::Mailbox0 => tsr.tme0().bit_is_set(), - Mailbox::Mailbox1 => tsr.tme1().bit_is_set(), - Mailbox::Mailbox2 => tsr.tme2().bit_is_set(), + Mailbox::Mailbox0 => tsr.tme(0), + Mailbox::Mailbox1 => tsr.tme(1), + Mailbox::Mailbox2 => tsr.tme(2), }; if mailbox_empty { false @@ -831,119 +821,101 @@ where /// Returns `true` if no frame is pending for transmission. pub fn is_idle(&self) -> bool { - let can = self.registers(); - let tsr = can.tsr.read(); - tsr.tme0().bit_is_set() && tsr.tme1().bit_is_set() && tsr.tme2().bit_is_set() + let tsr = self.canregs.tsr().read(); + tsr.tme(0) && tsr.tme(1) && tsr.tme(2) } /// Clears the request complete flag for all mailboxes. pub fn clear_interrupt_flags(&mut self) { - let can = self.registers(); - can.tsr - .write(|w| w.rqcp2().set_bit().rqcp1().set_bit().rqcp0().set_bit()); + self.canregs.tsr().write(|reg| { + reg.set_rqcp(0, true); + reg.set_rqcp(1, true); + reg.set_rqcp(2, true); + }); } } /// Interface to receiver FIFO 0. pub struct Rx0 { _can: PhantomData, + canregs: crate::pac::can::Can, } impl Rx0 where I: Instance, { - unsafe fn conjure() -> Self { - Self { _can: PhantomData } - } - - /// Creates a `&mut Self` out of thin air. - /// - /// This is only safe if it is the only way to access an `Rx`. - unsafe fn conjure_by_ref<'a>() -> &'a mut Self { - // Cause out of bounds access when `Self` is not zero-sized. - [()][core::mem::size_of::()]; - - // Any aligned pointer is valid for ZSTs. - &mut *NonNull::dangling().as_ptr() + unsafe fn conjure(canregs: crate::pac::can::Can) -> Self { + Self { + _can: PhantomData, + canregs, + } } /// Returns a received frame if available. /// /// Returns `Err` when a frame was lost due to buffer overrun. pub fn receive(&mut self) -> nb::Result { - receive_fifo(self.registers(), 0) - } - - fn registers(&self) -> &RegisterBlock { - unsafe { &*I::REGISTERS } + receive_fifo(self.canregs, 0) } } /// Interface to receiver FIFO 1. pub struct Rx1 { _can: PhantomData, + canregs: crate::pac::can::Can, } impl Rx1 where I: Instance, { - unsafe fn conjure() -> Self { - Self { _can: PhantomData } - } - - /// Creates a `&mut Self` out of thin air. - /// - /// This is only safe if it is the only way to access an `Rx`. - unsafe fn conjure_by_ref<'a>() -> &'a mut Self { - // Cause out of bounds access when `Self` is not zero-sized. - [()][core::mem::size_of::()]; - - // Any aligned pointer is valid for ZSTs. - &mut *NonNull::dangling().as_ptr() + unsafe fn conjure(canregs: crate::pac::can::Can) -> Self { + Self { + _can: PhantomData, + canregs, + } } /// Returns a received frame if available. /// /// Returns `Err` when a frame was lost due to buffer overrun. pub fn receive(&mut self) -> nb::Result { - receive_fifo(self.registers(), 1) - } - - fn registers(&self) -> &RegisterBlock { - unsafe { &*I::REGISTERS } + receive_fifo(self.canregs, 1) } } -fn receive_fifo(can: &RegisterBlock, fifo_nr: usize) -> nb::Result { +fn receive_fifo(canregs: crate::pac::can::Can, fifo_nr: usize) -> nb::Result { assert!(fifo_nr < 2); - let rfr = &can.rfr[fifo_nr]; - let rx = &can.rx[fifo_nr]; + let rfr = canregs.rfr(fifo_nr); + let rx = canregs.rx(fifo_nr); + + //let rfr = &can.rfr[fifo_nr]; + //let rx = &can.rx[fifo_nr]; // Check if a frame is available in the mailbox. let rfr_read = rfr.read(); - if rfr_read.fmp().bits() == 0 { + if rfr_read.fmp() == 0 { return Err(nb::Error::WouldBlock); } // Check for RX FIFO overrun. - if rfr_read.fovr().bit_is_set() { - rfr.write(|w| w.fovr().set_bit()); + if rfr_read.fovr() { + rfr.write(|w| w.set_fovr(true)); return Err(nb::Error::Other(OverrunError { _priv: () })); } // Read the frame. let mut frame = Frame { - id: IdReg(rx.rir.read().bits()), + id: IdReg(rx.rir().read().0), data: [0; 8].into(), }; - frame.data[0..4].copy_from_slice(&rx.rdlr.read().bits().to_ne_bytes()); - frame.data[4..8].copy_from_slice(&rx.rdhr.read().bits().to_ne_bytes()); - frame.data.len = rx.rdtr.read().dlc().bits(); + frame.data[0..4].copy_from_slice(&rx.rdlr().read().0.to_ne_bytes()); + frame.data[4..8].copy_from_slice(&rx.rdhr().read().0.to_ne_bytes()); + frame.data.len = rx.rdtr().read().dlc(); // Release the mailbox. - rfr.write(|w| w.rfom().set_bit()); + rfr.write(|w| w.set_rfom(true)); Ok(frame) } diff --git a/embassy-stm32/src/can/bxcan.rs b/embassy-stm32/src/can/bxcan.rs index cd394c951..3a3411aaa 100644 --- a/embassy-stm32/src/can/bxcan.rs +++ b/embassy-stm32/src/can/bxcan.rs @@ -167,21 +167,14 @@ impl<'d, T: Instance> Can<'d, T> { rx.set_as_af(rx.af_num(), AFType::Input); tx.set_as_af(tx.af_num(), AFType::OutputPushPull); - let can = crate::can::bx::Can::builder(BxcanInstance(peri)).leave_disabled(); + let can = crate::can::bx::Can::builder(BxcanInstance(peri), T::regs()).leave_disabled(); Self { can } } /// Set CAN bit rate. pub fn set_bitrate(&mut self, bitrate: u32) { let bit_timing = util::calc_can_timings(T::frequency(), bitrate).unwrap(); - let sjw = u8::from(bit_timing.sync_jump_width) as u32; - let seg1 = u8::from(bit_timing.seg1) as u32; - let seg2 = u8::from(bit_timing.seg2) as u32; - let prescaler = u16::from(bit_timing.prescaler) as u32; - self.can - .modify_config() - .set_bit_timing((sjw - 1) << 24 | (seg1 - 1) << 16 | (seg2 - 1) << 20 | (prescaler - 1)) - .leave_disabled(); + self.can.modify_config().set_bit_timing(bit_timing).leave_disabled(); } /// Enables the peripheral and synchronizes with the bus. @@ -299,7 +292,7 @@ impl<'d, T: Instance> Can<'d, T> { /// Split the CAN driver into transmit and receive halves. /// /// Useful for doing separate transmit/receive tasks. - pub fn split<'c>(&'c mut self) -> (CanTx<'c, 'd, T>, CanRx<'c, 'd, T>) { + pub fn split<'c>(&'c mut self) -> (CanTx<'d, T>, CanRx<'d, T>) { let (tx, rx0, rx1) = self.can.split_by_ref(); (CanTx { tx }, CanRx { rx0, rx1 }) } @@ -313,11 +306,11 @@ impl<'d, T: Instance> AsMut>> for Can<' } /// CAN driver, transmit half. -pub struct CanTx<'c, 'd, T: Instance> { - tx: &'c mut crate::can::bx::Tx>, +pub struct CanTx<'d, T: Instance> { + tx: crate::can::bx::Tx>, } -impl<'c, 'd, T: Instance> CanTx<'c, 'd, T> { +impl<'d, T: Instance> CanTx<'d, T> { /// Queues the message to be sent. /// /// If the TX queue is full, this will wait until there is space, therefore exerting backpressure. @@ -404,12 +397,12 @@ impl<'c, 'd, T: Instance> CanTx<'c, 'd, T> { /// CAN driver, receive half. #[allow(dead_code)] -pub struct CanRx<'c, 'd, T: Instance> { - rx0: &'c mut crate::can::bx::Rx0>, - rx1: &'c mut crate::can::bx::Rx1>, +pub struct CanRx<'d, T: Instance> { + rx0: crate::can::bx::Rx0>, + rx1: crate::can::bx::Rx1>, } -impl<'c, 'd, T: Instance> CanRx<'c, 'd, T> { +impl<'d, T: Instance> CanRx<'d, T> { /// Read a CAN frame. /// /// If no CAN frame is in the RX buffer, this will wait until there is one.