diff --git a/embassy-stm32/src/eth/generic_smi.rs b/embassy-stm32/src/eth/generic_smi.rs index 968256046..1d83cec35 100644 --- a/embassy-stm32/src/eth/generic_smi.rs +++ b/embassy-stm32/src/eth/generic_smi.rs @@ -1,5 +1,7 @@ //! Generic SMI Ethernet PHY +use futures::task::Context; + use super::{StationManagement, PHY}; #[allow(dead_code)] @@ -40,13 +42,13 @@ pub struct GenericSMI; unsafe impl PHY for GenericSMI { /// Reset PHY and wait for it to come out of reset. - fn phy_reset(sm: &mut S) { + fn phy_reset(&mut self, sm: &mut S) { sm.smi_write(PHY_REG_BCR, PHY_REG_BCR_RESET); while sm.smi_read(PHY_REG_BCR) & PHY_REG_BCR_RESET == PHY_REG_BCR_RESET {} } /// PHY initialisation. - fn phy_init(sm: &mut S) { + fn phy_init(&mut self, sm: &mut S) { // Clear WU CSR Self::smi_write_ext(sm, PHY_REG_WUCSR, 0); @@ -54,7 +56,9 @@ unsafe impl PHY for GenericSMI { sm.smi_write(PHY_REG_BCR, PHY_REG_BCR_AN | PHY_REG_BCR_ANRST | PHY_REG_BCR_100M); } - fn poll_link(sm: &mut S) -> bool { + fn poll_link(&mut self, sm: &mut S, cx: &mut Context) -> bool { + cx.waker().wake_by_ref(); + let bsr = sm.smi_read(PHY_REG_BSR); // No link without autonegotiate diff --git a/embassy-stm32/src/eth/mod.rs b/embassy-stm32/src/eth/mod.rs index 4989e17c7..1687cb319 100644 --- a/embassy-stm32/src/eth/mod.rs +++ b/embassy-stm32/src/eth/mod.rs @@ -81,9 +81,7 @@ impl<'d, T: Instance, P: PHY> embassy_net_driver::Driver for Ethernet<'d, T, P> } fn link_state(&mut self, cx: &mut Context) -> LinkState { - // TODO: wake cx.waker on link state change - cx.waker().wake_by_ref(); - if P::poll_link(self) { + if self.phy.poll_link(&mut self.station_management, cx) { LinkState::Up } else { LinkState::Down @@ -148,11 +146,11 @@ pub unsafe trait StationManagement { /// The methods cannot move S pub unsafe trait PHY { /// Reset PHY and wait for it to come out of reset. - fn phy_reset(sm: &mut S); + fn phy_reset(&mut self, sm: &mut S); /// PHY initialisation. - fn phy_init(sm: &mut S); + fn phy_init(&mut self, sm: &mut S); /// Poll link to see if it is up and FD with 100Mbps - fn poll_link(sm: &mut S) -> bool; + fn poll_link(&mut self, sm: &mut S, cx: &mut Context) -> bool; } pub(crate) mod sealed { diff --git a/embassy-stm32/src/eth/v1/mod.rs b/embassy-stm32/src/eth/v1/mod.rs index b53c2d0fa..2a6ea35ff 100644 --- a/embassy-stm32/src/eth/v1/mod.rs +++ b/embassy-stm32/src/eth/v1/mod.rs @@ -3,6 +3,7 @@ mod rx_desc; mod tx_desc; +use core::marker::PhantomData; use core::sync::atomic::{fence, Ordering}; use embassy_hal_common::{into_ref, PeripheralRef}; @@ -48,9 +49,8 @@ pub struct Ethernet<'d, T: Instance, P: PHY> { pub(crate) rx: RDesRing<'d>, pins: [PeripheralRef<'d, AnyPin>; 9], - _phy: P, - clock_range: Cr, - phy_addr: u8, + pub(crate) phy: P, + pub(crate) station_management: EthernetStationManagement, pub(crate) mac_addr: [u8; 6], } @@ -224,9 +224,12 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { let mut this = Self { _peri: peri, pins, - _phy: phy, - clock_range, - phy_addr, + phy: phy, + station_management: EthernetStationManagement { + peri: PhantomData, + clock_range: clock_range, + phy_addr: phy_addr, + }, mac_addr, tx: TDesRing::new(&mut queue.tx_desc, &mut queue.tx_buf), rx: RDesRing::new(&mut queue.rx_desc, &mut queue.rx_buf), @@ -256,8 +259,8 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { w.set_tie(true); }); - P::phy_reset(&mut this); - P::phy_init(&mut this); + this.phy.phy_reset(&mut this.station_management); + this.phy.phy_init(&mut this.station_management); interrupt::ETH.unpend(); unsafe { interrupt::ETH.enable() }; @@ -266,7 +269,13 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { } } -unsafe impl<'d, T: Instance, P: PHY> StationManagement for Ethernet<'d, T, P> { +pub struct EthernetStationManagement { + peri: PhantomData, + clock_range: Cr, + phy_addr: u8, +} + +unsafe impl StationManagement for EthernetStationManagement { fn smi_read(&mut self, reg: u8) -> u16 { let mac = ETH.ethernet_mac(); diff --git a/embassy-stm32/src/eth/v2/mod.rs b/embassy-stm32/src/eth/v2/mod.rs index 600e1d3bc..bb681c42b 100644 --- a/embassy-stm32/src/eth/v2/mod.rs +++ b/embassy-stm32/src/eth/v2/mod.rs @@ -1,5 +1,6 @@ mod descriptors; +use core::marker::PhantomData; use core::sync::atomic::{fence, Ordering}; use embassy_hal_common::{into_ref, PeripheralRef}; @@ -40,9 +41,8 @@ pub struct Ethernet<'d, T: Instance, P: PHY> { pub(crate) tx: TDesRing<'d>, pub(crate) rx: RDesRing<'d>, pins: [PeripheralRef<'d, AnyPin>; 9], - _phy: P, - clock_range: u8, - phy_addr: u8, + pub(crate) phy: P, + pub(crate) station_management: EthernetStationManagement, pub(crate) mac_addr: [u8; 6], } @@ -201,9 +201,12 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { tx: TDesRing::new(&mut queue.tx_desc, &mut queue.tx_buf), rx: RDesRing::new(&mut queue.rx_desc, &mut queue.rx_buf), pins, - _phy: phy, - clock_range, - phy_addr, + phy: phy, + station_management: EthernetStationManagement { + peri: PhantomData, + clock_range: clock_range, + phy_addr: phy_addr, + }, mac_addr, }; @@ -229,8 +232,8 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { w.set_tie(true); }); - P::phy_reset(&mut this); - P::phy_init(&mut this); + this.phy.phy_reset(&mut this.station_management); + this.phy.phy_init(&mut this.station_management); interrupt::ETH.unpend(); unsafe { interrupt::ETH.enable() }; @@ -239,7 +242,13 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { } } -unsafe impl<'d, T: Instance, P: PHY> StationManagement for Ethernet<'d, T, P> { +pub struct EthernetStationManagement { + peri: PhantomData, + clock_range: u8, + phy_addr: u8, +} + +unsafe impl StationManagement for EthernetStationManagement { fn smi_read(&mut self, reg: u8) -> u16 { let mac = ETH.ethernet_mac();