From 48b37aa2bf83b8fccb293fcda7f51149a4ec1a24 Mon Sep 17 00:00:00 2001 From: xoviat Date: Sat, 15 Jul 2023 09:32:36 -0500 Subject: [PATCH 1/5] stm32/eth: refactor genericsmi --- embassy-stm32/src/eth/generic_smi.rs | 10 +++++++--- embassy-stm32/src/eth/mod.rs | 10 ++++------ embassy-stm32/src/eth/v1/mod.rs | 27 ++++++++++++++++++--------- embassy-stm32/src/eth/v2/mod.rs | 27 ++++++++++++++++++--------- 4 files changed, 47 insertions(+), 27 deletions(-) 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(); From bb24cfd1e8d359332acbc3c659cb9041d993483f Mon Sep 17 00:00:00 2001 From: xoviat Date: Sat, 15 Jul 2023 09:32:44 -0500 Subject: [PATCH 2/5] stm32/eth: add f4 example --- examples/stm32f4/src/bin/eth.rs | 111 ++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 examples/stm32f4/src/bin/eth.rs diff --git a/examples/stm32f4/src/bin/eth.rs b/examples/stm32f4/src/bin/eth.rs new file mode 100644 index 000000000..c32d886d0 --- /dev/null +++ b/examples/stm32f4/src/bin/eth.rs @@ -0,0 +1,111 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_net::tcp::TcpSocket; +use embassy_net::{Ipv4Address, Stack, StackResources}; +use embassy_stm32::eth::generic_smi::GenericSMI; +use embassy_stm32::eth::{Ethernet, PacketQueue}; +use embassy_stm32::peripherals::ETH; +use embassy_stm32::rng::Rng; +use embassy_stm32::time::mhz; +use embassy_stm32::{bind_interrupts, eth, Config}; +use embassy_time::{Duration, Timer}; +use embedded_io::asynch::Write; +use static_cell::make_static; +use {defmt_rtt as _, panic_probe as _}; +bind_interrupts!(struct Irqs { + ETH => eth::InterruptHandler; +}); + +type Device = Ethernet<'static, ETH, GenericSMI>; + +#[embassy_executor::task] +async fn net_task(stack: &'static Stack) -> ! { + stack.run().await +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) -> ! { + let mut config = Config::default(); + config.rcc.sys_ck = Some(mhz(200)); + let p = embassy_stm32::init(config); + + info!("Hello World!"); + + // Generate random seed. + let mut rng = Rng::new(p.RNG); + let mut seed = [0; 8]; + let _ = rng.async_fill_bytes(&mut seed).await; + let seed = u64::from_le_bytes(seed); + + let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF]; + + let device = Ethernet::new( + make_static!(PacketQueue::<16, 16>::new()), + p.ETH, + Irqs, + p.PA1, + p.PA2, + p.PC1, + p.PA7, + p.PC4, + p.PC5, + p.PG13, + p.PB13, + p.PG11, + GenericSMI, + mac_addr, + 0, + ); + + let config = embassy_net::Config::dhcpv4(Default::default()); + //let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { + // address: Ipv4Cidr::new(Ipv4Address::new(10, 42, 0, 61), 24), + // dns_servers: Vec::new(), + // gateway: Some(Ipv4Address::new(10, 42, 0, 1)), + //}); + + // Init network stack + let stack = &*make_static!(Stack::new( + device, + config, + make_static!(StackResources::<2>::new()), + seed + )); + + // Launch network task + unwrap!(spawner.spawn(net_task(&stack))); + + info!("Network task initialized"); + + // Then we can use it! + let mut rx_buffer = [0; 4096]; + let mut tx_buffer = [0; 4096]; + + loop { + let mut socket = TcpSocket::new(&stack, &mut rx_buffer, &mut tx_buffer); + + socket.set_timeout(Some(embassy_time::Duration::from_secs(10))); + + let remote_endpoint = (Ipv4Address::new(10, 42, 0, 1), 8000); + info!("connecting..."); + let r = socket.connect(remote_endpoint).await; + if let Err(e) = r { + info!("connect error: {:?}", e); + continue; + } + info!("connected!"); + let buf = [0; 1024]; + loop { + let r = socket.write_all(&buf).await; + if let Err(e) = r { + info!("write error: {:?}", e); + continue; + } + Timer::after(Duration::from_secs(1)).await; + } + } +} From c3774607a55141ce55d8ba462a2ebe18f80056de Mon Sep 17 00:00:00 2001 From: xoviat Date: Sat, 15 Jul 2023 09:37:25 -0500 Subject: [PATCH 3/5] stm32/eth: convert static metho --- embassy-stm32/src/eth/generic_smi.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/src/eth/generic_smi.rs b/embassy-stm32/src/eth/generic_smi.rs index 1d83cec35..5c7856437 100644 --- a/embassy-stm32/src/eth/generic_smi.rs +++ b/embassy-stm32/src/eth/generic_smi.rs @@ -50,7 +50,7 @@ unsafe impl PHY for GenericSMI { /// PHY initialisation. fn phy_init(&mut self, sm: &mut S) { // Clear WU CSR - Self::smi_write_ext(sm, PHY_REG_WUCSR, 0); + self.smi_write_ext(sm, PHY_REG_WUCSR, 0); // Enable auto-negotiation sm.smi_write(PHY_REG_BCR, PHY_REG_BCR_AN | PHY_REG_BCR_ANRST | PHY_REG_BCR_100M); @@ -78,7 +78,7 @@ unsafe impl PHY for GenericSMI { /// Public functions for the PHY impl GenericSMI { // Writes a value to an extended PHY register in MMD address space - fn smi_write_ext(sm: &mut S, reg_addr: u16, reg_data: u16) { + fn smi_write_ext(&mut self, sm: &mut S, reg_addr: u16, reg_data: u16) { sm.smi_write(PHY_REG_CTL, 0x0003); // set address sm.smi_write(PHY_REG_ADDAR, reg_addr); sm.smi_write(PHY_REG_CTL, 0x4003); // set data From 975a780efe73b20d3ba63a116792b28f9a6edada Mon Sep 17 00:00:00 2001 From: xoviat Date: Sat, 15 Jul 2023 09:57:09 -0500 Subject: [PATCH 4/5] stm32/eth: impl. poll interval --- embassy-stm32/src/eth/generic_smi.rs | 25 ++++++++++++++++++++++++- examples/stm32f4/src/bin/eth.rs | 2 +- examples/stm32f7/src/bin/eth.rs | 2 +- examples/stm32h5/src/bin/eth.rs | 2 +- examples/stm32h7/src/bin/eth.rs | 2 +- examples/stm32h7/src/bin/eth_client.rs | 2 +- 6 files changed, 29 insertions(+), 6 deletions(-) diff --git a/embassy-stm32/src/eth/generic_smi.rs b/embassy-stm32/src/eth/generic_smi.rs index 5c7856437..22631c2d1 100644 --- a/embassy-stm32/src/eth/generic_smi.rs +++ b/embassy-stm32/src/eth/generic_smi.rs @@ -1,6 +1,10 @@ //! Generic SMI Ethernet PHY +#[cfg(feature = "time")] +use embassy_time::{Duration, Timer}; use futures::task::Context; +#[cfg(feature = "time")] +use futures::FutureExt; use super::{StationManagement, PHY}; @@ -38,7 +42,22 @@ mod phy_consts { use self::phy_consts::*; /// Generic SMI Ethernet PHY -pub struct GenericSMI; +pub struct GenericSMI { + #[cfg(feature = "time")] + poll_interval: Duration, +} + +impl GenericSMI { + #[cfg(feature = "time")] + pub fn new(poll_interval: Duration) -> Self { + Self { poll_interval } + } + + #[cfg(not(feature = "time"))] + pub fn new() -> Self { + Self {} + } +} unsafe impl PHY for GenericSMI { /// Reset PHY and wait for it to come out of reset. @@ -57,8 +76,12 @@ unsafe impl PHY for GenericSMI { } fn poll_link(&mut self, sm: &mut S, 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(PHY_REG_BSR); // No link without autonegotiate diff --git a/examples/stm32f4/src/bin/eth.rs b/examples/stm32f4/src/bin/eth.rs index c32d886d0..15390592a 100644 --- a/examples/stm32f4/src/bin/eth.rs +++ b/examples/stm32f4/src/bin/eth.rs @@ -56,7 +56,7 @@ async fn main(spawner: Spawner) -> ! { p.PG13, p.PB13, p.PG11, - GenericSMI, + GenericSMI::new(Duration::from_millis(500)), mac_addr, 0, ); diff --git a/examples/stm32f7/src/bin/eth.rs b/examples/stm32f7/src/bin/eth.rs index fde6a7576..c1baa5848 100644 --- a/examples/stm32f7/src/bin/eth.rs +++ b/examples/stm32f7/src/bin/eth.rs @@ -57,7 +57,7 @@ async fn main(spawner: Spawner) -> ! { p.PG13, p.PB13, p.PG11, - GenericSMI, + GenericSMI::new(Duration::from_millis(500)), mac_addr, 0, ); diff --git a/examples/stm32h5/src/bin/eth.rs b/examples/stm32h5/src/bin/eth.rs index 78c8282a6..3b33265ac 100644 --- a/examples/stm32h5/src/bin/eth.rs +++ b/examples/stm32h5/src/bin/eth.rs @@ -76,7 +76,7 @@ async fn main(spawner: Spawner) -> ! { p.PG13, p.PB15, p.PG11, - GenericSMI, + GenericSMI::new(Duration::from_millis(500)), mac_addr, 0, ); diff --git a/examples/stm32h7/src/bin/eth.rs b/examples/stm32h7/src/bin/eth.rs index 12d37f7a4..9203708ad 100644 --- a/examples/stm32h7/src/bin/eth.rs +++ b/examples/stm32h7/src/bin/eth.rs @@ -58,7 +58,7 @@ async fn main(spawner: Spawner) -> ! { p.PG13, p.PB13, p.PG11, - GenericSMI, + GenericSMI::new(Duration::from_millis(500)), mac_addr, 0, ); diff --git a/examples/stm32h7/src/bin/eth_client.rs b/examples/stm32h7/src/bin/eth_client.rs index 6078fc3fe..8abc41095 100644 --- a/examples/stm32h7/src/bin/eth_client.rs +++ b/examples/stm32h7/src/bin/eth_client.rs @@ -59,7 +59,7 @@ async fn main(spawner: Spawner) -> ! { p.PG13, p.PB13, p.PG11, - GenericSMI, + GenericSMI::new(Duration::from_millis(500)), mac_addr, 0, ); From 17d5e1c47046ea69ef7ac6041ae3cf3be587221b Mon Sep 17 00:00:00 2001 From: xoviat Date: Sat, 15 Jul 2023 12:02:08 -0500 Subject: [PATCH 5/5] stm32/eth: add set_poll_interval --- embassy-stm32/src/eth/generic_smi.rs | 10 ++++++++-- examples/stm32f4/src/bin/eth.rs | 2 +- examples/stm32f7/src/bin/eth.rs | 2 +- examples/stm32h5/src/bin/eth.rs | 2 +- examples/stm32h7/src/bin/eth.rs | 2 +- examples/stm32h7/src/bin/eth_client.rs | 2 +- 6 files changed, 13 insertions(+), 7 deletions(-) diff --git a/embassy-stm32/src/eth/generic_smi.rs b/embassy-stm32/src/eth/generic_smi.rs index 22631c2d1..90631b175 100644 --- a/embassy-stm32/src/eth/generic_smi.rs +++ b/embassy-stm32/src/eth/generic_smi.rs @@ -49,8 +49,10 @@ pub struct GenericSMI { impl GenericSMI { #[cfg(feature = "time")] - pub fn new(poll_interval: Duration) -> Self { - Self { poll_interval } + pub fn new() -> Self { + Self { + poll_interval: Duration::from_millis(500), + } } #[cfg(not(feature = "time"))] @@ -100,6 +102,10 @@ unsafe impl PHY for GenericSMI { /// Public functions for the PHY impl GenericSMI { + pub fn set_poll_interval(&mut self, poll_interval: Duration) { + self.poll_interval = poll_interval + } + // 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(PHY_REG_CTL, 0x0003); // set address diff --git a/examples/stm32f4/src/bin/eth.rs b/examples/stm32f4/src/bin/eth.rs index 15390592a..d0b164393 100644 --- a/examples/stm32f4/src/bin/eth.rs +++ b/examples/stm32f4/src/bin/eth.rs @@ -56,7 +56,7 @@ async fn main(spawner: Spawner) -> ! { p.PG13, p.PB13, p.PG11, - GenericSMI::new(Duration::from_millis(500)), + GenericSMI::new(), mac_addr, 0, ); diff --git a/examples/stm32f7/src/bin/eth.rs b/examples/stm32f7/src/bin/eth.rs index c1baa5848..c6b2ba45c 100644 --- a/examples/stm32f7/src/bin/eth.rs +++ b/examples/stm32f7/src/bin/eth.rs @@ -57,7 +57,7 @@ async fn main(spawner: Spawner) -> ! { p.PG13, p.PB13, p.PG11, - GenericSMI::new(Duration::from_millis(500)), + GenericSMI::new(), mac_addr, 0, ); diff --git a/examples/stm32h5/src/bin/eth.rs b/examples/stm32h5/src/bin/eth.rs index 3b33265ac..0bff85ed8 100644 --- a/examples/stm32h5/src/bin/eth.rs +++ b/examples/stm32h5/src/bin/eth.rs @@ -76,7 +76,7 @@ async fn main(spawner: Spawner) -> ! { p.PG13, p.PB15, p.PG11, - GenericSMI::new(Duration::from_millis(500)), + GenericSMI::new(), mac_addr, 0, ); diff --git a/examples/stm32h7/src/bin/eth.rs b/examples/stm32h7/src/bin/eth.rs index 9203708ad..cfafcaed1 100644 --- a/examples/stm32h7/src/bin/eth.rs +++ b/examples/stm32h7/src/bin/eth.rs @@ -58,7 +58,7 @@ async fn main(spawner: Spawner) -> ! { p.PG13, p.PB13, p.PG11, - GenericSMI::new(Duration::from_millis(500)), + GenericSMI::new(), mac_addr, 0, ); diff --git a/examples/stm32h7/src/bin/eth_client.rs b/examples/stm32h7/src/bin/eth_client.rs index 8abc41095..4ed737578 100644 --- a/examples/stm32h7/src/bin/eth_client.rs +++ b/examples/stm32h7/src/bin/eth_client.rs @@ -59,7 +59,7 @@ async fn main(spawner: Spawner) -> ! { p.PG13, p.PB13, p.PG11, - GenericSMI::new(Duration::from_millis(500)), + GenericSMI::new(), mac_addr, 0, );