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 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<I: FilterOwner> 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<I: FilterOwner> 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<I: MasterInstance> 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<I: MasterInstance> 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<I: MasterInstance> MasterFilters<'_, I> {
impl<I: FilterOwner> 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<I: Instance> 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<I: Instance> 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();
self.canregs.ffa1r().modify(|reg| {
reg.set_ffa(
index as usize,
match fifo {
Fifo::Fifo0 => bits &= !(1 << index),
Fifo::Fifo1 => bits |= 1 << index,
}
w.bits(bits)
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))
}
}

View file

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

View file

@ -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<I: Instance> 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<I: Instance> 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<I: Instance> 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<I: Instance> CanBuilder<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(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<I: Instance> CanBuilder<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
}
@ -403,11 +405,13 @@ impl<I: Instance> CanBuilder<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;
}
}
@ -417,6 +421,7 @@ impl<I: Instance> CanBuilder<I> {
/// Interface to a bxCAN peripheral.
pub struct Can<I: Instance> {
instance: I,
canregs: crate::pac::can::Can,
}
impl<I> Can<I>
@ -424,15 +429,18 @@ where
I: Instance,
{
/// Creates a [`CanBuilder`] for constructing a CAN interface.
pub fn builder(instance: I) -> CanBuilder<I> {
let can_builder = CanBuilder { can: Can { instance } };
pub fn builder(instance: I, canregs: crate::pac::can::Can) -> CanBuilder<I> {
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<TransmitStatus, Infallible> {
// 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.
pub fn is_transmitter_idle(&self) -> bool {
// 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.
@ -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::<I>::conjure().abort(mailbox) }
unsafe { Tx::<I>::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<Frame, OverrunError> {
// Safety: We have a `&mut self` and have unique access to the peripheral.
let mut rx0 = unsafe { Rx0::<I>::conjure() };
let mut rx1 = unsafe { Rx1::<I>::conjure() };
let mut rx0 = unsafe { Rx0::<I>::conjure(self.canregs) };
let mut rx1 = unsafe { Rx1::<I>::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<I> {
pub fn rx0(&mut self) -> Rx0<I> {
// 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<I> {
pub fn rx1(&mut self) -> Rx1<I> {
// 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<I>, &mut Rx0<I>, &mut Rx1<I>) {
pub fn split_by_ref(&mut self) -> (Tx<I>, Rx0<I>, Rx1<I>) {
// 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<I>, Rx0<I>, Rx1<I>) {
// 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
/// 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<I> {
_can: PhantomData<I>,
}
#[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<I> Tx<I>
where
I: Instance,
{
unsafe fn conjure() -> Self {
Self { _can: PhantomData }
unsafe fn conjure(canregs: crate::pac::can::Can) -> Self {
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.
@ -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<TransmitStatus, Infallible> {
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<Frame> {
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<I> {
_can: PhantomData<I>,
canregs: crate::pac::can::Can,
}
impl<I> Rx0<I>
where
I: Instance,
{
unsafe fn conjure() -> Self {
Self { _can: PhantomData }
unsafe fn conjure(canregs: crate::pac::can::Can) -> Self {
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 `Err` when a frame was lost due to buffer overrun.
pub fn receive(&mut self) -> nb::Result<Frame, OverrunError> {
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<I> {
_can: PhantomData<I>,
canregs: crate::pac::can::Can,
}
impl<I> Rx1<I>
where
I: Instance,
{
unsafe fn conjure() -> Self {
Self { _can: PhantomData }
unsafe fn conjure(canregs: crate::pac::can::Can) -> Self {
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 `Err` when a frame was lost due to buffer overrun.
pub fn receive(&mut self) -> nb::Result<Frame, OverrunError> {
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<Frame, OverrunError> {
fn receive_fifo(canregs: crate::pac::can::Can, fifo_nr: usize) -> nb::Result<Frame, OverrunError> {
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)
}

View file

@ -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<crate::can::bx::Can<BxcanInstance<'d, T>>> for Can<'
}
/// CAN driver, transmit half.
pub struct CanTx<'c, 'd, T: Instance> {
tx: &'c mut crate::can::bx::Tx<BxcanInstance<'d, T>>,
pub struct CanTx<'d, T: Instance> {
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.
///
/// 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<BxcanInstance<'d, T>>,
rx1: &'c mut crate::can::bx::Rx1<BxcanInstance<'d, T>>,
pub struct CanRx<'d, T: Instance> {
rx0: crate::can::bx::Rx0<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.
///
/// If no CAN frame is in the RX buffer, this will wait until there is one.