Skip to content

Commit

Permalink
use method chaining to configure both filters and can
Browse files Browse the repository at this point in the history
  • Loading branch information
xoviat committed Jan 22, 2021
1 parent 1d6f176 commit d2bb8dd
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 52 deletions.
3 changes: 2 additions & 1 deletion src/filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,12 +270,13 @@ impl<I: FilterOwner> MasterFilters<'_, I> {

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) {
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.bank_count = split_index;
self
}

/// Accesses the filters assigned to the slave peripheral.
Expand Down
52 changes: 41 additions & 11 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,14 +211,11 @@ impl PartialOrd for IdReg {
}

/// Configuration proxy to be used with `Can::configure()`.
pub struct CanConfig<I> {
_can: PhantomData<I>,
pub struct CanConfig<'a, I: Instance> {
_can: PhantomData<&'a mut I>,
}

impl<I> CanConfig<I>
where
I: Instance,
{
impl<I: Instance> CanConfig<'_, I> {
fn registers(&self) -> &RegisterBlock {
unsafe { &*I::REGISTERS }
}
Expand All @@ -235,25 +232,44 @@ where
///
/// 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) {
pub fn set_bit_timing(&mut self, btr: u32) -> &mut Self {
let can = self.registers();
can.btr.modify(|r, w| unsafe {
let mode_bits = r.bits() & 0xC000_0000;
w.bits(mode_bits | btr)
});
self
}

/// Enables or disables loopback mode: Internally connects the TX and RX
/// signals together.
pub fn set_loopback(&mut self, enabled: bool) {
pub fn set_loopback(&mut self, enabled: bool) -> &mut Self {
let can = self.registers();
can.btr.modify(|_, w| w.lbkm().bit(enabled));
self
}

/// Enables or disables silent mode: Disconnects the TX signal from the pin.
pub fn set_silent(&mut self, enabled: bool) {
pub fn set_silent(&mut self, enabled: bool) -> &mut Self {
let can = self.registers();
can.btr.modify(|_, w| w.silm().bit(enabled));
self
}
}

impl<I: Instance> Drop for CanConfig<'_, I> {
#[inline]
fn drop(&mut self) {
// Leave initialization mode
let can = self.registers();
can.mcr
.modify(|_, w| w.sleep().set_bit().inrq().clear_bit());
loop {
let msr = can.msr.read();
if msr.slak().bit_is_set() && msr.inak().bit_is_clear() {
break;
}
}
}
}

Expand Down Expand Up @@ -307,9 +323,23 @@ where

let mut config = CanConfig { _can: PhantomData };
f(&mut config);
}

/// Configure bit timings and silent/loop-back 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());
loop {
let msr = can.msr.read();
if msr.slak().bit_is_clear() && msr.inak().bit_is_set() {
break;
}
}

// Leave init mode: go back to sleep.
self.sleep();
CanConfig { _can: PhantomData }
}

/// Configures the automatic wake-up feature.
Expand Down
84 changes: 44 additions & 40 deletions testsuite/tests/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,15 @@ impl State {
let periph = defmt::unwrap!(pac::Peripherals::take());
let (can1, can2) = testsuite::init(periph);
let mut can1 = Can::new(can1);
can1.configure(|c| {
c.set_loopback(true);
c.set_silent(true);
c.set_bit_timing(0x00050000);
});
can1.modify_config()
.set_loopback(true)
.set_silent(true)
.set_bit_timing(0x00050000);
let mut can2 = Can::new(can2);
can2.configure(|c| {
c.set_loopback(true);
c.set_silent(true);
c.set_bit_timing(0x00050000);
});
can2.modify_config()
.set_loopback(true)
.set_silent(true)
.set_bit_timing(0x00050000);

Self { can1, can2 }
}
Expand All @@ -34,21 +32,21 @@ impl State {
///
/// This is useful for testing recovery when the mailboxes are full.
fn go_slow(&mut self) {
self.can1.configure(|c| {
c.set_loopback(true);
c.set_silent(true);
c.set_bit_timing(0x007f_03ff);
});
self.can1
.modify_config()
.set_loopback(true)
.set_silent(true)
.set_bit_timing(0x007f_03ff);
nb::block!(self.can1.enable()).unwrap();
}

/// Configures the default (fast) speed.
fn go_fast(&mut self) {
self.can1.configure(|c| {
c.set_loopback(true);
c.set_silent(true);
c.set_bit_timing(0x00050000);
});
self.can1
.modify_config()
.set_loopback(true)
.set_silent(true)
.set_bit_timing(0x00050000);
nb::block!(self.can1.enable()).unwrap();
}
}
Expand Down Expand Up @@ -384,26 +382,32 @@ mod tests {
/// Requires that both are hooked up to the same CAN bus.
#[test]
fn ext_roundtrip(state: &mut State) {
state.can1.configure(|c| {
c.set_loopback(false);
c.set_silent(false);
c.set_bit_timing(0x00050000);
});
state.can2.configure(|c| {
c.set_loopback(false);
c.set_silent(false);
c.set_bit_timing(0x00050000);
});

let mut filt1 = state.can1.modify_filters();
filt1.set_split(1);
filt1.clear();
filt1.enable_bank(0, Mask32::accept_all());

let mut filt2 = filt1.slave_filters();
filt2.clear();
filt2.enable_bank(1, Mask32::accept_all());
drop(filt1);
state
.can1
.modify_config()
.set_loopback(false)
.set_silent(false)
.set_bit_timing(0x00050000);
state
.can2
.modify_config()
.set_loopback(false)
.set_silent(false)
.set_bit_timing(0x00050000);

state
.can1
.modify_filters()
.set_split(1)
.clear()
.enable_bank(0, Mask32::accept_all());

state
.can1
.modify_filters()
.slave_filters()
.clear()
.enable_bank(1, Mask32::accept_all());

block!(state.can1.enable()).unwrap();
block!(state.can2.enable()).unwrap();
Expand Down

0 comments on commit d2bb8dd

Please sign in to comment.