From 44881e643702b9ca41fc72109c3d16afd4b0449b Mon Sep 17 00:00:00 2001 From: datdenkikniet Date: Wed, 12 Nov 2025 22:02:09 +0100 Subject: ETH no longer knows about Station management --- embassy-stm32/src/eth/generic_phy.rs | 45 +++++++++++++++++++----------------- embassy-stm32/src/eth/mod.rs | 15 ++++-------- embassy-stm32/src/eth/sma/mod.rs | 13 ----------- embassy-stm32/src/eth/v1/mod.rs | 24 +++++-------------- embassy-stm32/src/eth/v2/mod.rs | 24 +++++-------------- 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 { use self::phy_consts::*; /// Generic SMI Ethernet PHY implementation -pub struct GenericPhy { +pub struct GenericPhy { phy_addr: u8, + sm: SM, #[cfg(feature = "time")] poll_interval: Duration, } -impl GenericPhy { +impl GenericPhy { /// Construct the PHY. It assumes the address `phy_addr` in the SMI communication /// /// # Panics /// `phy_addr` must be in range `0..32` - pub fn new(phy_addr: u8) -> Self { + pub fn new(sm: SM, phy_addr: u8) -> Self { assert!(phy_addr < 32); Self { phy_addr, + sm, #[cfg(feature = "time")] poll_interval: Duration::from_millis(500), } @@ -68,8 +70,9 @@ impl GenericPhy { /// /// # Panics /// Initialization panics if PHY didn't respond on any address - pub fn new_auto() -> Self { + pub fn new_auto(sm: SM) -> Self { Self { + sm, phy_addr: 0xFF, #[cfg(feature = "time")] poll_interval: Duration::from_millis(500), @@ -77,14 +80,14 @@ impl GenericPhy { } } -impl Phy for GenericPhy { - fn phy_reset(&mut self, sm: &mut S) { +impl Phy for GenericPhy { + fn phy_reset(&mut self) { // Detect SMI address if self.phy_addr == 0xFF { for addr in 0..32 { - sm.smi_write(addr, PHY_REG_BCR, PHY_REG_BCR_RESET); + self.sm.smi_write(addr, PHY_REG_BCR, PHY_REG_BCR_RESET); for _ in 0..10 { - if sm.smi_read(addr, PHY_REG_BCR) & PHY_REG_BCR_RESET != PHY_REG_BCR_RESET { + if self.sm.smi_read(addr, PHY_REG_BCR) & PHY_REG_BCR_RESET != PHY_REG_BCR_RESET { trace!("Found ETH PHY on address {}", addr); self.phy_addr = addr; return; @@ -96,30 +99,30 @@ impl Phy for GenericPhy { panic!("PHY did not respond"); } - sm.smi_write(self.phy_addr, PHY_REG_BCR, PHY_REG_BCR_RESET); - while sm.smi_read(self.phy_addr, PHY_REG_BCR) & PHY_REG_BCR_RESET == PHY_REG_BCR_RESET {} + self.sm.smi_write(self.phy_addr, PHY_REG_BCR, PHY_REG_BCR_RESET); + while self.sm.smi_read(self.phy_addr, PHY_REG_BCR) & PHY_REG_BCR_RESET == PHY_REG_BCR_RESET {} } - fn phy_init(&mut self, sm: &mut S) { + fn phy_init(&mut self) { // Clear WU CSR - self.smi_write_ext(sm, PHY_REG_WUCSR, 0); + self.smi_write_ext(PHY_REG_WUCSR, 0); // Enable auto-negotiation - sm.smi_write( + self.sm.smi_write( self.phy_addr, PHY_REG_BCR, PHY_REG_BCR_AN | PHY_REG_BCR_ANRST | PHY_REG_BCR_100M, ); } - fn poll_link(&mut self, sm: &mut S, cx: &mut Context) -> bool { + fn poll_link(&mut self, cx: &mut Context) -> bool { #[cfg(not(feature = "time"))] cx.waker().wake_by_ref(); #[cfg(feature = "time")] let _ = Timer::after(self.poll_interval).poll_unpin(cx); - let bsr = sm.smi_read(self.phy_addr, PHY_REG_BSR); + let bsr = self.sm.smi_read(self.phy_addr, PHY_REG_BSR); // No link without autonegotiate if bsr & PHY_REG_BSR_ANDONE == 0 { @@ -136,7 +139,7 @@ impl Phy for GenericPhy { } /// Public functions for the PHY -impl GenericPhy { +impl GenericPhy { /// Set the SMI polling interval. #[cfg(feature = "time")] pub fn set_poll_interval(&mut self, poll_interval: Duration) { @@ -144,10 +147,10 @@ impl GenericPhy { } // Writes a value to an extended PHY register in MMD address space - fn smi_write_ext(&mut self, sm: &mut S, reg_addr: u16, reg_data: u16) { - sm.smi_write(self.phy_addr, PHY_REG_CTL, 0x0003); // set address - sm.smi_write(self.phy_addr, PHY_REG_ADDAR, reg_addr); - sm.smi_write(self.phy_addr, PHY_REG_CTL, 0x4003); // set data - sm.smi_write(self.phy_addr, PHY_REG_ADDAR, reg_data); + fn smi_write_ext(&mut self, reg_addr: u16, reg_data: u16) { + self.sm.smi_write(self.phy_addr, PHY_REG_CTL, 0x0003); // set address + self.sm.smi_write(self.phy_addr, PHY_REG_ADDAR, reg_addr); + self.sm.smi_write(self.phy_addr, PHY_REG_CTL, 0x4003); // set data + self.sm.smi_write(self.phy_addr, PHY_REG_ADDAR, reg_data); } } 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> } fn link_state(&mut self, cx: &mut Context) -> LinkState { - if self.phy.poll_link(&mut self.station_management, cx) { + if self.phy.poll_link(cx) { LinkState::Up } else { LinkState::Down @@ -162,21 +162,14 @@ impl<'a, 'd> embassy_net_driver::TxToken for TxToken<'a, 'd> { /// Trait for an Ethernet PHY pub trait Phy { /// Reset PHY and wait for it to come out of reset. - fn phy_reset(&mut self, sm: &mut S); + fn phy_reset(&mut self); /// PHY initialisation. - fn phy_init(&mut self, sm: &mut S); + fn phy_init(&mut self); /// Poll link to see if it is up and FD with 100Mbps - fn poll_link(&mut self, sm: &mut S, cx: &mut Context) -> bool; + fn poll_link(&mut self, cx: &mut Context) -> bool; } impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> { - /// Directly expose the SMI interface used by the Ethernet driver. - /// - /// This can be used to for example configure special PHY registers for compliance testing. - pub fn station_management(&mut self) -> &mut impl StationManagement { - &mut self.station_management - } - /// Access the user-supplied `Phy`. pub fn phy(&self) -> &P { &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 { } } -impl SealedInstance for T { - fn regs() -> (Reg, Reg) { - let mac = ::regs().ethernet_mac(); - - #[cfg(any(eth_v1a, eth_v1b, eth_v1c))] - return (mac.macmiiar(), mac.macmiidr()); - - #[cfg(eth_v2)] - return (mac.macmdioar(), mac.macmdiodr()); - } -} - impl Instance for crate::peripherals::ETH_SMA {} -impl 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, pub(crate) use self::rx_desc::{RDes, RDesRing}; pub(crate) use self::tx_desc::{TDes, TDesRing}; -use super::sma::Sma; use super::*; -use crate::eth::{MDCPin, MDIOPin}; #[cfg(eth_v1a)] use crate::gpio::Pull; use crate::gpio::{AfType, AnyPin, OutputType, SealedPin, Speed}; @@ -53,7 +51,6 @@ pub struct Ethernet<'d, T: Instance, P: Phy> { pins: Pins<'d>, pub(crate) phy: P, - pub(crate) station_management: Sma<'d, T>, pub(crate) mac_addr: [u8; 6], } @@ -104,8 +101,6 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> { peri: Peri<'d, T>, irq: impl interrupt::typelevel::Binding + 'd, ref_clk: Peri<'d, if_afio!(impl RefClkPin)>, - mdio: Peri<'d, if_afio!(impl MDIOPin)>, - mdc: Peri<'d, if_afio!(impl MDCPin)>, crs: Peri<'d, if_afio!(impl CRSPin)>, rx_d0: Peri<'d, if_afio!(impl RXD0Pin)>, rx_d1: Peri<'d, if_afio!(impl RXD1Pin)>, @@ -165,16 +160,14 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> { tx_en.into(), ]); - Self::new_inner(queue, peri, irq, pins, mdio, mdc, phy, mac_addr) + Self::new_inner(queue, peri, irq, pins, phy, mac_addr) } - fn new_inner( + fn new_inner( queue: &'d mut PacketQueue, peri: Peri<'d, T>, _irq: impl interrupt::typelevel::Binding + 'd, pins: Pins<'d>, - mdio: Peri<'d, if_afio!(impl MDIOPin)>, - mdc: Peri<'d, if_afio!(impl MDCPin)>, phy: P, mac_addr: [u8; 6], ) -> Self { @@ -226,13 +219,10 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> { // TODO MTU size setting not found for v1 ethernet, check if correct - let sma_peri = unsafe { peri.clone_unchecked() }; - let mut this = Self { _peri: peri, pins, phy: phy, - station_management: Sma::new(sma_peri, mdio, mdc), mac_addr, tx: TDesRing::new(&mut queue.tx_desc, &mut queue.tx_buf), 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> { w.set_tie(true); }); - this.phy.phy_reset(&mut this.station_management); - this.phy.phy_init(&mut this.station_management); + this.phy.phy_reset(); + this.phy.phy_init(); interrupt::ETH.unpend(); unsafe { interrupt::ETH.enable() }; @@ -271,15 +261,13 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> { this } - /// Create a new MII ethernet driver using 14 pins. + /// Create a new MII ethernet driver using 12 pins. pub fn new_mii( queue: &'d mut PacketQueue, peri: Peri<'d, T>, irq: impl interrupt::typelevel::Binding + 'd, rx_clk: Peri<'d, if_afio!(impl RXClkPin)>, tx_clk: Peri<'d, if_afio!(impl TXClkPin)>, - mdio: Peri<'d, if_afio!(impl MDIOPin)>, - mdc: Peri<'d, if_afio!(impl MDCPin)>, rxdv: Peri<'d, if_afio!(impl RXDVPin)>, rx_d0: Peri<'d, if_afio!(impl RXD0Pin)>, rx_d1: Peri<'d, if_afio!(impl RXD1Pin)>, @@ -352,7 +340,7 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> { tx_en.into(), ]); - Self::new_inner(queue, peri, irq, pins, mdio, mdc, phy, mac_addr) + Self::new_inner(queue, peri, irq, pins, phy, mac_addr) } } 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; use stm32_metapac::syscfg::vals::EthSelPhy; pub(crate) use self::descriptors::{RDes, RDesRing, TDes, TDesRing}; -use super::sma::Sma; use super::*; -use crate::eth::{MDCPin, MDIOPin}; use crate::gpio::{AfType, AnyPin, OutputType, SealedPin as _, Speed}; use crate::interrupt; use crate::interrupt::InterruptExt; @@ -42,7 +40,6 @@ pub struct Ethernet<'d, T: Instance, P: Phy> { pub(crate) rx: RDesRing<'d>, pins: Pins<'d>, pub(crate) phy: P, - pub(crate) station_management: Sma<'d, T>, pub(crate) mac_addr: [u8; 6], } @@ -64,14 +61,12 @@ macro_rules! config_pins { } impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> { - /// Create a new RMII ethernet driver using 9 pins. + /// Create a new RMII ethernet driver using 7 pins. pub fn new( queue: &'d mut PacketQueue, peri: Peri<'d, T>, irq: impl interrupt::typelevel::Binding + 'd, ref_clk: Peri<'d, impl RefClkPin>, - mdio: Peri<'d, impl MDIOPin>, - mdc: Peri<'d, impl MDCPin>, crs: Peri<'d, impl CRSPin>, rx_d0: Peri<'d, impl RXD0Pin>, rx_d1: Peri<'d, impl RXD1Pin>, @@ -104,18 +99,16 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> { tx_en.into(), ]); - Self::new_inner(queue, peri, irq, pins, mdio, mdc, phy, mac_addr) + Self::new_inner(queue, peri, irq, pins, phy, mac_addr) } - /// Create a new MII ethernet driver using 14 pins. + /// Create a new MII ethernet driver using 12 pins. pub fn new_mii( queue: &'d mut PacketQueue, peri: Peri<'d, T>, irq: impl interrupt::typelevel::Binding + 'd, rx_clk: Peri<'d, impl RXClkPin>, tx_clk: Peri<'d, impl TXClkPin>, - mdio: Peri<'d, impl MDIOPin>, - mdc: Peri<'d, impl MDCPin>, rxdv: Peri<'d, impl RXDVPin>, rx_d0: Peri<'d, impl RXD0Pin>, rx_d1: Peri<'d, impl RXD1Pin>, @@ -161,7 +154,7 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> { tx_en.into(), ]); - Self::new_inner(queue, peri, irq, pins, mdio, mdc, phy, mac_addr) + Self::new_inner(queue, peri, irq, pins, phy, mac_addr) } fn new_inner( @@ -169,8 +162,6 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> { peri: Peri<'d, T>, _irq: impl interrupt::typelevel::Binding + 'd, pins: Pins<'d>, - mdio: Peri<'d, impl MDIOPin>, - mdc: Peri<'d, impl MDCPin>, phy: P, mac_addr: [u8; 6], ) -> Self { @@ -235,15 +226,12 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> { w.set_rbsz(RX_BUFFER_SIZE as u16); }); - let sma_peri = unsafe { peri.clone_unchecked() }; - let mut this = Self { _peri: peri, tx: TDesRing::new(&mut queue.tx_desc, &mut queue.tx_buf), rx: RDesRing::new(&mut queue.rx_desc, &mut queue.rx_buf), pins, phy, - station_management: Sma::new(sma_peri, mdio, mdc), mac_addr, }; @@ -269,8 +257,8 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> { w.set_tie(true); }); - this.phy.phy_reset(&mut this.station_management); - this.phy.phy_init(&mut this.station_management); + this.phy.phy_reset(); + this.phy.phy_init(); interrupt::ETH.unpend(); 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; use common::*; use embassy_executor::Spawner; use embassy_net::StackResources; -use embassy_stm32::eth::{Ethernet, GenericPhy, PacketQueue}; -use embassy_stm32::peripherals::ETH; +use embassy_stm32::eth::{Ethernet, GenericPhy, PacketQueue, Sma}; +use embassy_stm32::peripherals::{ETH, ETH_SMA}; use embassy_stm32::rng::Rng; use embassy_stm32::{bind_interrupts, eth, peripherals, rng}; use static_cell::StaticCell; @@ -27,7 +27,7 @@ bind_interrupts!(struct Irqs { RNG => rng::InterruptHandler; }); -type Device = Ethernet<'static, ETH, GenericPhy>; +type Device = Ethernet<'static, ETH, GenericPhy>>; #[embassy_executor::task] async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! { @@ -69,13 +69,15 @@ async fn main(spawner: Spawner) { const PACKET_QUEUE_SIZE: usize = 4; static PACKETS: StaticCell> = StaticCell::new(); + + let sma = Sma::new(p.ETH_SMA, p.PA2, p.PC1); + let phy = GenericPhy::new_auto(sma); + let device = Ethernet::new( PACKETS.init(PacketQueue::::new()), p.ETH, Irqs, p.PA1, - p.PA2, - p.PC1, p.PA7, p.PC4, p.PC5, @@ -85,7 +87,7 @@ async fn main(spawner: Spawner) { #[cfg(feature = "stm32h563zi")] p.PB15, p.PG11, - GenericPhy::new_auto(), + phy, mac_addr, ); -- cgit