diff options
| -rw-r--r-- | embassy-stm32/src/eth/generic_phy.rs | 45 | ||||
| -rw-r--r-- | embassy-stm32/src/eth/mod.rs | 15 | ||||
| -rw-r--r-- | embassy-stm32/src/eth/sma/mod.rs | 13 | ||||
| -rw-r--r-- | embassy-stm32/src/eth/v1/mod.rs | 24 | ||||
| -rw-r--r-- | embassy-stm32/src/eth/v2/mod.rs | 24 | ||||
| -rw-r--r-- | tests/stm32/src/bin/eth.rs | 14 |
6 files changed, 48 insertions, 87 deletions
diff --git a/embassy-stm32/src/eth/generic_phy.rs b/embassy-stm32/src/eth/generic_phy.rs index 947874d7f..4e61a83e7 100644 --- a/embassy-stm32/src/eth/generic_phy.rs +++ b/embassy-stm32/src/eth/generic_phy.rs | |||
| @@ -44,21 +44,23 @@ mod phy_consts { | |||
| 44 | use self::phy_consts::*; | 44 | use self::phy_consts::*; |
| 45 | 45 | ||
| 46 | /// Generic SMI Ethernet PHY implementation | 46 | /// Generic SMI Ethernet PHY implementation |
| 47 | pub struct GenericPhy { | 47 | pub struct GenericPhy<SM: StationManagement> { |
| 48 | phy_addr: u8, | 48 | phy_addr: u8, |
| 49 | sm: SM, | ||
| 49 | #[cfg(feature = "time")] | 50 | #[cfg(feature = "time")] |
| 50 | poll_interval: Duration, | 51 | poll_interval: Duration, |
| 51 | } | 52 | } |
| 52 | 53 | ||
| 53 | impl GenericPhy { | 54 | impl<SM: StationManagement> GenericPhy<SM> { |
| 54 | /// Construct the PHY. It assumes the address `phy_addr` in the SMI communication | 55 | /// Construct the PHY. It assumes the address `phy_addr` in the SMI communication |
| 55 | /// | 56 | /// |
| 56 | /// # Panics | 57 | /// # Panics |
| 57 | /// `phy_addr` must be in range `0..32` | 58 | /// `phy_addr` must be in range `0..32` |
| 58 | pub fn new(phy_addr: u8) -> Self { | 59 | pub fn new(sm: SM, phy_addr: u8) -> Self { |
| 59 | assert!(phy_addr < 32); | 60 | assert!(phy_addr < 32); |
| 60 | Self { | 61 | Self { |
| 61 | phy_addr, | 62 | phy_addr, |
| 63 | sm, | ||
| 62 | #[cfg(feature = "time")] | 64 | #[cfg(feature = "time")] |
| 63 | poll_interval: Duration::from_millis(500), | 65 | poll_interval: Duration::from_millis(500), |
| 64 | } | 66 | } |
| @@ -68,8 +70,9 @@ impl GenericPhy { | |||
| 68 | /// | 70 | /// |
| 69 | /// # Panics | 71 | /// # Panics |
| 70 | /// Initialization panics if PHY didn't respond on any address | 72 | /// Initialization panics if PHY didn't respond on any address |
| 71 | pub fn new_auto() -> Self { | 73 | pub fn new_auto(sm: SM) -> Self { |
| 72 | Self { | 74 | Self { |
| 75 | sm, | ||
| 73 | phy_addr: 0xFF, | 76 | phy_addr: 0xFF, |
| 74 | #[cfg(feature = "time")] | 77 | #[cfg(feature = "time")] |
| 75 | poll_interval: Duration::from_millis(500), | 78 | poll_interval: Duration::from_millis(500), |
| @@ -77,14 +80,14 @@ impl GenericPhy { | |||
| 77 | } | 80 | } |
| 78 | } | 81 | } |
| 79 | 82 | ||
| 80 | impl Phy for GenericPhy { | 83 | impl<SM: StationManagement> Phy for GenericPhy<SM> { |
| 81 | fn phy_reset<S: StationManagement>(&mut self, sm: &mut S) { | 84 | fn phy_reset(&mut self) { |
| 82 | // Detect SMI address | 85 | // Detect SMI address |
| 83 | if self.phy_addr == 0xFF { | 86 | if self.phy_addr == 0xFF { |
| 84 | for addr in 0..32 { | 87 | for addr in 0..32 { |
| 85 | sm.smi_write(addr, PHY_REG_BCR, PHY_REG_BCR_RESET); | 88 | self.sm.smi_write(addr, PHY_REG_BCR, PHY_REG_BCR_RESET); |
| 86 | for _ in 0..10 { | 89 | for _ in 0..10 { |
| 87 | if sm.smi_read(addr, PHY_REG_BCR) & PHY_REG_BCR_RESET != PHY_REG_BCR_RESET { | 90 | if self.sm.smi_read(addr, PHY_REG_BCR) & PHY_REG_BCR_RESET != PHY_REG_BCR_RESET { |
| 88 | trace!("Found ETH PHY on address {}", addr); | 91 | trace!("Found ETH PHY on address {}", addr); |
| 89 | self.phy_addr = addr; | 92 | self.phy_addr = addr; |
| 90 | return; | 93 | return; |
| @@ -96,30 +99,30 @@ impl Phy for GenericPhy { | |||
| 96 | panic!("PHY did not respond"); | 99 | panic!("PHY did not respond"); |
| 97 | } | 100 | } |
| 98 | 101 | ||
| 99 | sm.smi_write(self.phy_addr, PHY_REG_BCR, PHY_REG_BCR_RESET); | 102 | self.sm.smi_write(self.phy_addr, PHY_REG_BCR, PHY_REG_BCR_RESET); |
| 100 | while sm.smi_read(self.phy_addr, PHY_REG_BCR) & PHY_REG_BCR_RESET == PHY_REG_BCR_RESET {} | 103 | while self.sm.smi_read(self.phy_addr, PHY_REG_BCR) & PHY_REG_BCR_RESET == PHY_REG_BCR_RESET {} |
| 101 | } | 104 | } |
| 102 | 105 | ||
| 103 | fn phy_init<S: StationManagement>(&mut self, sm: &mut S) { | 106 | fn phy_init(&mut self) { |
| 104 | // Clear WU CSR | 107 | // Clear WU CSR |
| 105 | self.smi_write_ext(sm, PHY_REG_WUCSR, 0); | 108 | self.smi_write_ext(PHY_REG_WUCSR, 0); |
| 106 | 109 | ||
| 107 | // Enable auto-negotiation | 110 | // Enable auto-negotiation |
| 108 | sm.smi_write( | 111 | self.sm.smi_write( |
| 109 | self.phy_addr, | 112 | self.phy_addr, |
| 110 | PHY_REG_BCR, | 113 | PHY_REG_BCR, |
| 111 | PHY_REG_BCR_AN | PHY_REG_BCR_ANRST | PHY_REG_BCR_100M, | 114 | PHY_REG_BCR_AN | PHY_REG_BCR_ANRST | PHY_REG_BCR_100M, |
| 112 | ); | 115 | ); |
| 113 | } | 116 | } |
| 114 | 117 | ||
| 115 | fn poll_link<S: StationManagement>(&mut self, sm: &mut S, cx: &mut Context) -> bool { | 118 | fn poll_link(&mut self, cx: &mut Context) -> bool { |
| 116 | #[cfg(not(feature = "time"))] | 119 | #[cfg(not(feature = "time"))] |
| 117 | cx.waker().wake_by_ref(); | 120 | cx.waker().wake_by_ref(); |
| 118 | 121 | ||
| 119 | #[cfg(feature = "time")] | 122 | #[cfg(feature = "time")] |
| 120 | let _ = Timer::after(self.poll_interval).poll_unpin(cx); | 123 | let _ = Timer::after(self.poll_interval).poll_unpin(cx); |
| 121 | 124 | ||
| 122 | let bsr = sm.smi_read(self.phy_addr, PHY_REG_BSR); | 125 | let bsr = self.sm.smi_read(self.phy_addr, PHY_REG_BSR); |
| 123 | 126 | ||
| 124 | // No link without autonegotiate | 127 | // No link without autonegotiate |
| 125 | if bsr & PHY_REG_BSR_ANDONE == 0 { | 128 | if bsr & PHY_REG_BSR_ANDONE == 0 { |
| @@ -136,7 +139,7 @@ impl Phy for GenericPhy { | |||
| 136 | } | 139 | } |
| 137 | 140 | ||
| 138 | /// Public functions for the PHY | 141 | /// Public functions for the PHY |
| 139 | impl GenericPhy { | 142 | impl<SM: StationManagement> GenericPhy<SM> { |
| 140 | /// Set the SMI polling interval. | 143 | /// Set the SMI polling interval. |
| 141 | #[cfg(feature = "time")] | 144 | #[cfg(feature = "time")] |
| 142 | pub fn set_poll_interval(&mut self, poll_interval: Duration) { | 145 | pub fn set_poll_interval(&mut self, poll_interval: Duration) { |
| @@ -144,10 +147,10 @@ impl GenericPhy { | |||
| 144 | } | 147 | } |
| 145 | 148 | ||
| 146 | // Writes a value to an extended PHY register in MMD address space | 149 | // Writes a value to an extended PHY register in MMD address space |
| 147 | fn smi_write_ext<S: StationManagement>(&mut self, sm: &mut S, reg_addr: u16, reg_data: u16) { | 150 | fn smi_write_ext(&mut self, reg_addr: u16, reg_data: u16) { |
| 148 | sm.smi_write(self.phy_addr, PHY_REG_CTL, 0x0003); // set address | 151 | self.sm.smi_write(self.phy_addr, PHY_REG_CTL, 0x0003); // set address |
| 149 | sm.smi_write(self.phy_addr, PHY_REG_ADDAR, reg_addr); | 152 | self.sm.smi_write(self.phy_addr, PHY_REG_ADDAR, reg_addr); |
| 150 | sm.smi_write(self.phy_addr, PHY_REG_CTL, 0x4003); // set data | 153 | self.sm.smi_write(self.phy_addr, PHY_REG_CTL, 0x4003); // set data |
| 151 | sm.smi_write(self.phy_addr, PHY_REG_ADDAR, reg_data); | 154 | self.sm.smi_write(self.phy_addr, PHY_REG_ADDAR, reg_data); |
| 152 | } | 155 | } |
| 153 | } | 156 | } |
diff --git a/embassy-stm32/src/eth/mod.rs b/embassy-stm32/src/eth/mod.rs index 448d21f3f..c8bce0e8a 100644 --- a/embassy-stm32/src/eth/mod.rs +++ b/embassy-stm32/src/eth/mod.rs | |||
| @@ -111,7 +111,7 @@ impl<'d, T: Instance, P: Phy> embassy_net_driver::Driver for Ethernet<'d, T, P> | |||
| 111 | } | 111 | } |
| 112 | 112 | ||
| 113 | fn link_state(&mut self, cx: &mut Context) -> LinkState { | 113 | fn link_state(&mut self, cx: &mut Context) -> LinkState { |
| 114 | if self.phy.poll_link(&mut self.station_management, cx) { | 114 | if self.phy.poll_link(cx) { |
| 115 | LinkState::Up | 115 | LinkState::Up |
| 116 | } else { | 116 | } else { |
| 117 | LinkState::Down | 117 | LinkState::Down |
| @@ -162,21 +162,14 @@ impl<'a, 'd> embassy_net_driver::TxToken for TxToken<'a, 'd> { | |||
| 162 | /// Trait for an Ethernet PHY | 162 | /// Trait for an Ethernet PHY |
| 163 | pub trait Phy { | 163 | pub trait Phy { |
| 164 | /// Reset PHY and wait for it to come out of reset. | 164 | /// Reset PHY and wait for it to come out of reset. |
| 165 | fn phy_reset<S: StationManagement>(&mut self, sm: &mut S); | 165 | fn phy_reset(&mut self); |
| 166 | /// PHY initialisation. | 166 | /// PHY initialisation. |
| 167 | fn phy_init<S: StationManagement>(&mut self, sm: &mut S); | 167 | fn phy_init(&mut self); |
| 168 | /// Poll link to see if it is up and FD with 100Mbps | 168 | /// Poll link to see if it is up and FD with 100Mbps |
| 169 | fn poll_link<S: StationManagement>(&mut self, sm: &mut S, cx: &mut Context) -> bool; | 169 | fn poll_link(&mut self, cx: &mut Context) -> bool; |
| 170 | } | 170 | } |
| 171 | 171 | ||
| 172 | impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> { | 172 | impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> { |
| 173 | /// Directly expose the SMI interface used by the Ethernet driver. | ||
| 174 | /// | ||
| 175 | /// This can be used to for example configure special PHY registers for compliance testing. | ||
| 176 | pub fn station_management(&mut self) -> &mut impl StationManagement { | ||
| 177 | &mut self.station_management | ||
| 178 | } | ||
| 179 | |||
| 180 | /// Access the user-supplied `Phy`. | 173 | /// Access the user-supplied `Phy`. |
| 181 | pub fn phy(&self) -> &P { | 174 | pub fn phy(&self) -> &P { |
| 182 | &self.phy | 175 | &self.phy |
diff --git a/embassy-stm32/src/eth/sma/mod.rs b/embassy-stm32/src/eth/sma/mod.rs index 558107abc..6c851911d 100644 --- a/embassy-stm32/src/eth/sma/mod.rs +++ b/embassy-stm32/src/eth/sma/mod.rs | |||
| @@ -39,17 +39,4 @@ impl SealedInstance for crate::peripherals::ETH_SMA { | |||
| 39 | } | 39 | } |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | impl<T: crate::eth::Instance> SealedInstance for T { | ||
| 43 | fn regs() -> (Reg<AddressRegister, RW>, Reg<DataRegister, RW>) { | ||
| 44 | let mac = <T as crate::eth::SealedInstance>::regs().ethernet_mac(); | ||
| 45 | |||
| 46 | #[cfg(any(eth_v1a, eth_v1b, eth_v1c))] | ||
| 47 | return (mac.macmiiar(), mac.macmiidr()); | ||
| 48 | |||
| 49 | #[cfg(eth_v2)] | ||
| 50 | return (mac.macmdioar(), mac.macmdiodr()); | ||
| 51 | } | ||
| 52 | } | ||
| 53 | |||
| 54 | impl Instance for crate::peripherals::ETH_SMA {} | 42 | impl Instance for crate::peripherals::ETH_SMA {} |
| 55 | impl<T: crate::eth::Instance> Instance for T {} | ||
diff --git a/embassy-stm32/src/eth/v1/mod.rs b/embassy-stm32/src/eth/v1/mod.rs index d448537c8..45cd33d9a 100644 --- a/embassy-stm32/src/eth/v1/mod.rs +++ b/embassy-stm32/src/eth/v1/mod.rs | |||
| @@ -10,9 +10,7 @@ use stm32_metapac::eth::vals::{Apcs, Dm, DmaomrSr, Fes, Ftf, Ifg, Pbl, Rsf, St, | |||
| 10 | 10 | ||
| 11 | pub(crate) use self::rx_desc::{RDes, RDesRing}; | 11 | pub(crate) use self::rx_desc::{RDes, RDesRing}; |
| 12 | pub(crate) use self::tx_desc::{TDes, TDesRing}; | 12 | pub(crate) use self::tx_desc::{TDes, TDesRing}; |
| 13 | use super::sma::Sma; | ||
| 14 | use super::*; | 13 | use super::*; |
| 15 | use crate::eth::{MDCPin, MDIOPin}; | ||
| 16 | #[cfg(eth_v1a)] | 14 | #[cfg(eth_v1a)] |
| 17 | use crate::gpio::Pull; | 15 | use crate::gpio::Pull; |
| 18 | use crate::gpio::{AfType, AnyPin, OutputType, SealedPin, Speed}; | 16 | use crate::gpio::{AfType, AnyPin, OutputType, SealedPin, Speed}; |
| @@ -53,7 +51,6 @@ pub struct Ethernet<'d, T: Instance, P: Phy> { | |||
| 53 | 51 | ||
| 54 | pins: Pins<'d>, | 52 | pins: Pins<'d>, |
| 55 | pub(crate) phy: P, | 53 | pub(crate) phy: P, |
| 56 | pub(crate) station_management: Sma<'d, T>, | ||
| 57 | pub(crate) mac_addr: [u8; 6], | 54 | pub(crate) mac_addr: [u8; 6], |
| 58 | } | 55 | } |
| 59 | 56 | ||
| @@ -104,8 +101,6 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> { | |||
| 104 | peri: Peri<'d, T>, | 101 | peri: Peri<'d, T>, |
| 105 | irq: impl interrupt::typelevel::Binding<interrupt::typelevel::ETH, InterruptHandler> + 'd, | 102 | irq: impl interrupt::typelevel::Binding<interrupt::typelevel::ETH, InterruptHandler> + 'd, |
| 106 | ref_clk: Peri<'d, if_afio!(impl RefClkPin<T, A>)>, | 103 | ref_clk: Peri<'d, if_afio!(impl RefClkPin<T, A>)>, |
| 107 | mdio: Peri<'d, if_afio!(impl MDIOPin<T, A>)>, | ||
| 108 | mdc: Peri<'d, if_afio!(impl MDCPin<T, A>)>, | ||
| 109 | crs: Peri<'d, if_afio!(impl CRSPin<T, A>)>, | 104 | crs: Peri<'d, if_afio!(impl CRSPin<T, A>)>, |
| 110 | rx_d0: Peri<'d, if_afio!(impl RXD0Pin<T, A>)>, | 105 | rx_d0: Peri<'d, if_afio!(impl RXD0Pin<T, A>)>, |
| 111 | rx_d1: Peri<'d, if_afio!(impl RXD1Pin<T, A>)>, | 106 | rx_d1: Peri<'d, if_afio!(impl RXD1Pin<T, A>)>, |
| @@ -165,16 +160,14 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> { | |||
| 165 | tx_en.into(), | 160 | tx_en.into(), |
| 166 | ]); | 161 | ]); |
| 167 | 162 | ||
| 168 | Self::new_inner(queue, peri, irq, pins, mdio, mdc, phy, mac_addr) | 163 | Self::new_inner(queue, peri, irq, pins, phy, mac_addr) |
| 169 | } | 164 | } |
| 170 | 165 | ||
| 171 | fn new_inner<const TX: usize, const RX: usize, #[cfg(afio)] A>( | 166 | fn new_inner<const TX: usize, const RX: usize>( |
| 172 | queue: &'d mut PacketQueue<TX, RX>, | 167 | queue: &'d mut PacketQueue<TX, RX>, |
| 173 | peri: Peri<'d, T>, | 168 | peri: Peri<'d, T>, |
| 174 | _irq: impl interrupt::typelevel::Binding<interrupt::typelevel::ETH, InterruptHandler> + 'd, | 169 | _irq: impl interrupt::typelevel::Binding<interrupt::typelevel::ETH, InterruptHandler> + 'd, |
| 175 | pins: Pins<'d>, | 170 | 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, | 171 | phy: P, |
| 179 | mac_addr: [u8; 6], | 172 | mac_addr: [u8; 6], |
| 180 | ) -> Self { | 173 | ) -> Self { |
| @@ -226,13 +219,10 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> { | |||
| 226 | 219 | ||
| 227 | // TODO MTU size setting not found for v1 ethernet, check if correct | 220 | // TODO MTU size setting not found for v1 ethernet, check if correct |
| 228 | 221 | ||
| 229 | let sma_peri = unsafe { peri.clone_unchecked() }; | ||
| 230 | |||
| 231 | let mut this = Self { | 222 | let mut this = Self { |
| 232 | _peri: peri, | 223 | _peri: peri, |
| 233 | pins, | 224 | pins, |
| 234 | phy: phy, | 225 | phy: phy, |
| 235 | station_management: Sma::new(sma_peri, mdio, mdc), | ||
| 236 | mac_addr, | 226 | mac_addr, |
| 237 | tx: TDesRing::new(&mut queue.tx_desc, &mut queue.tx_buf), | 227 | tx: TDesRing::new(&mut queue.tx_desc, &mut queue.tx_buf), |
| 238 | rx: RDesRing::new(&mut queue.rx_desc, &mut queue.rx_buf), | 228 | rx: RDesRing::new(&mut queue.rx_desc, &mut queue.rx_buf), |
| @@ -262,8 +252,8 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> { | |||
| 262 | w.set_tie(true); | 252 | w.set_tie(true); |
| 263 | }); | 253 | }); |
| 264 | 254 | ||
| 265 | this.phy.phy_reset(&mut this.station_management); | 255 | this.phy.phy_reset(); |
| 266 | this.phy.phy_init(&mut this.station_management); | 256 | this.phy.phy_init(); |
| 267 | 257 | ||
| 268 | interrupt::ETH.unpend(); | 258 | interrupt::ETH.unpend(); |
| 269 | unsafe { interrupt::ETH.enable() }; | 259 | unsafe { interrupt::ETH.enable() }; |
| @@ -271,15 +261,13 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> { | |||
| 271 | this | 261 | this |
| 272 | } | 262 | } |
| 273 | 263 | ||
| 274 | /// Create a new MII ethernet driver using 14 pins. | 264 | /// Create a new MII ethernet driver using 12 pins. |
| 275 | pub fn new_mii<const TX: usize, const RX: usize, #[cfg(afio)] A>( | 265 | pub fn new_mii<const TX: usize, const RX: usize, #[cfg(afio)] A>( |
| 276 | queue: &'d mut PacketQueue<TX, RX>, | 266 | queue: &'d mut PacketQueue<TX, RX>, |
| 277 | peri: Peri<'d, T>, | 267 | peri: Peri<'d, T>, |
| 278 | irq: impl interrupt::typelevel::Binding<interrupt::typelevel::ETH, InterruptHandler> + 'd, | 268 | irq: impl interrupt::typelevel::Binding<interrupt::typelevel::ETH, InterruptHandler> + 'd, |
| 279 | rx_clk: Peri<'d, if_afio!(impl RXClkPin<T, A>)>, | 269 | rx_clk: Peri<'d, if_afio!(impl RXClkPin<T, A>)>, |
| 280 | tx_clk: Peri<'d, if_afio!(impl TXClkPin<T, A>)>, | 270 | tx_clk: Peri<'d, if_afio!(impl TXClkPin<T, A>)>, |
| 281 | mdio: Peri<'d, if_afio!(impl MDIOPin<T, A>)>, | ||
| 282 | mdc: Peri<'d, if_afio!(impl MDCPin<T, A>)>, | ||
| 283 | rxdv: Peri<'d, if_afio!(impl RXDVPin<T, A>)>, | 271 | rxdv: Peri<'d, if_afio!(impl RXDVPin<T, A>)>, |
| 284 | rx_d0: Peri<'d, if_afio!(impl RXD0Pin<T, A>)>, | 272 | rx_d0: Peri<'d, if_afio!(impl RXD0Pin<T, A>)>, |
| 285 | rx_d1: Peri<'d, if_afio!(impl RXD1Pin<T, A>)>, | 273 | rx_d1: Peri<'d, if_afio!(impl RXD1Pin<T, A>)>, |
| @@ -352,7 +340,7 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> { | |||
| 352 | tx_en.into(), | 340 | tx_en.into(), |
| 353 | ]); | 341 | ]); |
| 354 | 342 | ||
| 355 | Self::new_inner(queue, peri, irq, pins, mdio, mdc, phy, mac_addr) | 343 | Self::new_inner(queue, peri, irq, pins, phy, mac_addr) |
| 356 | } | 344 | } |
| 357 | } | 345 | } |
| 358 | 346 | ||
diff --git a/embassy-stm32/src/eth/v2/mod.rs b/embassy-stm32/src/eth/v2/mod.rs index 0db335a7c..faed7d8e2 100644 --- a/embassy-stm32/src/eth/v2/mod.rs +++ b/embassy-stm32/src/eth/v2/mod.rs | |||
| @@ -6,9 +6,7 @@ use embassy_hal_internal::Peri; | |||
| 6 | use stm32_metapac::syscfg::vals::EthSelPhy; | 6 | use stm32_metapac::syscfg::vals::EthSelPhy; |
| 7 | 7 | ||
| 8 | pub(crate) use self::descriptors::{RDes, RDesRing, TDes, TDesRing}; | 8 | pub(crate) use self::descriptors::{RDes, RDesRing, TDes, TDesRing}; |
| 9 | use super::sma::Sma; | ||
| 10 | use super::*; | 9 | use super::*; |
| 11 | use crate::eth::{MDCPin, MDIOPin}; | ||
| 12 | use crate::gpio::{AfType, AnyPin, OutputType, SealedPin as _, Speed}; | 10 | use crate::gpio::{AfType, AnyPin, OutputType, SealedPin as _, Speed}; |
| 13 | use crate::interrupt; | 11 | use crate::interrupt; |
| 14 | use crate::interrupt::InterruptExt; | 12 | use crate::interrupt::InterruptExt; |
| @@ -42,7 +40,6 @@ pub struct Ethernet<'d, T: Instance, P: Phy> { | |||
| 42 | pub(crate) rx: RDesRing<'d>, | 40 | pub(crate) rx: RDesRing<'d>, |
| 43 | pins: Pins<'d>, | 41 | pins: Pins<'d>, |
| 44 | pub(crate) phy: P, | 42 | pub(crate) phy: P, |
| 45 | pub(crate) station_management: Sma<'d, T>, | ||
| 46 | pub(crate) mac_addr: [u8; 6], | 43 | pub(crate) mac_addr: [u8; 6], |
| 47 | } | 44 | } |
| 48 | 45 | ||
| @@ -64,14 +61,12 @@ macro_rules! config_pins { | |||
| 64 | } | 61 | } |
| 65 | 62 | ||
| 66 | impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> { | 63 | impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> { |
| 67 | /// Create a new RMII ethernet driver using 9 pins. | 64 | /// Create a new RMII ethernet driver using 7 pins. |
| 68 | pub fn new<const TX: usize, const RX: usize>( | 65 | pub fn new<const TX: usize, const RX: usize>( |
| 69 | queue: &'d mut PacketQueue<TX, RX>, | 66 | queue: &'d mut PacketQueue<TX, RX>, |
| 70 | peri: Peri<'d, T>, | 67 | peri: Peri<'d, T>, |
| 71 | irq: impl interrupt::typelevel::Binding<interrupt::typelevel::ETH, InterruptHandler> + 'd, | 68 | irq: impl interrupt::typelevel::Binding<interrupt::typelevel::ETH, InterruptHandler> + 'd, |
| 72 | ref_clk: Peri<'d, impl RefClkPin<T>>, | 69 | ref_clk: Peri<'d, impl RefClkPin<T>>, |
| 73 | mdio: Peri<'d, impl MDIOPin<T>>, | ||
| 74 | mdc: Peri<'d, impl MDCPin<T>>, | ||
| 75 | crs: Peri<'d, impl CRSPin<T>>, | 70 | crs: Peri<'d, impl CRSPin<T>>, |
| 76 | rx_d0: Peri<'d, impl RXD0Pin<T>>, | 71 | rx_d0: Peri<'d, impl RXD0Pin<T>>, |
| 77 | rx_d1: Peri<'d, impl RXD1Pin<T>>, | 72 | rx_d1: Peri<'d, impl RXD1Pin<T>>, |
| @@ -104,18 +99,16 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> { | |||
| 104 | tx_en.into(), | 99 | tx_en.into(), |
| 105 | ]); | 100 | ]); |
| 106 | 101 | ||
| 107 | Self::new_inner(queue, peri, irq, pins, mdio, mdc, phy, mac_addr) | 102 | Self::new_inner(queue, peri, irq, pins, phy, mac_addr) |
| 108 | } | 103 | } |
| 109 | 104 | ||
| 110 | /// Create a new MII ethernet driver using 14 pins. | 105 | /// Create a new MII ethernet driver using 12 pins. |
| 111 | pub fn new_mii<const TX: usize, const RX: usize>( | 106 | pub fn new_mii<const TX: usize, const RX: usize>( |
| 112 | queue: &'d mut PacketQueue<TX, RX>, | 107 | queue: &'d mut PacketQueue<TX, RX>, |
| 113 | peri: Peri<'d, T>, | 108 | peri: Peri<'d, T>, |
| 114 | irq: impl interrupt::typelevel::Binding<interrupt::typelevel::ETH, InterruptHandler> + 'd, | 109 | irq: impl interrupt::typelevel::Binding<interrupt::typelevel::ETH, InterruptHandler> + 'd, |
| 115 | rx_clk: Peri<'d, impl RXClkPin<T>>, | 110 | rx_clk: Peri<'d, impl RXClkPin<T>>, |
| 116 | tx_clk: Peri<'d, impl TXClkPin<T>>, | 111 | tx_clk: Peri<'d, impl TXClkPin<T>>, |
| 117 | mdio: Peri<'d, impl MDIOPin<T>>, | ||
| 118 | mdc: Peri<'d, impl MDCPin<T>>, | ||
| 119 | rxdv: Peri<'d, impl RXDVPin<T>>, | 112 | rxdv: Peri<'d, impl RXDVPin<T>>, |
| 120 | rx_d0: Peri<'d, impl RXD0Pin<T>>, | 113 | rx_d0: Peri<'d, impl RXD0Pin<T>>, |
| 121 | rx_d1: Peri<'d, impl RXD1Pin<T>>, | 114 | rx_d1: Peri<'d, impl RXD1Pin<T>>, |
| @@ -161,7 +154,7 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> { | |||
| 161 | tx_en.into(), | 154 | tx_en.into(), |
| 162 | ]); | 155 | ]); |
| 163 | 156 | ||
| 164 | Self::new_inner(queue, peri, irq, pins, mdio, mdc, phy, mac_addr) | 157 | Self::new_inner(queue, peri, irq, pins, phy, mac_addr) |
| 165 | } | 158 | } |
| 166 | 159 | ||
| 167 | fn new_inner<const TX: usize, const RX: usize>( | 160 | fn new_inner<const TX: usize, const RX: usize>( |
| @@ -169,8 +162,6 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> { | |||
| 169 | peri: Peri<'d, T>, | 162 | peri: Peri<'d, T>, |
| 170 | _irq: impl interrupt::typelevel::Binding<interrupt::typelevel::ETH, InterruptHandler> + 'd, | 163 | _irq: impl interrupt::typelevel::Binding<interrupt::typelevel::ETH, InterruptHandler> + 'd, |
| 171 | pins: Pins<'d>, | 164 | pins: Pins<'d>, |
| 172 | mdio: Peri<'d, impl MDIOPin<T>>, | ||
| 173 | mdc: Peri<'d, impl MDCPin<T>>, | ||
| 174 | phy: P, | 165 | phy: P, |
| 175 | mac_addr: [u8; 6], | 166 | mac_addr: [u8; 6], |
| 176 | ) -> Self { | 167 | ) -> Self { |
| @@ -235,15 +226,12 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> { | |||
| 235 | w.set_rbsz(RX_BUFFER_SIZE as u16); | 226 | w.set_rbsz(RX_BUFFER_SIZE as u16); |
| 236 | }); | 227 | }); |
| 237 | 228 | ||
| 238 | let sma_peri = unsafe { peri.clone_unchecked() }; | ||
| 239 | |||
| 240 | let mut this = Self { | 229 | let mut this = Self { |
| 241 | _peri: peri, | 230 | _peri: peri, |
| 242 | tx: TDesRing::new(&mut queue.tx_desc, &mut queue.tx_buf), | 231 | tx: TDesRing::new(&mut queue.tx_desc, &mut queue.tx_buf), |
| 243 | rx: RDesRing::new(&mut queue.rx_desc, &mut queue.rx_buf), | 232 | rx: RDesRing::new(&mut queue.rx_desc, &mut queue.rx_buf), |
| 244 | pins, | 233 | pins, |
| 245 | phy, | 234 | phy, |
| 246 | station_management: Sma::new(sma_peri, mdio, mdc), | ||
| 247 | mac_addr, | 235 | mac_addr, |
| 248 | }; | 236 | }; |
| 249 | 237 | ||
| @@ -269,8 +257,8 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> { | |||
| 269 | w.set_tie(true); | 257 | w.set_tie(true); |
| 270 | }); | 258 | }); |
| 271 | 259 | ||
| 272 | this.phy.phy_reset(&mut this.station_management); | 260 | this.phy.phy_reset(); |
| 273 | this.phy.phy_init(&mut this.station_management); | 261 | this.phy.phy_init(); |
| 274 | 262 | ||
| 275 | interrupt::ETH.unpend(); | 263 | interrupt::ETH.unpend(); |
| 276 | unsafe { interrupt::ETH.enable() }; | 264 | unsafe { interrupt::ETH.enable() }; |
diff --git a/tests/stm32/src/bin/eth.rs b/tests/stm32/src/bin/eth.rs index a65682a02..95789ffc5 100644 --- a/tests/stm32/src/bin/eth.rs +++ b/tests/stm32/src/bin/eth.rs | |||
| @@ -7,8 +7,8 @@ mod common; | |||
| 7 | use common::*; | 7 | use common::*; |
| 8 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 9 | use embassy_net::StackResources; | 9 | use embassy_net::StackResources; |
| 10 | use embassy_stm32::eth::{Ethernet, GenericPhy, PacketQueue}; | 10 | use embassy_stm32::eth::{Ethernet, GenericPhy, PacketQueue, Sma}; |
| 11 | use embassy_stm32::peripherals::ETH; | 11 | use embassy_stm32::peripherals::{ETH, ETH_SMA}; |
| 12 | use embassy_stm32::rng::Rng; | 12 | use embassy_stm32::rng::Rng; |
| 13 | use embassy_stm32::{bind_interrupts, eth, peripherals, rng}; | 13 | use embassy_stm32::{bind_interrupts, eth, peripherals, rng}; |
| 14 | use static_cell::StaticCell; | 14 | use static_cell::StaticCell; |
| @@ -27,7 +27,7 @@ bind_interrupts!(struct Irqs { | |||
| 27 | RNG => rng::InterruptHandler<peripherals::RNG>; | 27 | RNG => rng::InterruptHandler<peripherals::RNG>; |
| 28 | }); | 28 | }); |
| 29 | 29 | ||
| 30 | type Device = Ethernet<'static, ETH, GenericPhy>; | 30 | type Device = Ethernet<'static, ETH, GenericPhy<Sma<'static, ETH_SMA>>>; |
| 31 | 31 | ||
| 32 | #[embassy_executor::task] | 32 | #[embassy_executor::task] |
| 33 | async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! { | 33 | async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! { |
| @@ -69,13 +69,15 @@ async fn main(spawner: Spawner) { | |||
| 69 | const PACKET_QUEUE_SIZE: usize = 4; | 69 | const PACKET_QUEUE_SIZE: usize = 4; |
| 70 | 70 | ||
| 71 | static PACKETS: StaticCell<PacketQueue<PACKET_QUEUE_SIZE, PACKET_QUEUE_SIZE>> = StaticCell::new(); | 71 | static PACKETS: StaticCell<PacketQueue<PACKET_QUEUE_SIZE, PACKET_QUEUE_SIZE>> = StaticCell::new(); |
| 72 | |||
| 73 | let sma = Sma::new(p.ETH_SMA, p.PA2, p.PC1); | ||
| 74 | let phy = GenericPhy::new_auto(sma); | ||
| 75 | |||
| 72 | let device = Ethernet::new( | 76 | let device = Ethernet::new( |
| 73 | PACKETS.init(PacketQueue::<PACKET_QUEUE_SIZE, PACKET_QUEUE_SIZE>::new()), | 77 | PACKETS.init(PacketQueue::<PACKET_QUEUE_SIZE, PACKET_QUEUE_SIZE>::new()), |
| 74 | p.ETH, | 78 | p.ETH, |
| 75 | Irqs, | 79 | Irqs, |
| 76 | p.PA1, | 80 | p.PA1, |
| 77 | p.PA2, | ||
| 78 | p.PC1, | ||
| 79 | p.PA7, | 81 | p.PA7, |
| 80 | p.PC4, | 82 | p.PC4, |
| 81 | p.PC5, | 83 | p.PC5, |
| @@ -85,7 +87,7 @@ async fn main(spawner: Spawner) { | |||
| 85 | #[cfg(feature = "stm32h563zi")] | 87 | #[cfg(feature = "stm32h563zi")] |
| 86 | p.PB15, | 88 | p.PB15, |
| 87 | p.PG11, | 89 | p.PG11, |
| 88 | GenericPhy::new_auto(), | 90 | phy, |
| 89 | mac_addr, | 91 | mac_addr, |
| 90 | ); | 92 | ); |
| 91 | 93 | ||
