Skip to content

Commit 3cc823c

Browse files
committed
Sacrifice some usability for a lot of space savings
1 parent 6b39f9c commit 3cc823c

File tree

6 files changed

+124
-82
lines changed

6 files changed

+124
-82
lines changed

Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ cortex-m = "0.7"
2929
log = { version = "0.4", optional = true }
3030
defmt = { version = "0.3", optional = true }
3131
bitflags = "1.3.2"
32-
heapless = "0.7.16"
3332

3433
[dependencies.smoltcp]
3534
version = "0.8"

examples/arp.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,11 @@ use cortex_m_rt::{entry, exception};
1616

1717
use cortex_m::interrupt::Mutex;
1818
use stm32_eth::{
19-
mac::{phy::BarePhy, Phy},
19+
mac::{
20+
frame_filtering::{FrameFiltering, FrameFilteringMode, Mac},
21+
phy::BarePhy,
22+
Phy,
23+
},
2024
stm32::{interrupt, CorePeripherals, Peripherals, SYST},
2125
};
2226

@@ -57,6 +61,15 @@ fn main() -> ! {
5761
.unwrap();
5862
eth_dma.enable_interrupt();
5963

64+
let some_mac = if eth_dma.tx_is_running() { 1 } else { 0 };
65+
66+
let frame_filtering = FrameFiltering::filter_destinations(
67+
Mac::new([some_mac, some_mac, some_mac, some_mac, some_mac, some_mac]),
68+
&[],
69+
);
70+
71+
eth_mac.configure_filtering(&FrameFilteringMode::Filter(frame_filtering));
72+
6073
let mut last_link_up = false;
6174

6275
let mut bare_phy = BarePhy::new(eth_mac.with_mii(mdio, mdc), PHY_ADDR, Default::default());
@@ -111,6 +124,15 @@ fn main() -> ! {
111124
}
112125
Err(TxError::WouldBlock) => defmt::info!("ARP failed"),
113126
}
127+
128+
// while let Ok(message) = eth_dma.recv_next() {
129+
// let mut chunks = message.chunks(6);
130+
131+
// let dst_mac = Mac::try_from(chunks.next().unwrap()).ok().unwrap();
132+
// let src_mac = Mac::try_from(chunks.next().unwrap()).ok().unwrap();
133+
134+
// defmt::warn!("DA: {}, SA: {}", dst_mac, src_mac);
135+
// }
114136
} else {
115137
defmt::info!("Down");
116138
}

