Skip to content

Commit 4037f42

Browse files
committed
can: Improve advanced filter configuration
1 parent 38c3b26 commit 4037f42

File tree

2 files changed

+70
-94
lines changed

2 files changed

+70
-94
lines changed

examples/can-loopback.rs

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -57,28 +57,23 @@ fn main() -> ! {
5757
// The order of the added filters is important: it must match configuration
5858
// of the `split_filters_advanced()` method.
5959

60-
// Matches 0, 1, 2
60+
// 2x 11bit id + mask filter bank: Matches 0, 1, 2
6161
filters
62-
.add_standard([
63-
&Filter::new_standard(0).with_mask(!0b1),
64-
&Filter::new_standard(0).with_mask(!0b10),
65-
])
62+
.add(&Filter::new_standard(0).with_mask(!0b1))
6663
.unwrap();
67-
68-
// Matches 4, 5
6964
filters
70-
.add_list([&Filter::new_standard(4), &Filter::new_standard(5)])
65+
.add(&Filter::new_standard(0).with_mask(!0b10))
7166
.unwrap();
7267

73-
// Matches 8, 9, 10, 11
74-
filters
75-
.add_standard_list([
76-
&Filter::new_standard(8),
77-
&Filter::new_standard(9),
78-
&Filter::new_standard(10),
79-
&Filter::new_standard(11),
80-
])
81-
.unwrap();
68+
// 2x 29bit id filter bank: Matches 4, 5
69+
filters.add(&Filter::new_standard(4)).unwrap();
70+
filters.add(&Filter::new_standard(5)).unwrap();
71+
72+
// 4x 11bit id filter bank: Matches 8, 9, 10, 11
73+
filters.add(&Filter::new_standard(8)).unwrap();
74+
filters.add(&Filter::new_standard(9)).unwrap();
75+
filters.add(&Filter::new_standard(10)).unwrap();
76+
filters.add(&Filter::new_standard(11)).unwrap();
8277

8378
// Split the peripheral into transmitter and receiver parts.
8479
let mut rx = can.take_rx(filters).unwrap();

src/can.rs

Lines changed: 58 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -705,96 +705,77 @@ where
705705

706706
/// Adds a filter. Returns `Err` if the maximum number of filters was reached.
707707
pub fn add(&mut self, filter: &Filter) -> Result<(), ()> {
708-
let idx = self.next_idx()?;
709-
self.check_config(idx, false, true)?;
710-
self.write_filter_bank(idx, filter.id, filter.mask);
711-
Ok(())
712-
}
708+
let can = unsafe { &*CAN1::ptr() };
713709

714-
/// Adds two filters, each filtering for a single ID.
715-
///
716-
/// The filter bank must to be configured to `fm1r.fbm = 1` and `fs1r.fsc = 1` by
717-
/// `Can::split_filters_advanced()`.
718-
pub fn add_list(&mut self, filters: [&Filter; 2]) -> Result<(), ()> {
719-
if !filters[0].matches_single_id() || !filters[1].matches_single_id() {
710+
let idx = self.start_idx + self.count;
711+
if idx >= self.stop_idx {
720712
return Err(());
721713
}
722714

723-
let idx = self.next_idx()?;
724-
self.check_config(idx, true, true)?;
725-
self.write_filter_bank(idx, filters[0].id, filters[1].id);
726-
Ok(())
727-
}
715+
let mode_list = (can.fm1r.read().bits() & (1 << idx)) != 0;
716+
let scale_16bit = (can.fs1r.read().bits() & (1 << idx)) == 0;
717+
let bank_enabled = (can.fa1r.read().bits() & (1 << idx)) != 0;
728718

729-
/// Adds two standard ID filters with mask support.
730-
///
731-
/// The filter bank must to be configured to `fm1r.fbm = 0` and `fs1r.fsc = 0` by
732-
/// `Can::split_filters_advanced()`.
733-
pub fn add_standard(&mut self, filters: [&Filter; 2]) -> Result<(), ()> {
734-
if filters[0].is_extended() || filters[1].is_extended() {
719+
// Make sure the filter is supported by the filter bank configuration.
720+
if (mode_list && !filter.matches_single_id()) || (scale_16bit && filter.is_extended()) {
735721
return Err(());
736722
}
737723

738-
let idx = self.next_idx()?;
739-
self.check_config(idx, false, false)?;
740-
self.write_filter_bank(
741-
idx,
742-
filters[0].mask_to_16bit() << 16 | filters[0].id_to_16bit(),
743-
filters[1].mask_to_16bit() << 16 | filters[1].id_to_16bit(),
744-
);
745-
Ok(())
746-
}
724+
// Disable the filter bank so it can be modified.
725+
bb::clear(&can.fa1r, idx as u8);
747726

748-
/// Adds four filters, each filtering for a single standard ID.
749-
///
750-
/// The filter bank must to be configured to `fm1r.fbm = 1` and `fs1r.fsc = 0` by
751-
/// `Can::split_filters_advanced()`.
752-
pub fn add_standard_list(&mut self, filters: [&Filter; 4]) -> Result<(), ()> {
753-
for filter in &filters {
754-
if !filter.matches_single_id() {
755-
return Err(());
727+
let filter_bank = &can.fb[idx];
728+
let fr1 = filter_bank.fr1.read().bits();
729+
let fr2 = filter_bank.fr2.read().bits();
730+
let (fr1, fr2) = match (mode_list, scale_16bit, bank_enabled) {
731+
// 29bit id + mask
732+
(false, false, _) => {
733+
self.count += 1;
734+
(filter.id, filter.mask)
756735
}
757-
}
758-
759-
let idx = self.next_idx()?;
760-
self.check_config(idx, true, false)?;
761-
self.write_filter_bank(
762-
idx,
763-
filters[1].id_to_16bit() << 16 | filters[0].id_to_16bit(),
764-
filters[3].id_to_16bit() << 16 | filters[2].id_to_16bit(),
765-
);
766-
Ok(())
767-
}
768-
769-
fn next_idx(&self) -> Result<usize, ()> {
770-
let idx = self.start_idx + self.count;
771-
if idx < self.stop_idx {
772-
Ok(idx)
773-
} else {
774-
Err(())
775-
}
776-
}
777-
778-
fn check_config(&self, idx: usize, mode_list: bool, scale_32bit: bool) -> Result<(), ()> {
779-
let can = unsafe { &*CAN1::ptr() };
780-
781-
if mode_list == ((can.fm1r.read().bits() & (1 << idx)) != 0)
782-
&& scale_32bit == ((can.fs1r.read().bits() & (1 << idx)) != 0)
783-
{
784-
Ok(())
785-
} else {
786-
Err(())
787-
}
788-
}
789-
790-
fn write_filter_bank(&mut self, idx: usize, fr1: u32, fr2: u32) {
791-
let can = unsafe { &*CAN1::ptr() };
736+
// 2x 29bit id
737+
(true, false, false) => (filter.id, filter.id),
738+
(true, false, true) => {
739+
self.count += 1;
740+
(fr1, filter.id)
741+
}
742+
// 2x 11bit id + mask
743+
(false, true, false) => (
744+
filter.mask_to_16bit() << 16 | filter.id_to_16bit(),
745+
filter.mask_to_16bit() << 16 | filter.id_to_16bit(),
746+
),
747+
(false, true, true) => {
748+
self.count += 1;
749+
(fr1, filter.mask_to_16bit() << 16 | filter.id_to_16bit())
750+
}
751+
// 4x 11bit id
752+
(true, true, false) => (
753+
filter.id_to_16bit() << 16 | filter.id_to_16bit(),
754+
filter.id_to_16bit() << 16 | filter.id_to_16bit(),
755+
),
756+
(true, true, true) => {
757+
let f = [fr1 & 0xFFFF, fr1 >> 16, fr2 & 0xFFFF, fr2 >> 16];
758+
759+
if f[0] == f[1] {
760+
// One filter available, add the second.
761+
(filter.id_to_16bit() << 16 | f[0], fr2)
762+
} else if f[0] == f[2] {
763+
// Two filters available, add the third.
764+
(fr1, f[0] << 16 | filter.id_to_16bit())
765+
} else if f[0] == f[3] {
766+
// Three filters available, add the fourth.
767+
self.count += 1;
768+
(fr1, filter.id_to_16bit() << 16 | f[2])
769+
} else {
770+
unreachable!()
771+
}
772+
}
773+
};
792774

793-
let filter_bank = &can.fb[idx];
794775
filter_bank.fr1.write(|w| unsafe { w.bits(fr1) });
795776
filter_bank.fr2.write(|w| unsafe { w.bits(fr2) });
796-
bb::set(&can.fa1r, idx as u8); // Enable filter
797-
self.count += 1;
777+
bb::set(&can.fa1r, idx as u8); // Enable the filter bank
778+
Ok(())
798779
}
799780

800781
/// Disables all enabled filter banks.

0 commit comments

Comments
 (0)