Port registers access to using Embassy PAC

Use stm32-metapac for filters module.
This commit is contained in:
Corey Schuhen 2024-03-03 20:27:08 +10:00
parent b0f05e7682
commit 455cc40261
4 changed files with 218 additions and 279 deletions

View file

@ -2,7 +2,6 @@
use core::marker::PhantomData; use core::marker::PhantomData;
use crate::can::bx::pac::can::RegisterBlock;
use crate::can::bx::{ExtendedId, Fifo, FilterOwner, Id, Instance, MasterInstance, StandardId}; use crate::can::bx::{ExtendedId, Fifo, FilterOwner, Id, Instance, MasterInstance, StandardId};
const F32_RTR: u32 = 0b010; // set the RTR bit to match remote frames 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. /// On chips with splittable filter banks, this value can be dynamic.
bank_count: u8, bank_count: u8,
_can: PhantomData<&'a mut I>, _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 // NOTE: This type mutably borrows the CAN instance and has unique access to the registers while it
// exists. // exists.
impl<I: FilterOwner> MasterFilters<'_, I> { impl<I: FilterOwner> MasterFilters<'_, I> {
pub(crate) unsafe fn new() -> Self { pub(crate) unsafe fn new(canregs: crate::pac::can::Can) -> Self {
let can = &*I::REGISTERS;
// Enable initialization mode. // Enable initialization mode.
can.fmr.modify(|_, w| w.finit().set_bit()); canregs.fmr().modify(|reg| reg.set_finit(true));
// Read the filter split value. // 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 // (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 // of them to the master peripheral, and in devices with 28, assigns them 50/50 to
@ -234,18 +232,15 @@ impl<I: FilterOwner> MasterFilters<'_, I> {
Self { Self {
bank_count, bank_count,
_can: PhantomData, _can: PhantomData,
canregs,
} }
} }
fn registers(&self) -> &RegisterBlock { fn banks_imm(&self) -> FilterBanks {
unsafe { &*I::REGISTERS }
}
fn banks_imm(&self) -> FilterBanks<'_> {
FilterBanks { FilterBanks {
start_idx: 0, start_idx: 0,
bank_count: self.bank_count, bank_count: self.bank_count,
can: self.registers(), canregs: self.canregs,
} }
} }
@ -296,9 +291,7 @@ impl<I: MasterInstance> MasterFilters<'_, I> {
/// Sets the index at which the filter banks owned by the slave peripheral start. /// 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 { pub fn set_split(&mut self, split_index: u8) -> &mut Self {
assert!(split_index <= I::NUM_FILTER_BANKS); assert!(split_index <= I::NUM_FILTER_BANKS);
self.registers() self.canregs.fmr().modify(|reg| reg.set_can2sb(split_index));
.fmr
.modify(|_, w| unsafe { w.can2sb().bits(split_index) });
self.bank_count = split_index; self.bank_count = split_index;
self self
} }
@ -310,6 +303,7 @@ impl<I: MasterInstance> MasterFilters<'_, I> {
start_idx: self.bank_count, start_idx: self.bank_count,
bank_count: I::NUM_FILTER_BANKS - self.bank_count, bank_count: I::NUM_FILTER_BANKS - self.bank_count,
_can: PhantomData, _can: PhantomData,
canregs: self.canregs,
} }
} }
} }
@ -317,10 +311,8 @@ impl<I: MasterInstance> MasterFilters<'_, I> {
impl<I: FilterOwner> Drop for MasterFilters<'_, I> { impl<I: FilterOwner> Drop for MasterFilters<'_, I> {
#[inline] #[inline]
fn drop(&mut self) { fn drop(&mut self) {
let can = self.registers();
// Leave initialization mode. // 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, start_idx: u8,
bank_count: u8, bank_count: u8,
_can: PhantomData<&'a mut I>, _can: PhantomData<&'a mut I>,
canregs: crate::pac::can::Can,
} }
impl<I: Instance> SlaveFilters<'_, I> { impl<I: Instance> SlaveFilters<'_, I> {
fn registers(&self) -> &RegisterBlock { fn banks_imm(&self) -> FilterBanks {
unsafe { &*I::REGISTERS }
}
fn banks_imm(&self) -> FilterBanks<'_> {
FilterBanks { FilterBanks {
start_idx: self.start_idx, start_idx: self.start_idx,
bank_count: self.bank_count, bank_count: self.bank_count,
can: self.registers(), canregs: self.canregs,
} }
} }
@ -381,20 +370,22 @@ impl<I: Instance> SlaveFilters<'_, I> {
} }
} }
struct FilterBanks<'a> { struct FilterBanks {
start_idx: u8, start_idx: u8,
bank_count: u8, bank_count: u8,
can: &'a RegisterBlock, canregs: crate::pac::can::Can,
} }
impl FilterBanks<'_> { impl FilterBanks {
fn clear(&mut self) { fn clear(&mut self) {
let mask = filter_bitmask(self.start_idx, self.bank_count); let mask = filter_bitmask(self.start_idx, self.bank_count);
self.can.fa1r.modify(|r, w| { self.canregs.fa1r().modify(|reg| {
let bits = r.bits(); for i in 0..28usize {
// Clear all bits in `mask`. if (0x01u32 << i) & mask != 0 {
unsafe { w.bits(bits & !mask) } reg.set_fact(i, false);
}
}
}); });
} }
@ -404,8 +395,7 @@ impl FilterBanks<'_> {
fn disable(&mut self, index: u8) { fn disable(&mut self, index: u8) {
self.assert_bank_index(index); self.assert_bank_index(index);
self.canregs.fa1r().modify(|reg| reg.set_fact(index as usize, false))
self.can.fa1r.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << index)) })
} }
fn enable(&mut self, index: u8, fifo: Fifo, config: BankConfig) { fn enable(&mut self, index: u8, fifo: Fifo, config: BankConfig) {
@ -413,27 +403,11 @@ impl FilterBanks<'_> {
// Configure mode. // Configure mode.
let mode = matches!(config, BankConfig::List16(_) | BankConfig::List32(_)); let mode = matches!(config, BankConfig::List16(_) | BankConfig::List32(_));
self.can.fm1r.modify(|r, w| { self.canregs.fm1r().modify(|reg| reg.set_fbm(index as usize, mode));
let mut bits = r.bits();
if mode {
bits |= 1 << index;
} else {
bits &= !(1 << index);
}
unsafe { w.bits(bits) }
});
// Configure scale. // Configure scale.
let scale = matches!(config, BankConfig::List32(_) | BankConfig::Mask32(_)); let scale = matches!(config, BankConfig::List32(_) | BankConfig::Mask32(_));
self.can.fs1r.modify(|r, w| { self.canregs.fs1r().modify(|reg| reg.set_fsc(index as usize, scale));
let mut bits = r.bits();
if scale {
bits |= 1 << index;
} else {
bits &= !(1 << index);
}
unsafe { w.bits(bits) }
});
// Configure filter register. // Configure filter register.
let (fxr1, fxr2); let (fxr1, fxr2);
@ -455,22 +429,23 @@ impl FilterBanks<'_> {
fxr2 = a.mask; fxr2 = a.mask;
} }
}; };
let bank = &self.can.fb[usize::from(index)]; let bank = self.canregs.fb(index as usize);
bank.fr1.write(|w| unsafe { w.bits(fxr1) }); bank.fr1().write(|w| w.0 = fxr1);
bank.fr2.write(|w| unsafe { w.bits(fxr2) }); bank.fr2().write(|w| w.0 = fxr2);
// Assign to the right FIFO // Assign to the right FIFO
self.can.ffa1r.modify(|r, w| unsafe { self.canregs.ffa1r().modify(|reg| {
let mut bits = r.bits(); reg.set_ffa(
index as usize,
match fifo { match fifo {
Fifo::Fifo0 => bits &= !(1 << index), Fifo::Fifo0 => false,
Fifo::Fifo1 => bits |= 1 << index, Fifo::Fifo1 => true,
} },
w.bits(bits) )
}); });
// Set active. // 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))
} }
} }

