Skip to content

Commit e56a1d0

Browse files
authored
Merge pull request #4095 from G33KatWork/stm32_eth_v1_mii
Implement MII for STM32 V1 ethernet peripheral
2 parents 05c6634 + d9f708c commit e56a1d0

File tree

1 file changed

+116
-15
lines changed
  • embassy-stm32/src/eth/v1

1 file changed

+116
-15
lines changed

embassy-stm32/src/eth/v1/mod.rs

Lines changed: 116 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,18 @@ pub struct Ethernet<'d, T: Instance, P: Phy> {
5151
pub(crate) tx: TDesRing<'d>,
5252
pub(crate) rx: RDesRing<'d>,
5353

54-
pins: [Peri<'d, AnyPin>; 9],
54+
pins: Pins<'d>,
5555
pub(crate) phy: P,
5656
pub(crate) station_management: EthernetStationManagement<T>,
5757
pub(crate) mac_addr: [u8; 6],
5858
}
5959

60+
/// Pins of ethernet driver.
61+
enum Pins<'d> {
62+
Rmii([Peri<'d, AnyPin>; 9]),
63+
Mii([Peri<'d, AnyPin>; 14]),
64+
}
65+
6066
#[cfg(eth_v1a)]
6167
macro_rules! config_in_pins {
6268
($($pin:ident),*) => {
@@ -96,7 +102,7 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> {
96102
pub fn new<const TX: usize, const RX: usize>(
97103
queue: &'d mut PacketQueue<TX, RX>,
98104
peri: Peri<'d, T>,
99-
_irq: impl interrupt::typelevel::Binding<interrupt::typelevel::ETH, InterruptHandler> + 'd,
105+
irq: impl interrupt::typelevel::Binding<interrupt::typelevel::ETH, InterruptHandler> + 'd,
100106
ref_clk: Peri<'d, impl RefClkPin<T>>,
101107
mdio: Peri<'d, impl MDIOPin<T>>,
102108
mdc: Peri<'d, impl MDCPin<T>>,
@@ -146,6 +152,29 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> {
146152
#[cfg(any(eth_v1b, eth_v1c))]
147153
config_pins!(ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en);
148154

155+
let pins = Pins::Rmii([
156+
ref_clk.into(),
157+
mdio.into(),
158+
mdc.into(),
159+
crs.into(),
160+
rx_d0.into(),
161+
rx_d1.into(),
162+
tx_d0.into(),
163+
tx_d1.into(),
164+
tx_en.into(),
165+
]);
166+
167+
Self::new_inner(queue, peri, irq, pins, phy, mac_addr)
168+
}
169+
170+
fn new_inner<const TX: usize, const RX: usize>(
171+
queue: &'d mut PacketQueue<TX, RX>,
172+
peri: Peri<'d, T>,
173+
_irq: impl interrupt::typelevel::Binding<interrupt::typelevel::ETH, InterruptHandler> + 'd,
174+
pins: Pins<'d>,
175+
phy: P,
176+
mac_addr: [u8; 6],
177+
) -> Self {
149178
let dma = T::regs().ethernet_dma();
150179
let mac = T::regs().ethernet_mac();
151180

@@ -210,18 +239,6 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> {
210239
}
211240
};
212241

213-
let pins = [
214-
ref_clk.into(),
215-
mdio.into(),
216-
mdc.into(),
217-
crs.into(),
218-
rx_d0.into(),
219-
rx_d1.into(),
220-
tx_d0.into(),
221-
tx_d1.into(),
222-
tx_en.into(),
223-
];
224-
225242
let mut this = Self {
226243
_peri: peri,
227244
pins,
@@ -267,6 +284,87 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> {
267284

268285
this
269286
}
287+
288+
/// Create a new MII ethernet driver using 14 pins.
289+
pub fn new_mii<const TX: usize, const RX: usize>(
290+
queue: &'d mut PacketQueue<TX, RX>,
291+
peri: Peri<'d, T>,
292+
irq: impl interrupt::typelevel::Binding<interrupt::typelevel::ETH, InterruptHandler> + 'd,
293+
rx_clk: Peri<'d, impl RXClkPin<T>>,
294+
tx_clk: Peri<'d, impl TXClkPin<T>>,
295+
mdio: Peri<'d, impl MDIOPin<T>>,
296+
mdc: Peri<'d, impl MDCPin<T>>,
297+
rxdv: Peri<'d, impl RXDVPin<T>>,
298+
rx_d0: Peri<'d, impl RXD0Pin<T>>,
299+
rx_d1: Peri<'d, impl RXD1Pin<T>>,
300+
rx_d2: Peri<'d, impl RXD2Pin<T>>,
301+
rx_d3: Peri<'d, impl RXD3Pin<T>>,
302+
tx_d0: Peri<'d, impl TXD0Pin<T>>,
303+
tx_d1: Peri<'d, impl TXD1Pin<T>>,
304+
tx_d2: Peri<'d, impl TXD2Pin<T>>,
305+
tx_d3: Peri<'d, impl TXD3Pin<T>>,
306+
tx_en: Peri<'d, impl TXEnPin<T>>,
307+
phy: P,
308+
mac_addr: [u8; 6],
309+
) -> Self {
310+
// TODO: Handle optional signals like CRS, MII_COL, RX_ER?
311+
312+
// Enable the necessary Clocks
313+
#[cfg(eth_v1a)]
314+
critical_section::with(|_| {
315+
RCC.apb2enr().modify(|w| w.set_afioen(true));
316+
317+
// Select MII (Media Independent Interface)
318+
// Must be done prior to enabling peripheral clock
319+
AFIO.mapr().modify(|w| w.set_mii_rmii_sel(false));
320+
321+
RCC.ahbenr().modify(|w| {
322+
w.set_ethen(true);
323+
w.set_ethtxen(true);
324+
w.set_ethrxen(true);
325+
});
326+
});
327+
328+
#[cfg(any(eth_v1b, eth_v1c))]
329+
critical_section::with(|_| {
330+
RCC.ahb1enr().modify(|w| {
331+
w.set_ethen(true);
332+
w.set_ethtxen(true);
333+
w.set_ethrxen(true);
334+
});
335+
336+
// MII (Media Independent Interface)
337+
SYSCFG.pmc().modify(|w| w.set_mii_rmii_sel(false));
338+
});
339+
340+
#[cfg(eth_v1a)]
341+
{
342+
config_in_pins!(rx_clk, tx_clk, rx_d0, rx_d1, rx_d2, rx_d3, rxdv);
343+
config_af_pins!(mdio, mdc, tx_d0, tx_d1, tx_d2, tx_d3, tx_en);
344+
}
345+
346+
#[cfg(any(eth_v1b, eth_v1c))]
347+
config_pins!(rx_clk, tx_clk, mdio, mdc, rxdv, rx_d0, rx_d1, rx_d2, rx_d3, tx_d0, tx_d1, tx_d2, tx_d3, tx_en);
348+
349+
let pins = Pins::Mii([
350+
rx_clk.into(),
351+
tx_clk.into(),
352+
mdio.into(),
353+
mdc.into(),
354+
rxdv.into(),
355+
rx_d0.into(),
356+
rx_d1.into(),
357+
rx_d2.into(),
358+
rx_d3.into(),
359+
tx_d0.into(),
360+
tx_d1.into(),
361+
tx_d2.into(),
362+
tx_d3.into(),
363+
tx_en.into(),
364+
]);
365+
366+
Self::new_inner(queue, peri, irq, pins, phy, mac_addr)
367+
}
270368
}
271369

272370
/// Ethernet station management interface.
@@ -322,7 +420,10 @@ impl<'d, T: Instance, P: Phy> Drop for Ethernet<'d, T, P> {
322420
dma.dmaomr().modify(|w| w.set_sr(DmaomrSr::STOPPED));
323421

324422
critical_section::with(|_| {
325-
for pin in self.pins.iter_mut() {
423+
for pin in match self.pins {
424+
Pins::Rmii(ref mut pins) => pins.iter_mut(),
425+
Pins::Mii(ref mut pins) => pins.iter_mut(),
426+
} {
326427
pin.set_as_disconnected();
327428
}
328429
})

0 commit comments

Comments
 (0)