aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordatdenkikniet <[email protected]>2025-11-12 21:39:40 +0100
committerdatdenkikniet <[email protected]>2025-11-13 23:08:33 +0100
commit3f9865f9d8e9be95cad25df3f535fbe01087ed83 (patch)
tree540381350cfbecbe1a42cd0085ade2aa3b98864a
parent578679771eafe93ccc0e8de8fc3f97a5b991b02c (diff)
Give EthernetManagement owernship of MDIO pins
-rw-r--r--embassy-stm32/src/eth/v1/mod.rs50
-rw-r--r--embassy-stm32/src/eth/v2/mod.rs50
2 files changed, 62 insertions, 38 deletions
diff --git a/embassy-stm32/src/eth/v1/mod.rs b/embassy-stm32/src/eth/v1/mod.rs
index a77eb8719..91daa9d0b 100644
--- a/embassy-stm32/src/eth/v1/mod.rs
+++ b/embassy-stm32/src/eth/v1/mod.rs
@@ -53,14 +53,14 @@ pub struct Ethernet<'d, T: Instance, P: Phy> {
53 53
54 pins: Pins<'d>, 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<'d, T>,
57 pub(crate) mac_addr: [u8; 6], 57 pub(crate) mac_addr: [u8; 6],
58} 58}
59 59
60/// Pins of ethernet driver. 60/// Pins of ethernet driver.
61enum Pins<'d> { 61enum Pins<'d> {
62 Rmii([Peri<'d, AnyPin>; 9]), 62 Rmii([Peri<'d, AnyPin>; 7]),
63 Mii([Peri<'d, AnyPin>; 14]), 63 Mii([Peri<'d, AnyPin>; 12]),
64} 64}
65 65
66#[cfg(eth_v1a)] 66#[cfg(eth_v1a)]
@@ -157,8 +157,6 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> {
157 157
158 let pins = Pins::Rmii([ 158 let pins = Pins::Rmii([
159 ref_clk.into(), 159 ref_clk.into(),
160 mdio.into(),
161 mdc.into(),
162 crs.into(), 160 crs.into(),
163 rx_d0.into(), 161 rx_d0.into(),
164 rx_d1.into(), 162 rx_d1.into(),
@@ -167,7 +165,7 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> {
167 tx_en.into(), 165 tx_en.into(),
168 ]); 166 ]);
169 167
170 Self::new_inner(queue, peri, irq, pins, phy, mac_addr) 168 Self::new_inner(queue, peri, irq, pins, mdio, mdc, phy, mac_addr)
171 } 169 }
172 170
173 fn new_inner<const TX: usize, const RX: usize>( 171 fn new_inner<const TX: usize, const RX: usize>(
@@ -175,6 +173,8 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> {
175 peri: Peri<'d, T>, 173 peri: Peri<'d, T>,
176 _irq: impl interrupt::typelevel::Binding<interrupt::typelevel::ETH, InterruptHandler> + 'd, 174 _irq: impl interrupt::typelevel::Binding<interrupt::typelevel::ETH, InterruptHandler> + 'd,
177 pins: Pins<'d>, 175 pins: Pins<'d>,
176 mdio: Peri<'d, if_afio!(impl MDIOPin<T, A>)>,
177 mdc: Peri<'d, if_afio!(impl MDCPin<T, A>)>,
178 phy: P, 178 phy: P,
179 mac_addr: [u8; 6], 179 mac_addr: [u8; 6],
180 ) -> Self { 180 ) -> Self {
@@ -249,6 +249,7 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> {
249 station_management: EthernetStationManagement { 249 station_management: EthernetStationManagement {
250 peri: PhantomData, 250 peri: PhantomData,
251 clock_range: clock_range, 251 clock_range: clock_range,
252 pins: [mdio.into(), mdc.into()],
252 }, 253 },
253 mac_addr, 254 mac_addr,
254 tx: TDesRing::new(&mut queue.tx_desc, &mut queue.tx_buf), 255 tx: TDesRing::new(&mut queue.tx_desc, &mut queue.tx_buf),
@@ -357,8 +358,6 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> {
357 let pins = Pins::Mii([ 358 let pins = Pins::Mii([
358 rx_clk.into(), 359 rx_clk.into(),
359 tx_clk.into(), 360 tx_clk.into(),
360 mdio.into(),
361 mdc.into(),
362 rxdv.into(), 361 rxdv.into(),
363 rx_d0.into(), 362 rx_d0.into(),
364 rx_d1.into(), 363 rx_d1.into(),
@@ -371,43 +370,50 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> {
371 tx_en.into(), 370 tx_en.into(),
372 ]); 371 ]);
373 372
374 Self::new_inner(queue, peri, irq, pins, phy, mac_addr) 373 Self::new_inner(queue, peri, irq, pins, mdio, mdc, phy, mac_addr)
375 } 374 }
376} 375}
377 376
378/// Ethernet station management interface. 377/// Ethernet station management interface.
379pub(crate) struct EthernetStationManagement<T: Instance> { 378pub(crate) struct EthernetStationManagement<'d, T: Instance> {
380 peri: PhantomData<T>, 379 peri: PhantomData<T>,
381 clock_range: Cr, 380 clock_range: Cr,
381 pins: [Peri<'d, AnyPin>; 2],
382} 382}
383 383
384impl<T: Instance> StationManagement for EthernetStationManagement<T> { 384impl<T: Instance> StationManagement for EthernetStationManagement<'_, T> {
385 fn smi_read(&mut self, phy_addr: u8, reg: u8) -> u16 { 385 fn smi_read(&mut self, phy_addr: u8, reg: u8) -> u16 {
386 let mac = T::regs().ethernet_mac(); 386 let (macmiiar, macmiidr) = {
387 let regs = T::regs().ethernet_mac();
388 (regs.macmiiar(), regs.macmiidr())
389 };
387 390
388 mac.macmiiar().modify(|w| { 391 macmiiar.modify(|w| {
389 w.set_pa(phy_addr); 392 w.set_pa(phy_addr);
390 w.set_mr(reg); 393 w.set_mr(reg);
391 w.set_mw(Mw::READ); // read operation 394 w.set_mw(Mw::READ); // read operation
392 w.set_cr(self.clock_range); 395 w.set_cr(self.clock_range);
393 w.set_mb(MbProgress::BUSY); // indicate that operation is in progress 396 w.set_mb(MbProgress::BUSY); // indicate that operation is in progress
394 }); 397 });
395 while mac.macmiiar().read().mb() == MbProgress::BUSY {} 398 while macmiiar.read().mb() == MbProgress::BUSY {}
396 mac.macmiidr().read().md() 399 macmiidr.read().md()
397 } 400 }
398 401
399 fn smi_write(&mut self, phy_addr: u8, reg: u8, val: u16) { 402 fn smi_write(&mut self, phy_addr: u8, reg: u8, val: u16) {
400 let mac = T::regs().ethernet_mac(); 403 let (macmiiar, macmiidr) = {
404 let regs = T::regs().ethernet_mac();
405 (regs.macmiiar(), regs.macmiidr())
406 };
401 407
402 mac.macmiidr().write(|w| w.set_md(val)); 408 macmiidr.write(|w| w.set_md(val));
403 mac.macmiiar().modify(|w| { 409 macmiiar.modify(|w| {
404 w.set_pa(phy_addr); 410 w.set_pa(phy_addr);
405 w.set_mr(reg); 411 w.set_mr(reg);
406 w.set_mw(Mw::WRITE); // write 412 w.set_mw(Mw::WRITE); // write
407 w.set_cr(self.clock_range); 413 w.set_cr(self.clock_range);
408 w.set_mb(MbProgress::BUSY); 414 w.set_mb(MbProgress::BUSY);
409 }); 415 });
410 while mac.macmiiar().read().mb() == MbProgress::BUSY {} 416 while macmiiar.read().mb() == MbProgress::BUSY {}
411 } 417 }
412} 418}
413 419
@@ -437,3 +443,9 @@ impl<'d, T: Instance, P: Phy> Drop for Ethernet<'d, T, P> {
437 }) 443 })
438 } 444 }
439} 445}
446
447impl<T: Instance> Drop for EthernetStationManagement<'_, T> {
448 fn drop(&mut self) {
449 self.pins.iter_mut().for_each(|p| p.set_as_disconnected());
450 }
451}
diff --git a/embassy-stm32/src/eth/v2/mod.rs b/embassy-stm32/src/eth/v2/mod.rs
index 39a6e8b0f..61dea6f3f 100644
--- a/embassy-stm32/src/eth/v2/mod.rs
+++ b/embassy-stm32/src/eth/v2/mod.rs
@@ -42,14 +42,14 @@ pub struct Ethernet<'d, T: Instance, P: Phy> {
42 pub(crate) rx: RDesRing<'d>, 42 pub(crate) rx: RDesRing<'d>,
43 pins: Pins<'d>, 43 pins: Pins<'d>,
44 pub(crate) phy: P, 44 pub(crate) phy: P,
45 pub(crate) station_management: EthernetStationManagement<T>, 45 pub(crate) station_management: EthernetStationManagement<'d, T>,
46 pub(crate) mac_addr: [u8; 6], 46 pub(crate) mac_addr: [u8; 6],
47} 47}
48 48
49/// Pins of ethernet driver. 49/// Pins of ethernet driver.
50enum Pins<'d> { 50enum Pins<'d> {
51 Rmii([Peri<'d, AnyPin>; 9]), 51 Rmii([Peri<'d, AnyPin>; 7]),
52 Mii([Peri<'d, AnyPin>; 14]), 52 Mii([Peri<'d, AnyPin>; 12]),
53} 53}
54 54
55macro_rules! config_pins { 55macro_rules! config_pins {
@@ -96,8 +96,6 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> {
96 96
97 let pins = Pins::Rmii([ 97 let pins = Pins::Rmii([
98 ref_clk.into(), 98 ref_clk.into(),
99 mdio.into(),
100 mdc.into(),
101 crs.into(), 99 crs.into(),
102 rx_d0.into(), 100 rx_d0.into(),
103 rx_d1.into(), 101 rx_d1.into(),
@@ -106,7 +104,7 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> {
106 tx_en.into(), 104 tx_en.into(),
107 ]); 105 ]);
108 106
109 Self::new_inner(queue, peri, irq, pins, phy, mac_addr) 107 Self::new_inner(queue, peri, irq, pins, mdio, mdc, phy, mac_addr)
110 } 108 }
111 109
112 /// Create a new MII ethernet driver using 14 pins. 110 /// Create a new MII ethernet driver using 14 pins.
@@ -151,8 +149,6 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> {
151 let pins = Pins::Mii([ 149 let pins = Pins::Mii([
152 rx_clk.into(), 150 rx_clk.into(),
153 tx_clk.into(), 151 tx_clk.into(),
154 mdio.into(),
155 mdc.into(),
156 rxdv.into(), 152 rxdv.into(),
157 rx_d0.into(), 153 rx_d0.into(),
158 rx_d1.into(), 154 rx_d1.into(),
@@ -165,7 +161,7 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> {
165 tx_en.into(), 161 tx_en.into(),
166 ]); 162 ]);
167 163
168 Self::new_inner(queue, peri, irq, pins, phy, mac_addr) 164 Self::new_inner(queue, peri, irq, pins, mdio, mdc, phy, mac_addr)
169 } 165 }
170 166
171 fn new_inner<const TX: usize, const RX: usize>( 167 fn new_inner<const TX: usize, const RX: usize>(
@@ -173,6 +169,8 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> {
173 peri: Peri<'d, T>, 169 peri: Peri<'d, T>,
174 _irq: impl interrupt::typelevel::Binding<interrupt::typelevel::ETH, InterruptHandler> + 'd, 170 _irq: impl interrupt::typelevel::Binding<interrupt::typelevel::ETH, InterruptHandler> + 'd,
175 pins: Pins<'d>, 171 pins: Pins<'d>,
172 mdio: Peri<'d, impl MDIOPin<T>>,
173 mdc: Peri<'d, impl MDCPin<T>>,
176 phy: P, 174 phy: P,
177 mac_addr: [u8; 6], 175 mac_addr: [u8; 6],
178 ) -> Self { 176 ) -> Self {
@@ -262,6 +260,7 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> {
262 station_management: EthernetStationManagement { 260 station_management: EthernetStationManagement {
263 peri: PhantomData, 261 peri: PhantomData,
264 clock_range: clock_range, 262 clock_range: clock_range,
263 pins: [mdio.into(), mdc.into()],
265 }, 264 },
266 mac_addr, 265 mac_addr,
267 }; 266 };
@@ -299,38 +298,45 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> {
299} 298}
300 299
301/// Ethernet SMI driver. 300/// Ethernet SMI driver.
302pub struct EthernetStationManagement<T: Instance> { 301pub struct EthernetStationManagement<'d, T: Instance> {
303 peri: PhantomData<T>, 302 peri: PhantomData<T>,
304 clock_range: u8, 303 clock_range: u8,
304 pins: [Peri<'d, AnyPin>; 2],
305} 305}
306 306
307impl<T: Instance> StationManagement for EthernetStationManagement<T> { 307impl<T: Instance> StationManagement for EthernetStationManagement<'_, T> {
308 fn smi_read(&mut self, phy_addr: u8, reg: u8) -> u16 { 308 fn smi_read(&mut self, phy_addr: u8, reg: u8) -> u16 {
309 let mac = T::regs().ethernet_mac(); 309 let (macmdioar, macmdiodr) = {
310 let regs = T::regs().ethernet_mac();
311 (regs.macmdioar(), regs.macmdiodr())
312 };
310 313
311 mac.macmdioar().modify(|w| { 314 macmdioar.modify(|w| {
312 w.set_pa(phy_addr); 315 w.set_pa(phy_addr);
313 w.set_rda(reg); 316 w.set_rda(reg);
314 w.set_goc(0b11); // read 317 w.set_goc(0b11); // read
315 w.set_cr(self.clock_range); 318 w.set_cr(self.clock_range);
316 w.set_mb(true); 319 w.set_mb(true);
317 }); 320 });
318 while mac.macmdioar().read().mb() {} 321 while macmdioar.read().mb() {}
319 mac.macmdiodr().read().md() 322 macmdiodr.read().md()
320 } 323 }
321 324
322 fn smi_write(&mut self, phy_addr: u8, reg: u8, val: u16) { 325 fn smi_write(&mut self, phy_addr: u8, reg: u8, val: u16) {
323 let mac = T::regs().ethernet_mac(); 326 let (macmdioar, macmdiodr) = {
327 let regs = T::regs().ethernet_mac();
328 (regs.macmdioar(), regs.macmdiodr())
329 };
324 330
325 mac.macmdiodr().write(|w| w.set_md(val)); 331 macmdiodr.write(|w| w.set_md(val));
326 mac.macmdioar().modify(|w| { 332 macmdioar.modify(|w| {
327 w.set_pa(phy_addr); 333 w.set_pa(phy_addr);
328 w.set_rda(reg); 334 w.set_rda(reg);
329 w.set_goc(0b01); // write 335 w.set_goc(0b01); // write
330 w.set_cr(self.clock_range); 336 w.set_cr(self.clock_range);
331 w.set_mb(true); 337 w.set_mb(true);
332 }); 338 });
333 while mac.macmdioar().read().mb() {} 339 while macmdioar.read().mb() {}
334 } 340 }
335} 341}
336 342
@@ -370,3 +376,9 @@ impl<'d, T: Instance, P: Phy> Drop for Ethernet<'d, T, P> {
370 }) 376 })
371 } 377 }
372} 378}
379
380impl<T: Instance> Drop for EthernetStationManagement<'_, T> {
381 fn drop(&mut self) {
382 self.pins.iter_mut().for_each(|p| p.set_as_disconnected());
383 }
384}