View file

@ -1,5 +1,4 @@
#[cfg(test)] #[cfg(test)]
use core::cmp::Ordering; use core::cmp::Ordering;
use core::ops::{Deref, DerefMut}; use core::ops::{Deref, DerefMut};

View file

@ -35,7 +35,6 @@ use core::cmp::{Ord, Ordering};
use core::convert::{Infallible, TryInto}; use core::convert::{Infallible, TryInto};
use core::marker::PhantomData; use core::marker::PhantomData;
use core::mem; use core::mem;
use core::ptr::NonNull;
pub use id::{ExtendedId, Id, StandardId}; pub use id::{ExtendedId, Id, StandardId};
@ -125,7 +124,7 @@ pub struct OverrunError {
/// priority than remote frames. /// priority than remote frames.
#[derive(Clone, Copy, Debug, PartialEq, Eq)] #[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
struct IdReg(u32); pub(crate) struct IdReg(u32);
impl IdReg { impl IdReg {
const STANDARD_SHIFT: u32 = 21; const STANDARD_SHIFT: u32 = 21;
@ -243,23 +242,25 @@ impl<I: Instance> CanConfig<'_, I> {
/// ///
/// Then copy the `CAN_BUS_TIME` register value from the table and pass it as the `btr` /// Then copy the `CAN_BUS_TIME` register value from the table and pass it as the `btr`
/// parameter to this method. /// parameter to this method.
pub fn set_bit_timing(self, btr: u32) -> Self { pub fn set_bit_timing(self, bt: crate::can::util::NominalBitTiming) -> Self {
self.can.set_bit_timing(btr); self.can.set_bit_timing(bt);
self self
} }
/// Enables or disables loopback mode: Internally connects the TX and RX /// Enables or disables loopback mode: Internally connects the TX and RX
/// signals together. /// signals together.
pub fn set_loopback(self, enabled: bool) -> Self { pub fn set_loopback(self, enabled: bool) -> Self {
let can = self.can.registers(); self.can.canregs.btr().modify(|reg| reg.set_lbkm(enabled));
can.btr.modify(|_, w| w.lbkm().bit(enabled));
self self
} }
/// Enables or disables silent mode: Disconnects the TX signal from the pin. /// Enables or disables silent mode: Disconnects the TX signal from the pin.
pub fn set_silent(self, enabled: bool) -> Self { pub fn set_silent(self, enabled: bool) -> Self {
let can = self.can.registers(); let mode = match enabled {
can.btr.modify(|_, w| w.silm().bit(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 self
} }
@ -270,8 +271,7 @@ impl<I: Instance> CanConfig<'_, I> {
/// ///
/// Automatic retransmission is enabled by default. /// Automatic retransmission is enabled by default.
pub fn set_automatic_retransmit(self, enabled: bool) -> Self { pub fn set_automatic_retransmit(self, enabled: bool) -> Self {
let can = self.can.registers(); self.can.canregs.mcr().modify(|reg| reg.set_nart(enabled));
can.mcr.modify(|_, w| w.nart().bit(!enabled));
self self
} }
@ -304,11 +304,13 @@ impl<I: Instance> CanConfig<'_, I> {
/// Leaves initialization mode, enters sleep mode. /// Leaves initialization mode, enters sleep mode.
fn leave_init_mode(&mut self) { fn leave_init_mode(&mut self) {
let can = self.can.registers(); self.can.canregs.mcr().modify(|reg| {
can.mcr.modify(|_, w| w.sleep().set_bit().inrq().clear_bit()); reg.set_sleep(true);
reg.set_inrq(false);
});
loop { loop {
let msr = can.msr.read(); let msr = self.can.canregs.msr().read();
if msr.slak().bit_is_set() && msr.inak().bit_is_clear() { if msr.slak() && !msr.inak() {
break; break;
} }
} }
@ -341,23 +343,24 @@ impl<I: Instance> CanBuilder<I> {
/// ///
/// Then copy the `CAN_BUS_TIME` register value from the table and pass it as the `btr` /// Then copy the `CAN_BUS_TIME` register value from the table and pass it as the `btr`
/// parameter to this method. /// parameter to this method.
pub fn set_bit_timing(mut self, btr: u32) -> Self { pub fn set_bit_timing(mut self, bt: crate::can::util::NominalBitTiming) -> Self {
self.can.set_bit_timing(btr); self.can.set_bit_timing(bt);
self self
} }
/// Enables or disables loopback mode: Internally connects the TX and RX /// Enables or disables loopback mode: Internally connects the TX and RX
/// signals together. /// signals together.
pub fn set_loopback(self, enabled: bool) -> Self { pub fn set_loopback(self, enabled: bool) -> Self {
let can = self.can.registers(); self.can.canregs.btr().modify(|reg| reg.set_lbkm(enabled));
can.btr.modify(|_, w| w.lbkm().bit(enabled));
self self
} }
/// Enables or disables silent mode: Disconnects the TX signal from the pin. /// Enables or disables silent mode: Disconnects the TX signal from the pin.
pub fn set_silent(self, enabled: bool) -> Self { pub fn set_silent(self, enabled: bool) -> Self {
let can = self.can.registers(); let mode = match enabled {
can.btr.modify(|_, w| w.silm().bit(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 self
} }
@ -368,8 +371,7 @@ impl<I: Instance> CanBuilder<I> {
/// ///
/// Automatic retransmission is enabled by default. /// Automatic retransmission is enabled by default.
pub fn set_automatic_retransmit(self, enabled: bool) -> Self { pub fn set_automatic_retransmit(self, enabled: bool) -> Self {
let can = self.can.registers(); self.can.canregs.mcr().modify(|reg| reg.set_nart(enabled));
can.mcr.modify(|_, w| w.nart().bit(!enabled));
self self
} }
@ -403,11 +405,13 @@ impl<I: Instance> CanBuilder<I> {
/// Leaves initialization mode, enters sleep mode. /// Leaves initialization mode, enters sleep mode.
fn leave_init_mode(&mut self) { fn leave_init_mode(&mut self) {
let can = self.can.registers(); self.can.canregs.mcr().modify(|reg| {
can.mcr.modify(|_, w| w.sleep().set_bit().inrq().clear_bit()); reg.set_sleep(true);
reg.set_inrq(false);
});
loop { loop {
let msr = can.msr.read(); let msr = self.can.canregs.msr().read();
if msr.slak().bit_is_set() && msr.inak().bit_is_clear() { if msr.slak() && !msr.inak() {
break; break;
} }
} }
@ -417,6 +421,7 @@ impl<I: Instance> CanBuilder<I> {
/// Interface to a bxCAN peripheral. /// Interface to a bxCAN peripheral.
pub struct Can<I: Instance> { pub struct Can<I: Instance> {
instance: I, instance: I,
canregs: crate::pac::can::Can,
} }
impl<I> Can<I> impl<I> Can<I>
@ -424,15 +429,18 @@ where
I: Instance, I: Instance,
{ {
/// Creates a [`CanBuilder`] for constructing a CAN interface. /// Creates a [`CanBuilder`] for constructing a CAN interface.
pub fn builder(instance: I) -> CanBuilder<I> { pub fn builder(instance: I, canregs: crate::pac::can::Can) -> CanBuilder<I> {
let can_builder = CanBuilder { can: Can { instance } }; let can_builder = CanBuilder {
can: Can { instance, canregs },
};
let can_reg = can_builder.can.registers(); canregs.mcr().modify(|reg| {
// Enter init mode. reg.set_sleep(false);
can_reg.mcr.modify(|_, w| w.sleep().clear_bit().inrq().set_bit()); reg.set_inrq(true);
});
loop { loop {
let msr = can_reg.msr.read(); let msr = canregs.msr().read();
if msr.slak().bit_is_clear() && msr.inak().bit_is_set() { if !msr.slak() && msr.inak() {
break; break;
} }
} }
@ -440,18 +448,16 @@ where
can_builder can_builder
} }
fn registers(&self) -> &RegisterBlock { fn set_bit_timing(&mut self, bt: crate::can::util::NominalBitTiming) {
unsafe { &*I::REGISTERS } let prescaler = u16::from(bt.prescaler) & 0x1FF;
} let seg1 = u8::from(bt.seg1);
let seg2 = u8::from(bt.seg2) & 0x7F;
fn set_bit_timing(&mut self, btr: u32) { let sync_jump_width = u8::from(bt.sync_jump_width) & 0x7F;
// Mask of all non-reserved BTR bits, except the mode flags. self.canregs.btr().modify(|reg| {
const MASK: u32 = 0x037F_03FF; reg.set_brp(prescaler - 1);
reg.set_ts(0, seg1 - 1);
let can = self.registers(); reg.set_ts(1, seg2 - 1);
can.btr.modify(|r, w| unsafe { reg.set_sjw(sync_jump_width - 1);
let mode_bits = r.bits() & 0xC000_0000;
w.bits(mode_bits | (btr & MASK))
}); });
} }
@ -467,7 +473,7 @@ where
/// The peripheral is disabled by setting `RESET` in `CAN_MCR`, which causes the peripheral to /// The peripheral is disabled by setting `RESET` in `CAN_MCR`, which causes the peripheral to
/// enter sleep mode. /// enter sleep mode.
pub fn free(self) -> I { 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 self.instance
} }
@ -475,13 +481,13 @@ where
/// ///
/// Calling this method will enter initialization mode. /// Calling this method will enter initialization mode.
pub fn modify_config(&mut self) -> CanConfig<'_, I> { pub fn modify_config(&mut self) -> CanConfig<'_, I> {
let can = self.registers(); self.canregs.mcr().modify(|reg| {
reg.set_sleep(false);
// Enter init mode. reg.set_inrq(true);
can.mcr.modify(|_, w| w.sleep().clear_bit().inrq().set_bit()); });
loop { loop {
let msr = can.msr.read(); let msr = self.canregs.msr().read();
if msr.slak().bit_is_clear() && msr.inak().bit_is_set() { if !msr.slak() && msr.inak() {
break; break;
} }
} }
@ -497,8 +503,7 @@ where
/// receive the frame. If enabled, [`Interrupt::Wakeup`] will also be triggered by the incoming /// receive the frame. If enabled, [`Interrupt::Wakeup`] will also be triggered by the incoming
/// frame. /// frame.
pub fn set_automatic_wakeup(&mut self, enabled: bool) { pub fn set_automatic_wakeup(&mut self, enabled: bool) {
let can = self.registers(); self.canregs.mcr().modify(|reg| reg.set_awum(enabled));
can.mcr.modify(|_, w| w.awum().bit(enabled));
} }
/// Leaves initialization mode and enables the peripheral (non-blocking version). /// 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 /// in the background. The peripheral is enabled and ready to use when this method returns
/// successfully. /// successfully.
pub fn enable_non_blocking(&mut self) -> nb::Result<(), Infallible> { pub fn enable_non_blocking(&mut self) -> nb::Result<(), Infallible> {
let can = self.registers(); let msr = self.canregs.msr().read();
let msr = can.msr.read(); if msr.slak() {
if msr.slak().bit_is_set() { self.canregs.mcr().modify(|reg| {
can.mcr.modify(|_, w| w.abom().set_bit().sleep().clear_bit()); reg.set_abom(true);
reg.set_sleep(false);
});
Err(nb::Error::WouldBlock) Err(nb::Error::WouldBlock)
} else { } else {
Ok(()) Ok(())
@ -524,11 +531,13 @@ where
/// ///
/// While in sleep mode, an incoming CAN frame will trigger [`Interrupt::Wakeup`] if enabled. /// While in sleep mode, an incoming CAN frame will trigger [`Interrupt::Wakeup`] if enabled.
pub fn sleep(&mut self) { pub fn sleep(&mut self) {
let can = self.registers(); self.canregs.mcr().modify(|reg| {
can.mcr.modify(|_, w| w.sleep().set_bit().inrq().clear_bit()); reg.set_sleep(true);
reg.set_inrq(false);
});
loop { loop {
let msr = can.msr.read(); let msr = self.canregs.msr().read();
if msr.slak().bit_is_set() && msr.inak().bit_is_clear() { if msr.slak() && !msr.inak() {
break; break;
} }
} }
@ -539,11 +548,13 @@ where
/// Note that this will not trigger [`Interrupt::Wakeup`], only reception of an incoming CAN /// Note that this will not trigger [`Interrupt::Wakeup`], only reception of an incoming CAN
/// frame will cause that interrupt. /// frame will cause that interrupt.
pub fn wakeup(&mut self) { pub fn wakeup(&mut self) {
let can = self.registers(); self.canregs.mcr().modify(|reg| {
can.mcr.modify(|_, w| w.sleep().clear_bit().inrq().clear_bit()); reg.set_sleep(false);
reg.set_inrq(false);
});
loop { loop {
let msr = can.msr.read(); let msr = self.canregs.msr().read();
if msr.slak().bit_is_clear() && msr.inak().bit_is_clear() { if !msr.slak() && !msr.inak() {
break; break;
} }
} }
@ -560,13 +571,13 @@ where
/// [`TransmitStatus::dequeued_frame`]. /// [`TransmitStatus::dequeued_frame`].
pub fn transmit(&mut self, frame: &Frame) -> nb::Result<TransmitStatus, Infallible> { pub fn transmit(&mut self, frame: &Frame) -> nb::Result<TransmitStatus, Infallible> {
// Safety: We have a `&mut self` and have unique access to the peripheral. // Safety: We have a `&mut self` and have unique access to the peripheral.
unsafe { Tx::<I>::conjure().transmit(frame) } unsafe { Tx::<I>::conjure(self.canregs).transmit(frame) }
} }
/// Returns `true` if no frame is pending for transmission. /// Returns `true` if no frame is pending for transmission.
pub fn is_transmitter_idle(&self) -> bool { pub fn is_transmitter_idle(&self) -> bool {
// Safety: Read-only operation. // Safety: Read-only operation.
unsafe { Tx::<I>::conjure().is_idle() } unsafe { Tx::<I>::conjure(self.canregs).is_idle() }
} }
/// Attempts to abort the sending of a frame that is pending in a mailbox. /// Attempts to abort the sending of a frame that is pending in a mailbox.
@ -578,7 +589,7 @@ where
/// returns `true`. /// returns `true`.
pub fn abort(&mut self, mailbox: Mailbox) -> bool { pub fn abort(&mut self, mailbox: Mailbox) -> bool {
// Safety: We have a `&mut self` and have unique access to the peripheral. // Safety: We have a `&mut self` and have unique access to the peripheral.
unsafe { Tx::<I>::conjure().abort(mailbox) } unsafe { Tx::<I>::conjure(self.canregs).abort(mailbox) }
} }
/// Returns a received frame if available. /// Returns a received frame if available.
@ -589,8 +600,8 @@ where
/// Returns `Err` when a frame was lost due to buffer overrun. /// Returns `Err` when a frame was lost due to buffer overrun.
pub fn receive(&mut self) -> nb::Result<Frame, OverrunError> { pub fn receive(&mut self) -> nb::Result<Frame, OverrunError> {
// Safety: We have a `&mut self` and have unique access to the peripheral. // Safety: We have a `&mut self` and have unique access to the peripheral.
let mut rx0 = unsafe { Rx0::<I>::conjure() }; let mut rx0 = unsafe { Rx0::<I>::conjure(self.canregs) };
let mut rx1 = unsafe { Rx1::<I>::conjure() }; let mut rx1 = unsafe { Rx1::<I>::conjure(self.canregs) };
match rx0.receive() { match rx0.receive() {
Err(nb::Error::WouldBlock) => rx1.receive(), Err(nb::Error::WouldBlock) => rx1.receive(),
@ -599,30 +610,35 @@ where
} }
/// Returns a reference to the RX FIFO 0. /// Returns a reference to the RX FIFO 0.
pub fn rx0(&mut self) -> &mut Rx0<I> { pub fn rx0(&mut self) -> Rx0<I> {
// Safety: We take `&mut self` and the return value lifetimes are tied to `self`'s lifetime. // 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. /// Returns a reference to the RX FIFO 1.
pub fn rx1(&mut self) -> &mut Rx1<I> { pub fn rx1(&mut self) -> Rx1<I> {
// Safety: We take `&mut self` and the return value lifetimes are tied to `self`'s lifetime. // 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) -> (Tx<I>, Rx0<I>, Rx1<I>) {
pub fn split_by_ref(&mut self) -> (&mut Tx<I>, &mut Rx0<I>, &mut Rx1<I>) {
// Safety: We take `&mut self` and the return value lifetimes are tied to `self`'s lifetime. // Safety: We take `&mut self` and the return value lifetimes are tied to `self`'s lifetime.
let tx = unsafe { Tx::conjure_by_ref() }; let tx = unsafe { Tx::conjure(self.canregs) };
let rx0 = unsafe { Rx0::conjure_by_ref() }; let rx0 = unsafe { Rx0::conjure(self.canregs) };
let rx1 = unsafe { Rx1::conjure_by_ref() }; let rx1 = unsafe { Rx1::conjure(self.canregs) };
(tx, rx0, rx1) (tx, rx0, rx1)
} }
/// Consumes this `Can` instance and splits it into transmitting and receiving halves. /// Consumes this `Can` instance and splits it into transmitting and receiving halves.
pub fn split(self) -> (Tx<I>, Rx0<I>, Rx1<I>) { pub fn split(self) -> (Tx<I>, Rx0<I>, Rx1<I>) {
// Safety: `Self` is not `Copy` and is destroyed by moving it into this method. // 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<I: FilterOwner> Can<I> {
/// To modify filters of a slave peripheral, `modify_filters` has to be called on the master /// To modify filters of a slave peripheral, `modify_filters` has to be called on the master
/// peripheral instead. /// peripheral instead.
pub fn modify_filters(&mut self) -> MasterFilters<'_, I> { pub fn modify_filters(&mut self) -> MasterFilters<'_, I> {
unsafe { MasterFilters::new() } unsafe { MasterFilters::new(self.canregs) }
} }
} }
/// Interface to the CAN transmitter part. /// Interface to the CAN transmitter part.
pub struct Tx<I> { pub struct Tx<I> {
_can: PhantomData<I>, _can: PhantomData<I>,
} canregs: crate::pac::can::Can,
#[inline]
const fn ok_mask(idx: usize) -> u32 {
0x02 << (8 * idx)
}
#[inline]
const fn abort_mask(idx: usize) -> u32 {
0x80 << (8 * idx)
} }
impl<I> Tx<I> impl<I> Tx<I>
where where
I: Instance, I: Instance,
{ {
unsafe fn conjure() -> Self { unsafe fn conjure(canregs: crate::pac::can::Can) -> Self {
Self { _can: PhantomData } Self {
_can: PhantomData,
canregs,
} }
/// Creates a `&mut Self` out of thin air.
///
/// This is only safe if it is the only way to access a `Tx<I>`.
unsafe fn conjure_by_ref<'a>() -> &'a mut Self {
// Cause out of bounds access when `Self` is not zero-sized.
[()][core::mem::size_of::<Self>()];
// Any aligned pointer is valid for ZSTs.
&mut *NonNull::dangling().as_ptr()
}
fn registers(&self) -> &RegisterBlock {
unsafe { &*I::REGISTERS }
} }
/// Puts a CAN frame in a transmit mailbox for transmission on the bus. /// 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 /// cancelled and `frame` is enqueued instead. The frame that was replaced is returned as
/// [`TransmitStatus::dequeued_frame`]. /// [`TransmitStatus::dequeued_frame`].
pub fn transmit(&mut self, frame: &Frame) -> nb::Result<TransmitStatus, Infallible> { pub fn transmit(&mut self, frame: &Frame) -> nb::Result<TransmitStatus, Infallible> {
let can = self.registers();
// Get the index of the next free mailbox or the one with the lowest priority. // Get the index of the next free mailbox or the one with the lowest priority.
let tsr = can.tsr.read(); let tsr = self.canregs.tsr().read();
let idx = tsr.code().bits() as usize; 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 { let pending_frame = if frame_is_pending {
// High priority frames are transmitted first by the mailbox system. // High priority frames are transmitted first by the mailbox system.
// Frames with identical identifier shall be transmitted in FIFO order. // Frames with identical identifier shall be transmitted in FIFO order.
@ -701,8 +694,7 @@ where
self.check_priority(1, frame.id)?; self.check_priority(1, frame.id)?;
self.check_priority(2, frame.id)?; self.check_priority(2, frame.id)?;
let all_frames_are_pending = let all_frames_are_pending = !tsr.tme(0) && !tsr.tme(1) && !tsr.tme(2);
tsr.tme0().bit_is_clear() && tsr.tme1().bit_is_clear() && tsr.tme2().bit_is_clear();
if all_frames_are_pending { if all_frames_are_pending {
// No free mailbox is available. This can only happen when three frames with // No free mailbox is available. This can only happen when three frames with
// ascending priority (descending IDs) were requested for transmission and all // 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 /// Returns `Ok` when the mailbox is free or if it contains pending frame with a
/// lower priority (higher ID) than the identifier `id`. /// lower priority (higher ID) than the identifier `id`.
fn check_priority(&self, idx: usize, id: IdReg) -> nb::Result<(), Infallible> { 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. // Read the pending frame's id to check its priority.
assert!(idx < 3); 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 // Check the priority by comparing the identifiers. But first make sure the
// frame has not finished the transmission (`TXRQ` == 0) in the meantime. // 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 // There's a mailbox whose priority is higher or equal
// the priority of the new frame. // the priority of the new frame.
return Err(nb::Error::WouldBlock); return Err(nb::Error::WouldBlock);
@ -753,33 +744,34 @@ where
} }
fn write_mailbox(&mut self, idx: usize, frame: &Frame) { fn write_mailbox(&mut self, idx: usize, frame: &Frame) {
let can = self.registers();
debug_assert!(idx < 3); debug_assert!(idx < 3);
let mb = unsafe { &can.tx.get_unchecked(idx) };
mb.tdtr.write(|w| unsafe { w.dlc().bits(frame.dlc() as u8) }); let mb = self.canregs.tx(idx);
mb.tdlr mb.tdtr().write(|w| w.set_dlc(frame.dlc() as u8));
.write(|w| unsafe { w.bits(u32::from_ne_bytes(frame.data.bytes[0..4].try_into().unwrap())) });
mb.tdhr mb.tdlr()
.write(|w| unsafe { w.bits(u32::from_ne_bytes(frame.data.bytes[4..8].try_into().unwrap())) }); .write(|w| w.0 = u32::from_ne_bytes(frame.data.bytes[0..4].try_into().unwrap()));
mb.tir.write(|w| unsafe { w.bits(frame.id.0).txrq().set_bit() }); 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<Frame> { fn read_pending_mailbox(&mut self, idx: usize) -> Option<Frame> {
if self.abort_by_index(idx) { if self.abort_by_index(idx) {
let can = self.registers();
debug_assert!(idx < 3); debug_assert!(idx < 3);
let mb = unsafe { &can.tx.get_unchecked(idx) };
let mb = self.canregs.tx(idx);
// Read back the pending frame. // Read back the pending frame.
let mut pending_frame = Frame { let mut pending_frame = Frame {
id: IdReg(mb.tir.read().bits()), id: IdReg(mb.tir().read().0),
data: Data::empty(), data: Data::empty(),
}; };
pending_frame.data.bytes[0..4].copy_from_slice(&mb.tdlr.read().bits().to_ne_bytes()); 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().bits().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().bits(); pending_frame.data.len = mb.tdtr().read().dlc();
Some(pending_frame) Some(pending_frame)
} else { } else {
@ -793,15 +785,13 @@ where
/// Tries to abort a pending frame. Returns `true` when aborted. /// Tries to abort a pending frame. Returns `true` when aborted.
fn abort_by_index(&mut self, idx: usize) -> bool { fn abort_by_index(&mut self, idx: usize) -> bool {
let can = self.registers(); self.canregs.tsr().write(|reg| reg.set_abrq(idx, true));
can.tsr.write(|w| unsafe { w.bits(abort_mask(idx)) });
// Wait for the abort request to be finished. // Wait for the abort request to be finished.
loop { loop {
let tsr = can.tsr.read().bits(); let tsr = self.canregs.tsr().read();
if tsr & abort_mask(idx) == 0 { if false == tsr.abrq(idx) {
break tsr & ok_mask(idx) == 0; break tsr.txok(idx) == false;
} }
} }
} }
@ -816,11 +806,11 @@ where
pub fn abort(&mut self, mailbox: Mailbox) -> bool { pub fn abort(&mut self, mailbox: Mailbox) -> bool {
// If the mailbox is empty, the value of TXOKx depends on what happened with the previous // 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. // 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 { let mailbox_empty = match mailbox {
Mailbox::Mailbox0 => tsr.tme0().bit_is_set(), Mailbox::Mailbox0 => tsr.tme(0),
Mailbox::Mailbox1 => tsr.tme1().bit_is_set(), Mailbox::Mailbox1 => tsr.tme(1),
Mailbox::Mailbox2 => tsr.tme2().bit_is_set(), Mailbox::Mailbox2 => tsr.tme(2),
}; };
if mailbox_empty { if mailbox_empty {
false false
@ -831,119 +821,101 @@ where
/// Returns `true` if no frame is pending for transmission. /// Returns `true` if no frame is pending for transmission.
pub fn is_idle(&self) -> bool { pub fn is_idle(&self) -> bool {
let can = self.registers(); let tsr = self.canregs.tsr().read();
let tsr = can.tsr.read(); tsr.tme(0) && tsr.tme(1) && tsr.tme(2)
tsr.tme0().bit_is_set() && tsr.tme1().bit_is_set() && tsr.tme2().bit_is_set()
} }
/// Clears the request complete flag for all mailboxes. /// Clears the request complete flag for all mailboxes.
pub fn clear_interrupt_flags(&mut self) { pub fn clear_interrupt_flags(&mut self) {
let can = self.registers(); self.canregs.tsr().write(|reg| {
can.tsr reg.set_rqcp(0, true);
.write(|w| w.rqcp2().set_bit().rqcp1().set_bit().rqcp0().set_bit()); reg.set_rqcp(1, true);
reg.set_rqcp(2, true);
});
} }
} }
/// Interface to receiver FIFO 0. /// Interface to receiver FIFO 0.
pub struct Rx0<I> { pub struct Rx0<I> {
_can: PhantomData<I>, _can: PhantomData<I>,
canregs: crate::pac::can::Can,
} }
impl<I> Rx0<I> impl<I> Rx0<I>
where where
I: Instance, I: Instance,
{ {
unsafe fn conjure() -> Self { unsafe fn conjure(canregs: crate::pac::can::Can) -> Self {
Self { _can: PhantomData } Self {
_can: PhantomData,
canregs,
} }
/// Creates a `&mut Self` out of thin air.
///
/// This is only safe if it is the only way to access an `Rx<I>`.
unsafe fn conjure_by_ref<'a>() -> &'a mut Self {
// Cause out of bounds access when `Self` is not zero-sized.
[()][core::mem::size_of::<Self>()];
// Any aligned pointer is valid for ZSTs.
&mut *NonNull::dangling().as_ptr()
} }
/// Returns a received frame if available. /// Returns a received frame if available.
/// ///
/// Returns `Err` when a frame was lost due to buffer overrun. /// Returns `Err` when a frame was lost due to buffer overrun.
pub fn receive(&mut self) -> nb::Result<Frame, OverrunError> { pub fn receive(&mut self) -> nb::Result<Frame, OverrunError> {
receive_fifo(self.registers(), 0) receive_fifo(self.canregs, 0)
}
fn registers(&self) -> &RegisterBlock {
unsafe { &*I::REGISTERS }
} }
} }
/// Interface to receiver FIFO 1. /// Interface to receiver FIFO 1.
pub struct Rx1<I> { pub struct Rx1<I> {
_can: PhantomData<I>, _can: PhantomData<I>,
canregs: crate::pac::can::Can,
} }
impl<I> Rx1<I> impl<I> Rx1<I>
where where
I: Instance, I: Instance,
{ {
unsafe fn conjure() -> Self { unsafe fn conjure(canregs: crate::pac::can::Can) -> Self {
Self { _can: PhantomData } Self {
_can: PhantomData,
canregs,
} }
/// Creates a `&mut Self` out of thin air.
///
/// This is only safe if it is the only way to access an `Rx<I>`.
unsafe fn conjure_by_ref<'a>() -> &'a mut Self {
// Cause out of bounds access when `Self` is not zero-sized.
[()][core::mem::size_of::<Self>()];
// Any aligned pointer is valid for ZSTs.
&mut *NonNull::dangling().as_ptr()
} }
/// Returns a received frame if available. /// Returns a received frame if available.
/// ///
/// Returns `Err` when a frame was lost due to buffer overrun. /// Returns `Err` when a frame was lost due to buffer overrun.
pub fn receive(&mut self) -> nb::Result<Frame, OverrunError> { pub fn receive(&mut self) -> nb::Result<Frame, OverrunError> {
receive_fifo(self.registers(), 1) receive_fifo(self.canregs, 1)
}
fn registers(&self) -> &RegisterBlock {
unsafe { &*I::REGISTERS }
} }
} }
fn receive_fifo(can: &RegisterBlock, fifo_nr: usize) -> nb::Result<Frame, OverrunError> { fn receive_fifo(canregs: crate::pac::can::Can, fifo_nr: usize) -> nb::Result<Frame, OverrunError> {
assert!(fifo_nr < 2); assert!(fifo_nr < 2);
let rfr = &can.rfr[fifo_nr]; let rfr = canregs.rfr(fifo_nr);
let rx = &can.rx[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. // Check if a frame is available in the mailbox.
let rfr_read = rfr.read(); let rfr_read = rfr.read();
if rfr_read.fmp().bits() == 0 { if rfr_read.fmp() == 0 {
return Err(nb::Error::WouldBlock); return Err(nb::Error::WouldBlock);
} }
// Check for RX FIFO overrun. // Check for RX FIFO overrun.
if rfr_read.fovr().bit_is_set() { if rfr_read.fovr() {
rfr.write(|w| w.fovr().set_bit()); rfr.write(|w| w.set_fovr(true));
return Err(nb::Error::Other(OverrunError { _priv: () })); return Err(nb::Error::Other(OverrunError { _priv: () }));
} }
// Read the frame. // Read the frame.
let mut frame = Frame { let mut frame = Frame {
id: IdReg(rx.rir.read().bits()), id: IdReg(rx.rir().read().0),
data: [0; 8].into(), data: [0; 8].into(),
}; };
frame.data[0..4].copy_from_slice(&rx.rdlr.read().bits().to_ne_bytes()); frame.data[0..4].copy_from_slice(&rx.rdlr().read().0.to_ne_bytes());
frame.data[4..8].copy_from_slice(&rx.rdhr.read().bits().to_ne_bytes()); frame.data[4..8].copy_from_slice(&rx.rdhr().read().0.to_ne_bytes());
frame.data.len = rx.rdtr.read().dlc().bits(); frame.data.len = rx.rdtr().read().dlc();
// Release the mailbox. // Release the mailbox.
rfr.write(|w| w.rfom().set_bit()); rfr.write(|w| w.set_rfom(true));
Ok(frame) Ok(frame)
} }

View file

@ -167,21 +167,14 @@ impl<'d, T: Instance> Can<'d, T> {
rx.set_as_af(rx.af_num(), AFType::Input); rx.set_as_af(rx.af_num(), AFType::Input);
tx.set_as_af(tx.af_num(), AFType::OutputPushPull); 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 } Self { can }
} }
/// Set CAN bit rate. /// Set CAN bit rate.
pub fn set_bitrate(&mut self, bitrate: u32) { pub fn set_bitrate(&mut self, bitrate: u32) {
let bit_timing = util::calc_can_timings(T::frequency(), bitrate).unwrap(); let bit_timing = util::calc_can_timings(T::frequency(), bitrate).unwrap();
let sjw = u8::from(bit_timing.sync_jump_width) as u32; self.can.modify_config().set_bit_timing(bit_timing).leave_disabled();
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();
} }
/// Enables the peripheral and synchronizes with the bus. /// 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. /// Split the CAN driver into transmit and receive halves.
/// ///
/// Useful for doing separate transmit/receive tasks. /// 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(); let (tx, rx0, rx1) = self.can.split_by_ref();
(CanTx { tx }, CanRx { rx0, rx1 }) (CanTx { tx }, CanRx { rx0, rx1 })
} }
@ -313,11 +306,11 @@ impl<'d, T: Instance> AsMut<crate::can::bx::Can<BxcanInstance<'d, T>>> for Can<'
} }
/// CAN driver, transmit half. /// CAN driver, transmit half.
pub struct CanTx<'c, 'd, T: Instance> { pub struct CanTx<'d, T: Instance> {
tx: &'c mut crate::can::bx::Tx<BxcanInstance<'d, T>>, tx: crate::can::bx::Tx<BxcanInstance<'d, T>>,
} }
impl<'c, 'd, T: Instance> CanTx<'c, 'd, T> { impl<'d, T: Instance> CanTx<'d, T> {
/// Queues the message to be sent. /// Queues the message to be sent.
/// ///
/// If the TX queue is full, this will wait until there is space, therefore exerting backpressure. /// 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. /// CAN driver, receive half.
#[allow(dead_code)] #[allow(dead_code)]
pub struct CanRx<'c, 'd, T: Instance> { pub struct CanRx<'d, T: Instance> {
rx0: &'c mut crate::can::bx::Rx0<BxcanInstance<'d, T>>, rx0: crate::can::bx::Rx0<BxcanInstance<'d, T>>,
rx1: &'c mut crate::can::bx::Rx1<BxcanInstance<'d, T>>, rx1: crate::can::bx::Rx1<BxcanInstance<'d, T>>,
} }
impl<'c, 'd, T: Instance> CanRx<'c, 'd, T> { impl<'d, T: Instance> CanRx<'d, T> {
/// Read a CAN frame. /// Read a CAN frame.
/// ///
/// If no CAN frame is in the RX buffer, this will wait until there is one. /// If no CAN frame is in the RX buffer, this will wait until there is one.