diff options
| author | datdenkikniet <[email protected]> | 2025-11-12 21:39:40 +0100 |
|---|---|---|
| committer | datdenkikniet <[email protected]> | 2025-11-13 23:08:33 +0100 |
| commit | 3f9865f9d8e9be95cad25df3f535fbe01087ed83 (patch) | |
| tree | 540381350cfbecbe1a42cd0085ade2aa3b98864a | |
| parent | 578679771eafe93ccc0e8de8fc3f97a5b991b02c (diff) | |
Give EthernetManagement owernship of MDIO pins
| -rw-r--r-- | embassy-stm32/src/eth/v1/mod.rs | 50 | ||||
| -rw-r--r-- | embassy-stm32/src/eth/v2/mod.rs | 50 |
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. |
| 61 | enum Pins<'d> { | 61 | enum 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. |
| 379 | pub(crate) struct EthernetStationManagement<T: Instance> { | 378 | pub(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 | ||
| 384 | impl<T: Instance> StationManagement for EthernetStationManagement<T> { | 384 | impl<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 | |||
| 447 | impl<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. |
| 50 | enum Pins<'d> { | 50 | enum 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 | ||
| 55 | macro_rules! config_pins { | 55 | macro_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. |
| 302 | pub struct EthernetStationManagement<T: Instance> { | 301 | pub 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 | ||
| 307 | impl<T: Instance> StationManagement for EthernetStationManagement<T> { | 307 | impl<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 | |||
| 380 | impl<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 | } | ||