src/mac/frame_filtering/destination.rs

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
1-
use heapless::Vec;
2-
3-
use super::MacAddressFilter;
4-
51
/// The type of filtering that the MAC should apply to
62
/// frames that are to be transmitted.
73
#[derive(Debug, Clone)]
84
pub struct DestinationAddressFiltering {
95
/// Filtering to be performed based on perfect address matches.
10-
pub perfect_filtering: PerfectDestinationAddressFiltering,
6+
pub perfect_filtering: PerfectDestinationAddressFilteringMode,
117
/// Enable or disable hash table filtering for destination
128
/// addresses.
139
pub hash_table_filtering: bool,
@@ -18,7 +14,7 @@ impl DestinationAddressFiltering {
1814
/// not filter any frames.
1915
pub const fn new() -> Self {
2016
Self {
21-
perfect_filtering: PerfectDestinationAddressFiltering::new(),
17+
perfect_filtering: PerfectDestinationAddressFilteringMode::new(),
2218
hash_table_filtering: false,
2319
}
2420
}
@@ -34,24 +30,29 @@ impl Default for DestinationAddressFiltering {
3430
/// the MAC should apply to frames.
3531
#[derive(Debug, Clone)]
3632

37-
pub enum PerfectDestinationAddressFiltering {
33+
pub enum PerfectDestinationAddressFilteringMode {
3834
/// Filter frames by their Destination Address, based on
39-
/// the provided addresses.
40-
Normal(Vec<MacAddressFilter, 3>),
35+
/// the addresses configured with [`AddressFilterType::Destination`].
36+
///
37+
/// [`AddressFilterType::Destination`]: `super::AddressFilterType::Destination`
38+
Normal,
4139
/// Filter frames by their Destination Address, based on
42-
/// the inverse of the provided addresses.
43-
Inverse(Vec<MacAddressFilter, 3>),
40+
/// the inverse of the addresses configured with
41+
/// [`AddressFilterType::Destination`].
42+
///
43+
/// [`AddressFilterType::Destination`]: `super::AddressFilterType::Destination`
44+
Inverse,
4445
}
4546

46-
impl PerfectDestinationAddressFiltering {
47-
/// Create a new [`PerfectDestinationAddressFiltering`] that filters
47+
impl PerfectDestinationAddressFilteringMode {
48+
/// Create a new [`PerfectDestinationAddressFilteringMode`] that filters
4849
/// out all frames.
4950
pub const fn new() -> Self {
50-
Self::Normal(Vec::new())
51+
Self::Normal
5152
}
5253
}
5354

54-
impl Default for PerfectDestinationAddressFiltering {
55+
impl Default for PerfectDestinationAddressFilteringMode {
5556
fn default() -> Self {
5657
Self::new()
5758
}

src/mac/frame_filtering/mod.rs

Lines changed: 75 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
//! Hardware filtering of Ethernet frames
22
33
use crate::hal::pac::ETHERNET_MAC;
4-
use heapless::Vec;
54

65
mod destination;
76
pub use destination::*;
@@ -53,7 +52,10 @@ impl FrameFilteringMode {
5352
pub struct FrameFiltering {
5453
/// The MAC address of this station. This address is always
5554
/// used for Destination Address filtering.
56-
pub address: Mac,
55+
pub base_address: Mac,
56+
57+
/// Extra address filters to be used.
58+
pub address_filters: [Option<MacAddressFilter>; 3],
5759

5860
/// Frame filtering applied to frames based on
5961
/// their destination address.
@@ -94,16 +96,30 @@ impl FrameFiltering {
9496
/// * Does not filter out multicast frames.
9597
/// * Does not filter out broadcast frames.
9698
/// * Filters out all control frames.
97-
pub fn filter_destinations(station_addr: Mac, extra_addresses: Vec<Mac, 3>) -> Self {
98-
let extra_addrs = extra_addresses
99-
.into_iter()
100-
.map(|a| MacAddressFilter::new(a, MacAddressFilterMask::empty()))
101-
.collect();
99+
pub const fn filter_destinations(station_addr: Mac, extra_addresses: &[Mac]) -> Self {
100+
assert!(extra_addresses.len() <= 3);
101+
102+
let mut address_filters = [None, None, None];
103+
104+
let mut i = 0;
105+
loop {
106+
address_filters[i] = Some(MacAddressFilter::new(
107+
AddressFilterType::Destination,
108+
extra_addresses[i],
109+
MacAddressFilterMask::empty(),
110+
));
111+
112+
i += 1;
113+
if i == 3 || i == extra_addresses.len() {
114+
break;
115+
}
116+
}
102117

103118
FrameFiltering {
104-
address: station_addr,
119+
base_address: station_addr,
120+
address_filters,
105121
destination_address_filter: DestinationAddressFiltering {
106-
perfect_filtering: PerfectDestinationAddressFiltering::Normal(extra_addrs),
122+
perfect_filtering: PerfectDestinationAddressFilteringMode::Normal,
107123
hash_table_filtering: false,
108124
},
109125
source_address_filter: SourceAddressFiltering::Ignore,
@@ -117,7 +133,8 @@ impl FrameFiltering {
117133

118134
fn configure(&self, eth_mac: &ETHERNET_MAC) {
119135
let FrameFiltering {
120-
address,
136+
base_address,
137+
address_filters,
121138
destination_address_filter,
122139
source_address_filter,
123140
multicast_address_filter,
@@ -127,27 +144,29 @@ impl FrameFiltering {
127144
receive_all,
128145
} = self;
129146

130-
eth_mac.maca0hr.write(|w| w.maca0h().bits(address.high()));
131-
eth_mac.maca0lr.write(|w| w.maca0l().bits(address.low()));
147+
eth_mac
148+
.maca0hr
149+
.write(|w| w.maca0h().bits(base_address.high()));
150+
eth_mac
151+
.maca0lr
152+
.write(|w| w.maca0l().bits(base_address.low()));
132153

133-
let (daif, dest_addrs) = match &destination_address_filter.perfect_filtering {
134-
PerfectDestinationAddressFiltering::Normal(addrs) => (false, addrs),
135-
PerfectDestinationAddressFiltering::Inverse(addrs) => (true, addrs),
154+
let daif = match &destination_address_filter.perfect_filtering {
155+
PerfectDestinationAddressFilteringMode::Normal => false,
156+
PerfectDestinationAddressFilteringMode::Inverse => true,
136157
};
137158
let hu = destination_address_filter.hash_table_filtering;
138159

139-
let empty_vec = Vec::new();
140-
141-
let (saf, saif, source_addrs) = match &source_address_filter {
142-
SourceAddressFiltering::Ignore => (false, false, &empty_vec),
143-
SourceAddressFiltering::Normal(addrs) => (true, false, addrs),
144-
SourceAddressFiltering::Inverse(addrs) => (true, true, addrs),
160+
let (saf, saif) = match &source_address_filter {
161+
SourceAddressFiltering::Ignore => (false, false),
162+
SourceAddressFiltering::Normal => (true, false),
163+
SourceAddressFiltering::Inverse => (true, true),
145164
};
146165

147-
let (pam, hm, multicast_addrs) = match &multicast_address_filter {
148-
MulticastAddressFiltering::PassAll => (true, false, &empty_vec),
149-
MulticastAddressFiltering::DestinationAddressHash => (false, true, &empty_vec),
150-
MulticastAddressFiltering::DestinationAddress(addrs) => (false, false, addrs),
166+
let (pam, hm) = match &multicast_address_filter {
167+
MulticastAddressFiltering::PassAll => (true, false),
168+
MulticastAddressFiltering::DestinationAddressHash => (false, true),
169+
MulticastAddressFiltering::DestinationAddress => (false, false),
151170
};
152171

153172
let pcf = match &control_filter {
@@ -157,32 +176,23 @@ impl FrameFiltering {
157176
ControlFrameFiltering::AddressFilter => 0b11,
158177
};
159178

160-
assert!(
161-
source_addrs.len() + dest_addrs.len() + multicast_addrs.len() <= 3,
162-
"A maximum of 3 combined source, destination, and multicast address filters may be configured at any time."
163-
);
164-
165-
let mut dest_addrs = dest_addrs.iter();
166-
let mut source_addrs = source_addrs.iter();
167-
let mut multicast_addrs = multicast_addrs.iter();
168-
169179
macro_rules! next_addr_reg {
170-
($regh:ident, $regl:ident, $ah:ident, $al:ident) => {
171-
if let Some((addr, sa)) = dest_addrs
172-
.next()
173-
.map(|v| (v, false))
174-
.or(source_addrs.next().map(|v| (v, true)))
175-
.or(multicast_addrs.next().map(|v| (v, false)))
176-
{
180+
($idx:literal, $regh:ident, $regl:ident, $ah:ident, $al:ident) => {
181+
if let Some(filter) = &address_filters[$idx] {
182+
let sa = match filter.ty {
183+
AddressFilterType::Destination => false,
184+
AddressFilterType::Source => true,
185+
};
186+
177187
eth_mac.$regh.write(|w| {
178188
w.ae()
179189
.set_bit()
180190
.sa()
181191
.bit(sa)
182192
.mbc()
183-
.bits(addr.mask.bits())
193+
.bits(filter.mask.bits())
184194
.$ah()
185-
.bits(addr.address.high())
195+
.bits(filter.address.high())
186196
});
187197

188198
// This operation is only unsafe for register maca2lr STM32F107
@@ -192,14 +202,16 @@ impl FrameFiltering {
192202
#[allow(unused_unsafe)]
193203
eth_mac
194204
.$regl
195-
.write(|w| unsafe { w.$al().bits(addr.address.low()) });
205+
.write(|w| unsafe { w.$al().bits(filter.address.low()) });
206+
} else {
207+
eth_mac.$regh.write(|w| w.ae().clear_bit());
196208
}
197209
};
198210
}
199211

200-
next_addr_reg!(maca1hr, maca1lr, maca1h, maca1l);
201-
next_addr_reg!(maca2hr, maca2lr, maca2h, maca2l);
202-
next_addr_reg!(maca3hr, maca3lr, maca3h, maca3l);
212+
next_addr_reg!(0, maca1hr, maca1lr, maca1h, maca1l);
213+
next_addr_reg!(1, maca2hr, maca2lr, maca2h, maca2l);
214+
next_addr_reg!(2, maca3hr, maca3lr, maca3h, maca3l);
203215

204216
eth_mac.macffr.write(|w| {
205217
w.hpf()
@@ -237,7 +249,7 @@ impl FrameFiltering {
237249
}
238250

239251
/// A big-endian MAC address.
240-
#[derive(Debug, Clone)]
252+
#[derive(Debug, Clone, Copy)]
241253
pub struct Mac([u8; 6]);
242254

243255
impl Mac {
@@ -303,10 +315,22 @@ impl defmt::Format for Mac {
303315
}
304316
}
305317

318+
#[derive(Debug, Clone, Copy)]
319+
/// The type of an address filter.
320+
pub enum AddressFilterType {
321+
/// Filter based on Source Address.
322+
Source,
323+
/// Filter based on Destination address.
324+
Destination,
325+
}
326+
306327
/// A MAC address filter
307-
#[derive(Debug, Clone)]
328+
#[derive(Debug, Clone, Copy)]
308329

309330
pub struct MacAddressFilter {
331+
/// The address on which this filter
332+
/// should operate.
333+
pub ty: AddressFilterType,
310334
/// The address that this filter should use.
311335
pub address: Mac,
312336
/// The byte mask that should be used to mask
@@ -317,8 +341,8 @@ pub struct MacAddressFilter {
317341

318342
impl MacAddressFilter {
319343
/// Create a new MAC address filter.
320-
pub fn new(address: Mac, mask: MacAddressFilterMask) -> Self {
321-
Self { address, mask }
344+
pub const fn new(ty: AddressFilterType, address: Mac, mask: MacAddressFilterMask) -> Self {
345+
Self { ty, address, mask }
322346
}
323347
}
324348

src/mac/frame_filtering/multicast.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
use heapless::Vec;
2-
3-
use super::MacAddressFilter;
4-
51
/// Multicast address filtering
62
#[derive(Debug, Clone)]
73
pub enum MulticastAddressFiltering {
@@ -15,7 +11,7 @@ pub enum MulticastAddressFiltering {
1511
/// Only multicast frames whose destination address
1612
/// is equal to one of the provided destination addresses
1713
/// are passed to the application.
18-
DestinationAddress(Vec<MacAddressFilter, 3>),
14+
DestinationAddress,
1915
}
2016

2117
impl MulticastAddressFiltering {

src/mac/frame_filtering/source.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
use heapless::Vec;
2-
3-
use super::MacAddressFilter;
4-
51
/// The type of frame filtering that the MAC should perform
62
/// on received frames.
73
#[derive(Debug, Clone)]
@@ -10,18 +6,22 @@ pub enum SourceAddressFiltering {
106
/// Source address filtering never fails.
117
Ignore,
128
/// Filter frames by their Source Address, based on
13-
/// the provided addresses.
14-
Normal(Vec<MacAddressFilter, 3>),
9+
/// the addresses configured with [`AddressFilterType::Source`].
10+
///
11+
/// [`AddressFilterType::Source`]: `super::AddressFilterType::Destination`
12+
Normal,
1513
/// Filter frames by their Source Address, based on
16-
/// the inverse of the provided addresses.
17-
Inverse(Vec<MacAddressFilter, 3>),
14+
/// the addresses configured with [`AddressFilterType::Source`].
15+
///
16+
/// [`AddressFilterType::Source`]: `super::AddressFilterType::Destination`
17+
Inverse,
1818
}
1919

2020
impl SourceAddressFiltering {
2121
/// Create a new [`SourceAddressFiltering`] that
2222
/// does not filter any frames.
2323
pub const fn new() -> Self {
24-
Self::Inverse(Vec::new())
24+
Self::Inverse
2525
}
2626
}
2727

0 commit comments

Comments
 (0)