aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2025-04-15 10:34:27 +0000
committerGitHub <[email protected]>2025-04-15 10:34:27 +0000
commite56a1d0e457bee087a4094206b277fbf595a8f17 (patch)
treecef468c1a38079030de53be24fa3021f8c3418d8
parent05c663490422f0aaaf539de2ef570267582ca1c2 (diff)
parentd9f708ca6dff653ca7ab6c24b5e9e437ea922ce4 (diff)
Merge pull request #4095 from G33KatWork/stm32_eth_v1_mii
Implement MII for STM32 V1 ethernet peripheral
-rw-r--r--embassy-stm32/src/eth/v1/mod.rs131
1 files changed, 116 insertions, 15 deletions
diff --git a/embassy-stm32/src/eth/v1/mod.rs b/embassy-stm32/src/eth/v1/mod.rs
index 640191d69..01e321bce 100644
--- a/embassy-stm32/src/eth/v1/mod.rs
+++ b/embassy-stm32/src/eth/v1/mod.rs
@@ -51,12 +51,18 @@ pub struct Ethernet<'d, T: Instance, P: Phy> {
51 pub(crate) tx: TDesRing<'d>, 51 pub(crate) tx: TDesRing<'d>,
52 pub(crate) rx: RDesRing<'d>, 52 pub(crate) rx: RDesRing<'d>,
53 53
54 pins: [Peri<'d, AnyPin>; 9], 54 pins: Pins<'d>,
55 pub(crate) phy: P, 55 pub(crate) phy: P,
56 pub(crate) station_management: EthernetStationManagement<T>, 56 pub(crate) station_management: EthernetStationManagement<T>,
57 pub(crate) mac_addr: [u8; 6], 57 pub(crate) mac_addr: [u8; 6],
58} 58}
59 59
60/// Pins of ethernet driver.
61enum Pins<'d> {
62 Rmii([Peri<'d, AnyPin>; 9]),
63 Mii([Peri<'d, AnyPin>; 14]),
64}
65
60#[cfg(eth_v1a)] 66#[cfg(eth_v1a)]
61macro_rules! config_in_pins { 67macro_rules! config_in_pins {
62 ($($pin:ident),*) => { 68 ($($pin:ident),*) => {
@@ -96,7 +102,7 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> {
96 pub fn new<const TX: usize, const RX: usize>( 102 pub fn new<const TX: usize, const RX: usize>(
97 queue: &'d mut PacketQueue<TX, RX>, 103 queue: &'d mut PacketQueue<TX, RX>,
98 peri: Peri<'d, T>, 104 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,
100 ref_clk: Peri<'d, impl RefClkPin<T>>, 106 ref_clk: Peri<'d, impl RefClkPin<T>>,
101 mdio: Peri<'d, impl MDIOPin<T>>, 107 mdio: Peri<'d, impl MDIOPin<T>>,
102 mdc: Peri<'d, impl MDCPin<T>>, 108 mdc: Peri<'d, impl MDCPin<T>>,
@@ -146,6 +152,29 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> {
146 #[cfg(any(eth_v1b, eth_v1c))] 152 #[cfg(any(eth_v1b, eth_v1c))]
147 config_pins!(ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en); 153 config_pins!(ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en);
148 154
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 {
149 let dma = T::regs().ethernet_dma(); 178 let dma = T::regs().ethernet_dma();
150 let mac = T::regs().ethernet_mac(); 179 let mac = T::regs().ethernet_mac();
151 180
@@ -210,18 +239,6 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> {
210 } 239 }
211 }; 240 };
212 241
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
225 let mut this = Self { 242 let mut this = Self {
226 _peri: peri, 243 _peri: peri,
227 pins, 244 pins,
@@ -267,6 +284,87 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> {
267 284
268 this 285 this
269 } 286 }
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 }
270} 368}
271 369
272/// Ethernet station management interface. 370/// Ethernet station management interface.
@@ -322,7 +420,10 @@ impl<'d, T: Instance, P: Phy> Drop for Ethernet<'d, T, P> {
322 dma.dmaomr().modify(|w| w.set_sr(DmaomrSr::STOPPED)); 420 dma.dmaomr().modify(|w| w.set_sr(DmaomrSr::STOPPED));
323 421
324 critical_section::with(|_| { 422 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 } {
326 pin.set_as_disconnected(); 427 pin.set_as_disconnected();
327 } 428 }
328 }) 429 })