diff options
| author | Simon B. Gasse <[email protected]> | 2024-01-19 21:10:03 +0100 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2024-02-01 01:33:34 +0100 |
| commit | 42d8f3930a861dcc4540198bf2038151eb4e3e27 (patch) | |
| tree | a188a1489792563413a9330d9fb74d7cb42dd01a /embassy-stm32/src/eth/v2/mod.rs | |
| parent | e05f6505ae18696ad178119c747775b7e839ae8d (diff) | |
Implement MII interface
- Extend the eth/v2 module to support MII besides RMII.
- Replace `Ethernet::new` with `Ethernet::new_mii` and
`Ethernet::new_rmii`.
- Update ethernet examples.
- Add example for MII ethernet.
Diffstat (limited to 'embassy-stm32/src/eth/v2/mod.rs')
| -rw-r--r-- | embassy-stm32/src/eth/v2/mod.rs | 136 |
1 files changed, 113 insertions, 23 deletions
diff --git a/embassy-stm32/src/eth/v2/mod.rs b/embassy-stm32/src/eth/v2/mod.rs index 59745cba0..a176b01e5 100644 --- a/embassy-stm32/src/eth/v2/mod.rs +++ b/embassy-stm32/src/eth/v2/mod.rs | |||
| @@ -39,12 +39,18 @@ pub struct Ethernet<'d, T: Instance, P: PHY> { | |||
| 39 | _peri: PeripheralRef<'d, T>, | 39 | _peri: PeripheralRef<'d, T>, |
| 40 | pub(crate) tx: TDesRing<'d>, | 40 | pub(crate) tx: TDesRing<'d>, |
| 41 | pub(crate) rx: RDesRing<'d>, | 41 | pub(crate) rx: RDesRing<'d>, |
| 42 | pins: [PeripheralRef<'d, AnyPin>; 9], | 42 | pins: Pins<'d>, |
| 43 | pub(crate) phy: P, | 43 | pub(crate) phy: P, |
| 44 | pub(crate) station_management: EthernetStationManagement<T>, | 44 | pub(crate) station_management: EthernetStationManagement<T>, |
| 45 | pub(crate) mac_addr: [u8; 6], | 45 | pub(crate) mac_addr: [u8; 6], |
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | /// Pins of ethernet driver. | ||
| 49 | enum Pins<'d> { | ||
| 50 | Rmii([PeripheralRef<'d, AnyPin>; 9]), | ||
| 51 | Mii([PeripheralRef<'d, AnyPin>; 14]), | ||
| 52 | } | ||
| 53 | |||
| 48 | macro_rules! config_pins { | 54 | macro_rules! config_pins { |
| 49 | ($($pin:ident),*) => { | 55 | ($($pin:ident),*) => { |
| 50 | critical_section::with(|_| { | 56 | critical_section::with(|_| { |
| @@ -57,11 +63,11 @@ macro_rules! config_pins { | |||
| 57 | } | 63 | } |
| 58 | 64 | ||
| 59 | impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { | 65 | impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { |
| 60 | /// Create a new Ethernet driver. | 66 | /// Create a new RMII ethernet driver using 9 pins. |
| 61 | pub fn new<const TX: usize, const RX: usize>( | 67 | pub fn new_rmii<const TX: usize, const RX: usize>( |
| 62 | queue: &'d mut PacketQueue<TX, RX>, | 68 | queue: &'d mut PacketQueue<TX, RX>, |
| 63 | peri: impl Peripheral<P = T> + 'd, | 69 | peri: impl Peripheral<P = T> + 'd, |
| 64 | _irq: impl interrupt::typelevel::Binding<interrupt::typelevel::ETH, InterruptHandler> + 'd, | 70 | irq: impl interrupt::typelevel::Binding<interrupt::typelevel::ETH, InterruptHandler> + 'd, |
| 65 | ref_clk: impl Peripheral<P = impl RefClkPin<T>> + 'd, | 71 | ref_clk: impl Peripheral<P = impl RefClkPin<T>> + 'd, |
| 66 | mdio: impl Peripheral<P = impl MDIOPin<T>> + 'd, | 72 | mdio: impl Peripheral<P = impl MDIOPin<T>> + 'd, |
| 67 | mdc: impl Peripheral<P = impl MDCPin<T>> + 'd, | 73 | mdc: impl Peripheral<P = impl MDCPin<T>> + 'd, |
| @@ -74,8 +80,6 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { | |||
| 74 | phy: P, | 80 | phy: P, |
| 75 | mac_addr: [u8; 6], | 81 | mac_addr: [u8; 6], |
| 76 | ) -> Self { | 82 | ) -> Self { |
| 77 | into_ref!(peri, ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en); | ||
| 78 | |||
| 79 | // Enable the necessary Clocks | 83 | // Enable the necessary Clocks |
| 80 | #[cfg(not(rcc_h5))] | 84 | #[cfg(not(rcc_h5))] |
| 81 | critical_section::with(|_| { | 85 | critical_section::with(|_| { |
| @@ -85,7 +89,6 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { | |||
| 85 | w.set_eth1rxen(true); | 89 | w.set_eth1rxen(true); |
| 86 | }); | 90 | }); |
| 87 | 91 | ||
| 88 | // RMII | ||
| 89 | crate::pac::SYSCFG.pmcr().modify(|w| w.set_epis(0b100)); | 92 | crate::pac::SYSCFG.pmcr().modify(|w| w.set_epis(0b100)); |
| 90 | }); | 93 | }); |
| 91 | 94 | ||
| @@ -99,14 +102,110 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { | |||
| 99 | w.set_ethrxen(true); | 102 | w.set_ethrxen(true); |
| 100 | }); | 103 | }); |
| 101 | 104 | ||
| 102 | // RMII | ||
| 103 | crate::pac::SYSCFG | 105 | crate::pac::SYSCFG |
| 104 | .pmcr() | 106 | .pmcr() |
| 105 | .modify(|w| w.set_eth_sel_phy(crate::pac::syscfg::vals::EthSelPhy::B_0X4)); | 107 | .modify(|w| w.set_eth_sel_phy(crate::pac::syscfg::vals::EthSelPhy::B_0X4)); |
| 106 | }); | 108 | }); |
| 107 | 109 | ||
| 110 | into_ref!(ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en); | ||
| 108 | config_pins!(ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en); | 111 | config_pins!(ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en); |
| 109 | 112 | ||
| 113 | let pins = Pins::Rmii([ | ||
| 114 | ref_clk.map_into(), | ||
| 115 | mdio.map_into(), | ||
| 116 | mdc.map_into(), | ||
| 117 | crs.map_into(), | ||
| 118 | rx_d0.map_into(), | ||
| 119 | rx_d1.map_into(), | ||
| 120 | tx_d0.map_into(), | ||
| 121 | tx_d1.map_into(), | ||
| 122 | tx_en.map_into(), | ||
| 123 | ]); | ||
| 124 | |||
| 125 | Self::new_inner(queue, peri, irq, pins, phy, mac_addr) | ||
| 126 | } | ||
| 127 | |||
| 128 | /// Create a new MII ethernet driver using 14 pins. | ||
| 129 | pub fn new_mii<const TX: usize, const RX: usize>( | ||
| 130 | queue: &'d mut PacketQueue<TX, RX>, | ||
| 131 | peri: impl Peripheral<P = T> + 'd, | ||
| 132 | irq: impl interrupt::typelevel::Binding<interrupt::typelevel::ETH, InterruptHandler> + 'd, | ||
| 133 | rx_clk: impl Peripheral<P = impl RXClkPin<T>> + 'd, | ||
| 134 | tx_clk: impl Peripheral<P = impl TXClkPin<T>> + 'd, | ||
| 135 | mdio: impl Peripheral<P = impl MDIOPin<T>> + 'd, | ||
| 136 | mdc: impl Peripheral<P = impl MDCPin<T>> + 'd, | ||
| 137 | rxdv: impl Peripheral<P = impl RXDVPin<T>> + 'd, | ||
| 138 | rx_d0: impl Peripheral<P = impl RXD0Pin<T>> + 'd, | ||
| 139 | rx_d1: impl Peripheral<P = impl RXD1Pin<T>> + 'd, | ||
| 140 | rx_d2: impl Peripheral<P = impl RXD2Pin<T>> + 'd, | ||
| 141 | rx_d3: impl Peripheral<P = impl RXD3Pin<T>> + 'd, | ||
| 142 | tx_d0: impl Peripheral<P = impl TXD0Pin<T>> + 'd, | ||
| 143 | tx_d1: impl Peripheral<P = impl TXD1Pin<T>> + 'd, | ||
| 144 | tx_d2: impl Peripheral<P = impl TXD2Pin<T>> + 'd, | ||
| 145 | tx_d3: impl Peripheral<P = impl TXD3Pin<T>> + 'd, | ||
| 146 | tx_en: impl Peripheral<P = impl TXEnPin<T>> + 'd, | ||
| 147 | phy: P, | ||
| 148 | mac_addr: [u8; 6], | ||
| 149 | ) -> Self { | ||
| 150 | // Enable necessary clocks. | ||
| 151 | #[cfg(not(rcc_h5))] | ||
| 152 | critical_section::with(|_| { | ||
| 153 | crate::pac::RCC.ahb1enr().modify(|w| { | ||
| 154 | w.set_eth1macen(true); | ||
| 155 | w.set_eth1txen(true); | ||
| 156 | w.set_eth1rxen(true); | ||
| 157 | }); | ||
| 158 | |||
| 159 | crate::pac::SYSCFG.pmcr().modify(|w| w.set_epis(0b000)); | ||
| 160 | }); | ||
| 161 | |||
| 162 | #[cfg(rcc_h5)] | ||
| 163 | critical_section::with(|_| { | ||
| 164 | crate::pac::RCC.apb3enr().modify(|w| w.set_sbsen(true)); | ||
| 165 | |||
| 166 | crate::pac::RCC.ahb1enr().modify(|w| { | ||
| 167 | w.set_ethen(true); | ||
| 168 | w.set_ethtxen(true); | ||
| 169 | w.set_ethrxen(true); | ||
| 170 | }); | ||
| 171 | |||
| 172 | // TODO: This is for RMII - what would MII need here? | ||
| 173 | crate::pac::SYSCFG | ||
| 174 | .pmcr() | ||
| 175 | .modify(|w| w.set_eth_sel_phy(crate::pac::syscfg::vals::EthSelPhy::B_0X4)); | ||
| 176 | }); | ||
| 177 | |||
| 178 | into_ref!(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); | ||
| 179 | 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); | ||
| 180 | |||
| 181 | let pins = Pins::Mii([ | ||
| 182 | rx_clk.map_into(), | ||
| 183 | tx_clk.map_into(), | ||
| 184 | mdio.map_into(), | ||
| 185 | mdc.map_into(), | ||
| 186 | rxdv.map_into(), | ||
| 187 | rx_d0.map_into(), | ||
| 188 | rx_d1.map_into(), | ||
| 189 | rx_d2.map_into(), | ||
| 190 | rx_d3.map_into(), | ||
| 191 | tx_d0.map_into(), | ||
| 192 | tx_d1.map_into(), | ||
| 193 | tx_d2.map_into(), | ||
| 194 | tx_d3.map_into(), | ||
| 195 | tx_en.map_into(), | ||
| 196 | ]); | ||
| 197 | |||
| 198 | Self::new_inner(queue, peri, irq, pins, phy, mac_addr) | ||
| 199 | } | ||
| 200 | |||
| 201 | fn new_inner<const TX: usize, const RX: usize>( | ||
| 202 | queue: &'d mut PacketQueue<TX, RX>, | ||
| 203 | peri: impl Peripheral<P = T> + 'd, | ||
| 204 | _irq: impl interrupt::typelevel::Binding<interrupt::typelevel::ETH, InterruptHandler> + 'd, | ||
| 205 | pins: Pins<'d>, | ||
| 206 | phy: P, | ||
| 207 | mac_addr: [u8; 6], | ||
| 208 | ) -> Self { | ||
| 110 | let dma = ETH.ethernet_dma(); | 209 | let dma = ETH.ethernet_dma(); |
| 111 | let mac = ETH.ethernet_mac(); | 210 | let mac = ETH.ethernet_mac(); |
| 112 | let mtl = ETH.ethernet_mtl(); | 211 | let mtl = ETH.ethernet_mtl(); |
| @@ -182,24 +281,12 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { | |||
| 182 | } | 281 | } |
| 183 | }; | 282 | }; |
| 184 | 283 | ||
| 185 | let pins = [ | ||
| 186 | ref_clk.map_into(), | ||
| 187 | mdio.map_into(), | ||
| 188 | mdc.map_into(), | ||
| 189 | crs.map_into(), | ||
| 190 | rx_d0.map_into(), | ||
| 191 | rx_d1.map_into(), | ||
| 192 | tx_d0.map_into(), | ||
| 193 | tx_d1.map_into(), | ||
| 194 | tx_en.map_into(), | ||
| 195 | ]; | ||
| 196 | |||
| 197 | let mut this = Self { | 284 | let mut this = Self { |
| 198 | _peri: peri, | 285 | _peri: peri.into_ref(), |
| 199 | tx: TDesRing::new(&mut queue.tx_desc, &mut queue.tx_buf), | 286 | tx: TDesRing::new(&mut queue.tx_desc, &mut queue.tx_buf), |
| 200 | rx: RDesRing::new(&mut queue.rx_desc, &mut queue.rx_buf), | 287 | rx: RDesRing::new(&mut queue.rx_desc, &mut queue.rx_buf), |
| 201 | pins, | 288 | pins, |
| 202 | phy: phy, | 289 | phy, |
| 203 | station_management: EthernetStationManagement { | 290 | station_management: EthernetStationManagement { |
| 204 | peri: PhantomData, | 291 | peri: PhantomData, |
| 205 | clock_range: clock_range, | 292 | clock_range: clock_range, |
| @@ -302,7 +389,10 @@ impl<'d, T: Instance, P: PHY> Drop for Ethernet<'d, T, P> { | |||
| 302 | dma.dmacrx_cr().modify(|w| w.set_sr(false)); | 389 | dma.dmacrx_cr().modify(|w| w.set_sr(false)); |
| 303 | 390 | ||
| 304 | critical_section::with(|_| { | 391 | critical_section::with(|_| { |
| 305 | for pin in self.pins.iter_mut() { | 392 | for pin in match self.pins { |
| 393 | Pins::Rmii(ref mut pins) => pins.iter_mut(), | ||
| 394 | Pins::Mii(ref mut pins) => pins.iter_mut(), | ||
| 395 | } { | ||
| 306 | pin.set_as_disconnected(); | 396 | pin.set_as_disconnected(); |
| 307 | } | 397 | } |
| 308 | }) | 398 | }) |
