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 | |
| 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.
| -rw-r--r-- | embassy-stm32/build.rs | 7 | ||||
| -rw-r--r-- | embassy-stm32/src/eth/mod.rs | 7 | ||||
| -rw-r--r-- | embassy-stm32/src/eth/v2/mod.rs | 136 | ||||
| -rw-r--r-- | examples/stm32f4/src/bin/eth.rs | 2 | ||||
| -rw-r--r-- | examples/stm32f7/src/bin/eth.rs | 2 | ||||
| -rw-r--r-- | examples/stm32h5/src/bin/eth.rs | 2 | ||||
| -rw-r--r-- | examples/stm32h7/src/bin/eth.rs | 2 | ||||
| -rw-r--r-- | examples/stm32h7/src/bin/eth_client.rs | 2 | ||||
| -rw-r--r-- | examples/stm32h7/src/bin/eth_client_mii.rs | 142 | ||||
| -rw-r--r-- | tests/stm32/src/bin/eth.rs | 21 |
10 files changed, 295 insertions, 28 deletions
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index 414723573..bd4195619 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs | |||
| @@ -735,13 +735,20 @@ fn main() { | |||
| 735 | (("can", "TX"), quote!(crate::can::TxPin)), | 735 | (("can", "TX"), quote!(crate::can::TxPin)), |
| 736 | (("can", "RX"), quote!(crate::can::RxPin)), | 736 | (("can", "RX"), quote!(crate::can::RxPin)), |
| 737 | (("eth", "REF_CLK"), quote!(crate::eth::RefClkPin)), | 737 | (("eth", "REF_CLK"), quote!(crate::eth::RefClkPin)), |
| 738 | (("eth", "RX_CLK"), quote!(crate::eth::RXClkPin)), | ||
| 739 | (("eth", "TX_CLK"), quote!(crate::eth::TXClkPin)), | ||
| 738 | (("eth", "MDIO"), quote!(crate::eth::MDIOPin)), | 740 | (("eth", "MDIO"), quote!(crate::eth::MDIOPin)), |
| 739 | (("eth", "MDC"), quote!(crate::eth::MDCPin)), | 741 | (("eth", "MDC"), quote!(crate::eth::MDCPin)), |
| 740 | (("eth", "CRS_DV"), quote!(crate::eth::CRSPin)), | 742 | (("eth", "CRS_DV"), quote!(crate::eth::CRSPin)), |
| 743 | (("eth", "RX_DV"), quote!(crate::eth::RXDVPin)), | ||
| 741 | (("eth", "RXD0"), quote!(crate::eth::RXD0Pin)), | 744 | (("eth", "RXD0"), quote!(crate::eth::RXD0Pin)), |
| 742 | (("eth", "RXD1"), quote!(crate::eth::RXD1Pin)), | 745 | (("eth", "RXD1"), quote!(crate::eth::RXD1Pin)), |
| 746 | (("eth", "RXD2"), quote!(crate::eth::RXD2Pin)), | ||
| 747 | (("eth", "RXD3"), quote!(crate::eth::RXD3Pin)), | ||
| 743 | (("eth", "TXD0"), quote!(crate::eth::TXD0Pin)), | 748 | (("eth", "TXD0"), quote!(crate::eth::TXD0Pin)), |
| 744 | (("eth", "TXD1"), quote!(crate::eth::TXD1Pin)), | 749 | (("eth", "TXD1"), quote!(crate::eth::TXD1Pin)), |
| 750 | (("eth", "TXD2"), quote!(crate::eth::TXD2Pin)), | ||
| 751 | (("eth", "TXD3"), quote!(crate::eth::TXD3Pin)), | ||
| 745 | (("eth", "TX_EN"), quote!(crate::eth::TXEnPin)), | 752 | (("eth", "TX_EN"), quote!(crate::eth::TXEnPin)), |
| 746 | (("fmc", "A0"), quote!(crate::fmc::A0Pin)), | 753 | (("fmc", "A0"), quote!(crate::fmc::A0Pin)), |
| 747 | (("fmc", "A1"), quote!(crate::fmc::A1Pin)), | 754 | (("fmc", "A1"), quote!(crate::fmc::A1Pin)), |
diff --git a/embassy-stm32/src/eth/mod.rs b/embassy-stm32/src/eth/mod.rs index 448405507..fbcdd7fae 100644 --- a/embassy-stm32/src/eth/mod.rs +++ b/embassy-stm32/src/eth/mod.rs | |||
| @@ -192,12 +192,19 @@ impl sealed::Instance for crate::peripherals::ETH { | |||
| 192 | } | 192 | } |
| 193 | impl Instance for crate::peripherals::ETH {} | 193 | impl Instance for crate::peripherals::ETH {} |
| 194 | 194 | ||
| 195 | pin_trait!(RXClkPin, Instance); | ||
| 196 | pin_trait!(TXClkPin, Instance); | ||
| 195 | pin_trait!(RefClkPin, Instance); | 197 | pin_trait!(RefClkPin, Instance); |
| 196 | pin_trait!(MDIOPin, Instance); | 198 | pin_trait!(MDIOPin, Instance); |
| 197 | pin_trait!(MDCPin, Instance); | 199 | pin_trait!(MDCPin, Instance); |
| 200 | pin_trait!(RXDVPin, Instance); | ||
| 198 | pin_trait!(CRSPin, Instance); | 201 | pin_trait!(CRSPin, Instance); |
| 199 | pin_trait!(RXD0Pin, Instance); | 202 | pin_trait!(RXD0Pin, Instance); |
| 200 | pin_trait!(RXD1Pin, Instance); | 203 | pin_trait!(RXD1Pin, Instance); |
| 204 | pin_trait!(RXD2Pin, Instance); | ||
| 205 | pin_trait!(RXD3Pin, Instance); | ||
| 201 | pin_trait!(TXD0Pin, Instance); | 206 | pin_trait!(TXD0Pin, Instance); |
| 202 | pin_trait!(TXD1Pin, Instance); | 207 | pin_trait!(TXD1Pin, Instance); |
| 208 | pin_trait!(TXD2Pin, Instance); | ||
| 209 | pin_trait!(TXD3Pin, Instance); | ||
| 203 | pin_trait!(TXEnPin, Instance); | 210 | pin_trait!(TXEnPin, Instance); |
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 | }) |
diff --git a/examples/stm32f4/src/bin/eth.rs b/examples/stm32f4/src/bin/eth.rs index 7f5c8fdb1..2933cfe3c 100644 --- a/examples/stm32f4/src/bin/eth.rs +++ b/examples/stm32f4/src/bin/eth.rs | |||
| @@ -63,7 +63,7 @@ async fn main(spawner: Spawner) -> ! { | |||
| 63 | let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF]; | 63 | let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF]; |
| 64 | 64 | ||
| 65 | static PACKETS: StaticCell<PacketQueue<16, 16>> = StaticCell::new(); | 65 | static PACKETS: StaticCell<PacketQueue<16, 16>> = StaticCell::new(); |
| 66 | let device = Ethernet::new( | 66 | let device = Ethernet::new_rmii( |
| 67 | PACKETS.init(PacketQueue::<16, 16>::new()), | 67 | PACKETS.init(PacketQueue::<16, 16>::new()), |
| 68 | p.ETH, | 68 | p.ETH, |
| 69 | Irqs, | 69 | Irqs, |
diff --git a/examples/stm32f7/src/bin/eth.rs b/examples/stm32f7/src/bin/eth.rs index 5bff48197..85b5bd3e0 100644 --- a/examples/stm32f7/src/bin/eth.rs +++ b/examples/stm32f7/src/bin/eth.rs | |||
| @@ -64,7 +64,7 @@ async fn main(spawner: Spawner) -> ! { | |||
| 64 | let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF]; | 64 | let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF]; |
| 65 | 65 | ||
| 66 | static PACKETS: StaticCell<PacketQueue<16, 16>> = StaticCell::new(); | 66 | static PACKETS: StaticCell<PacketQueue<16, 16>> = StaticCell::new(); |
| 67 | let device = Ethernet::new( | 67 | let device = Ethernet::new_rmii( |
| 68 | PACKETS.init(PacketQueue::<16, 16>::new()), | 68 | PACKETS.init(PacketQueue::<16, 16>::new()), |
| 69 | p.ETH, | 69 | p.ETH, |
| 70 | Irqs, | 70 | Irqs, |
diff --git a/examples/stm32h5/src/bin/eth.rs b/examples/stm32h5/src/bin/eth.rs index 2370656e6..79288877f 100644 --- a/examples/stm32h5/src/bin/eth.rs +++ b/examples/stm32h5/src/bin/eth.rs | |||
| @@ -67,7 +67,7 @@ async fn main(spawner: Spawner) -> ! { | |||
| 67 | let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF]; | 67 | let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF]; |
| 68 | 68 | ||
| 69 | static PACKETS: StaticCell<PacketQueue<4, 4>> = StaticCell::new(); | 69 | static PACKETS: StaticCell<PacketQueue<4, 4>> = StaticCell::new(); |
| 70 | let device = Ethernet::new( | 70 | let device = Ethernet::new_rmii( |
| 71 | PACKETS.init(PacketQueue::<4, 4>::new()), | 71 | PACKETS.init(PacketQueue::<4, 4>::new()), |
| 72 | p.ETH, | 72 | p.ETH, |
| 73 | Irqs, | 73 | Irqs, |
diff --git a/examples/stm32h7/src/bin/eth.rs b/examples/stm32h7/src/bin/eth.rs index cd9a27fcd..9abdcf3c0 100644 --- a/examples/stm32h7/src/bin/eth.rs +++ b/examples/stm32h7/src/bin/eth.rs | |||
| @@ -64,7 +64,7 @@ async fn main(spawner: Spawner) -> ! { | |||
| 64 | let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF]; | 64 | let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF]; |
| 65 | 65 | ||
| 66 | static PACKETS: StaticCell<PacketQueue<4, 4>> = StaticCell::new(); | 66 | static PACKETS: StaticCell<PacketQueue<4, 4>> = StaticCell::new(); |
| 67 | let device = Ethernet::new( | 67 | let device = Ethernet::new_rmii( |
| 68 | PACKETS.init(PacketQueue::<4, 4>::new()), | 68 | PACKETS.init(PacketQueue::<4, 4>::new()), |
| 69 | p.ETH, | 69 | p.ETH, |
| 70 | Irqs, | 70 | Irqs, |
diff --git a/examples/stm32h7/src/bin/eth_client.rs b/examples/stm32h7/src/bin/eth_client.rs index dcc6e36e2..c4da5776f 100644 --- a/examples/stm32h7/src/bin/eth_client.rs +++ b/examples/stm32h7/src/bin/eth_client.rs | |||
| @@ -65,7 +65,7 @@ async fn main(spawner: Spawner) -> ! { | |||
| 65 | let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF]; | 65 | let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF]; |
| 66 | 66 | ||
| 67 | static PACKETS: StaticCell<PacketQueue<16, 16>> = StaticCell::new(); | 67 | static PACKETS: StaticCell<PacketQueue<16, 16>> = StaticCell::new(); |
| 68 | let device = Ethernet::new( | 68 | let device = Ethernet::new_rmii( |
| 69 | PACKETS.init(PacketQueue::<16, 16>::new()), | 69 | PACKETS.init(PacketQueue::<16, 16>::new()), |
| 70 | p.ETH, | 70 | p.ETH, |
| 71 | Irqs, | 71 | Irqs, |
diff --git a/examples/stm32h7/src/bin/eth_client_mii.rs b/examples/stm32h7/src/bin/eth_client_mii.rs new file mode 100644 index 000000000..de6ea522a --- /dev/null +++ b/examples/stm32h7/src/bin/eth_client_mii.rs | |||
| @@ -0,0 +1,142 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::*; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_net::tcp::client::{TcpClient, TcpClientState}; | ||
| 7 | use embassy_net::{Stack, StackResources}; | ||
| 8 | use embassy_stm32::eth::generic_smi::GenericSMI; | ||
| 9 | use embassy_stm32::eth::{Ethernet, PacketQueue}; | ||
| 10 | use embassy_stm32::peripherals::ETH; | ||
| 11 | use embassy_stm32::rng::Rng; | ||
| 12 | use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; | ||
| 13 | use embassy_time::Timer; | ||
| 14 | use embedded_io_async::Write; | ||
| 15 | use embedded_nal_async::{Ipv4Addr, SocketAddr, SocketAddrV4, TcpConnect}; | ||
| 16 | use rand_core::RngCore; | ||
| 17 | use static_cell::StaticCell; | ||
| 18 | use {defmt_rtt as _, panic_probe as _}; | ||
| 19 | |||
| 20 | bind_interrupts!(struct Irqs { | ||
| 21 | ETH => eth::InterruptHandler; | ||
| 22 | RNG => rng::InterruptHandler<peripherals::RNG>; | ||
| 23 | }); | ||
| 24 | |||
| 25 | type Device = Ethernet<'static, ETH, GenericSMI>; | ||
| 26 | |||
| 27 | #[embassy_executor::task] | ||
| 28 | async fn net_task(stack: &'static Stack<Device>) -> ! { | ||
| 29 | stack.run().await | ||
| 30 | } | ||
| 31 | |||
| 32 | #[embassy_executor::main] | ||
| 33 | async fn main(spawner: Spawner) -> ! { | ||
| 34 | let mut config = Config::default(); | ||
| 35 | { | ||
| 36 | use embassy_stm32::rcc::*; | ||
| 37 | config.rcc.hsi = Some(HSIPrescaler::DIV1); | ||
| 38 | config.rcc.csi = true; | ||
| 39 | config.rcc.hsi48 = Some(Default::default()); // needed for RNG | ||
| 40 | config.rcc.pll1 = Some(Pll { | ||
| 41 | source: PllSource::HSI, | ||
| 42 | prediv: PllPreDiv::DIV4, | ||
| 43 | mul: PllMul::MUL50, | ||
| 44 | divp: Some(PllDiv::DIV2), | ||
| 45 | divq: None, | ||
| 46 | divr: None, | ||
| 47 | }); | ||
| 48 | config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz | ||
| 49 | config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz | ||
| 50 | config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz | ||
| 51 | config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz | ||
| 52 | config.rcc.apb3_pre = APBPrescaler::DIV2; // 100 Mhz | ||
| 53 | config.rcc.apb4_pre = APBPrescaler::DIV2; // 100 Mhz | ||
| 54 | config.rcc.voltage_scale = VoltageScale::Scale1; | ||
| 55 | } | ||
| 56 | let p = embassy_stm32::init(config); | ||
| 57 | info!("Hello World!"); | ||
| 58 | |||
| 59 | // Generate random seed. | ||
| 60 | let mut rng = Rng::new(p.RNG, Irqs); | ||
| 61 | let mut seed = [0; 8]; | ||
| 62 | rng.fill_bytes(&mut seed); | ||
| 63 | let seed = u64::from_le_bytes(seed); | ||
| 64 | |||
| 65 | let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF]; | ||
| 66 | |||
| 67 | static PACKETS: StaticCell<PacketQueue<16, 16>> = StaticCell::new(); | ||
| 68 | |||
| 69 | let device = Ethernet::new_mii( | ||
| 70 | PACKETS.init(PacketQueue::<16, 16>::new()), | ||
| 71 | p.ETH, | ||
| 72 | Irqs, | ||
| 73 | p.PA1, | ||
| 74 | p.PC3, | ||
| 75 | p.PA2, | ||
| 76 | p.PC1, | ||
| 77 | p.PA7, | ||
| 78 | p.PC4, | ||
| 79 | p.PC5, | ||
| 80 | p.PB0, | ||
| 81 | p.PB1, | ||
| 82 | p.PG13, | ||
| 83 | p.PG12, | ||
| 84 | p.PC2, | ||
| 85 | p.PE2, | ||
| 86 | p.PG11, | ||
| 87 | GenericSMI::new(1), | ||
| 88 | mac_addr, | ||
| 89 | ); | ||
| 90 | info!("Device created"); | ||
| 91 | |||
| 92 | let config = embassy_net::Config::dhcpv4(Default::default()); | ||
| 93 | //let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { | ||
| 94 | // address: Ipv4Cidr::new(Ipv4Address::new(10, 42, 0, 61), 24), | ||
| 95 | // dns_servers: Vec::new(), | ||
| 96 | // gateway: Some(Ipv4Address::new(10, 42, 0, 1)), | ||
| 97 | //}); | ||
| 98 | |||
| 99 | // Init network stack | ||
| 100 | static STACK: StaticCell<Stack<Device>> = StaticCell::new(); | ||
| 101 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | ||
| 102 | let stack = &*STACK.init(Stack::new( | ||
| 103 | device, | ||
| 104 | config, | ||
| 105 | RESOURCES.init(StackResources::<3>::new()), | ||
| 106 | seed, | ||
| 107 | )); | ||
| 108 | |||
| 109 | // Launch network task | ||
| 110 | unwrap!(spawner.spawn(net_task(stack))); | ||
| 111 | |||
| 112 | // Ensure DHCP configuration is up before trying connect | ||
| 113 | stack.wait_config_up().await; | ||
| 114 | |||
| 115 | info!("Network task initialized"); | ||
| 116 | |||
| 117 | let state: TcpClientState<1, 1024, 1024> = TcpClientState::new(); | ||
| 118 | let client = TcpClient::new(&stack, &state); | ||
| 119 | |||
| 120 | loop { | ||
| 121 | // You need to start a server on the host machine, for example: `nc -l 8000` | ||
| 122 | let addr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(192, 168, 100, 1), 8000)); | ||
| 123 | |||
| 124 | info!("connecting..."); | ||
| 125 | let r = client.connect(addr).await; | ||
| 126 | if let Err(e) = r { | ||
| 127 | info!("connect error: {:?}", e); | ||
| 128 | Timer::after_secs(1).await; | ||
| 129 | continue; | ||
| 130 | } | ||
| 131 | let mut connection = r.unwrap(); | ||
| 132 | info!("connected!"); | ||
| 133 | loop { | ||
| 134 | let r = connection.write_all(b"Hello\n").await; | ||
| 135 | if let Err(e) = r { | ||
| 136 | info!("write error: {:?}", e); | ||
| 137 | break; | ||
| 138 | } | ||
| 139 | Timer::after_secs(1).await; | ||
| 140 | } | ||
| 141 | } | ||
| 142 | } | ||
diff --git a/tests/stm32/src/bin/eth.rs b/tests/stm32/src/bin/eth.rs index 7c02f0354..b244874e7 100644 --- a/tests/stm32/src/bin/eth.rs +++ b/tests/stm32/src/bin/eth.rs | |||
| @@ -71,6 +71,7 @@ async fn main(spawner: Spawner) { | |||
| 71 | const PACKET_QUEUE_SIZE: usize = 4; | 71 | const PACKET_QUEUE_SIZE: usize = 4; |
| 72 | 72 | ||
| 73 | static PACKETS: StaticCell<PacketQueue<PACKET_QUEUE_SIZE, PACKET_QUEUE_SIZE>> = StaticCell::new(); | 73 | static PACKETS: StaticCell<PacketQueue<PACKET_QUEUE_SIZE, PACKET_QUEUE_SIZE>> = StaticCell::new(); |
| 74 | #[cfg(not(eth_v2))] | ||
| 74 | let device = Ethernet::new( | 75 | let device = Ethernet::new( |
| 75 | PACKETS.init(PacketQueue::<PACKET_QUEUE_SIZE, PACKET_QUEUE_SIZE>::new()), | 76 | PACKETS.init(PacketQueue::<PACKET_QUEUE_SIZE, PACKET_QUEUE_SIZE>::new()), |
| 76 | p.ETH, | 77 | p.ETH, |
| @@ -90,6 +91,26 @@ async fn main(spawner: Spawner) { | |||
| 90 | GenericSMI::new(0), | 91 | GenericSMI::new(0), |
| 91 | mac_addr, | 92 | mac_addr, |
| 92 | ); | 93 | ); |
| 94 | #[cfg(eth_v2)] | ||
| 95 | let device = Ethernet::new_rmii( | ||
| 96 | PACKETS.init(PacketQueue::<PACKET_QUEUE_SIZE, PACKET_QUEUE_SIZE>::new()), | ||
| 97 | p.ETH, | ||
| 98 | Irqs, | ||
| 99 | p.PA1, | ||
| 100 | p.PA2, | ||
| 101 | p.PC1, | ||
| 102 | p.PA7, | ||
| 103 | p.PC4, | ||
| 104 | p.PC5, | ||
| 105 | p.PG13, | ||
| 106 | #[cfg(not(feature = "stm32h563zi"))] | ||
| 107 | p.PB13, | ||
| 108 | #[cfg(feature = "stm32h563zi")] | ||
| 109 | p.PB15, | ||
| 110 | p.PG11, | ||
| 111 | GenericSMI::new(0), | ||
| 112 | mac_addr, | ||
| 113 | ); | ||
| 93 | 114 | ||
| 94 | let config = embassy_net::Config::dhcpv4(Default::default()); | 115 | let config = embassy_net::Config::dhcpv4(Default::default()); |
| 95 | //let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { | 116 | //let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { |
