diff options
| author | Dario Nieuwenhuis <[email protected]> | 2025-04-15 10:34:27 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-04-15 10:34:27 +0000 |
| commit | e56a1d0e457bee087a4094206b277fbf595a8f17 (patch) | |
| tree | cef468c1a38079030de53be24fa3021f8c3418d8 | |
| parent | 05c663490422f0aaaf539de2ef570267582ca1c2 (diff) | |
| parent | d9f708ca6dff653ca7ab6c24b5e9e437ea922ce4 (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.rs | 131 |
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. | ||
| 61 | enum Pins<'d> { | ||
| 62 | Rmii([Peri<'d, AnyPin>; 9]), | ||
| 63 | Mii([Peri<'d, AnyPin>; 14]), | ||
| 64 | } | ||
| 65 | |||
| 60 | #[cfg(eth_v1a)] | 66 | #[cfg(eth_v1a)] |
| 61 | macro_rules! config_in_pins { | 67 | macro_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 | }) |
