diff --git a/embassy-stm32/src/eth/lan8742a.rs b/embassy-stm32/src/eth/generic_smi.rs similarity index 74% rename from embassy-stm32/src/eth/lan8742a.rs rename to embassy-stm32/src/eth/generic_smi.rs index 74d0ca5de..5a323bf5a 100644 --- a/embassy-stm32/src/eth/lan8742a.rs +++ b/embassy-stm32/src/eth/generic_smi.rs @@ -1,4 +1,4 @@ -//! SMSC LAN8742A Ethernet PHY +//! Generic SMI Ethernet PHY use super::{StationManagement, PHY}; @@ -13,7 +13,6 @@ mod phy_consts { pub const PHY_REG_ANEXP: u8 = 0x06; pub const PHY_REG_ANNPTX: u8 = 0x07; pub const PHY_REG_ANNPRX: u8 = 0x08; - pub const PHY_REG_SSR: u8 = 0x1F; // Special Status Register pub const PHY_REG_CTL: u8 = 0x0D; // Ethernet PHY Register Control pub const PHY_REG_ADDAR: u8 = 0x0E; // Ethernet PHY Address or Data @@ -33,20 +32,13 @@ mod phy_consts { pub const PHY_REG_BSR_UP: u16 = 1 << 2; pub const PHY_REG_BSR_FAULT: u16 = 1 << 4; pub const PHY_REG_BSR_ANDONE: u16 = 1 << 5; - - pub const PHY_REG_SSR_ANDONE: u16 = 1 << 12; - pub const PHY_REG_SSR_SPEED: u16 = 0b111 << 2; - pub const PHY_REG_SSR_10BASE_HD: u16 = 0b001 << 2; - pub const PHY_REG_SSR_10BASE_FD: u16 = 0b101 << 2; - pub const PHY_REG_SSR_100BASE_HD: u16 = 0b010 << 2; - pub const PHY_REG_SSR_100BASE_FD: u16 = 0b110 << 2; } use self::phy_consts::*; -/// SMSC LAN8742A Ethernet PHY -pub struct LAN8742A; +/// Generic SMI Ethernet PHY +pub struct GenericSMI; -unsafe impl PHY for LAN8742A { +unsafe impl PHY for GenericSMI { /// Reset PHY and wait for it to come out of reset. fn phy_reset(sm: &mut S) { sm.smi_write(PHY_REG_BCR, PHY_REG_BCR_RESET); @@ -67,7 +59,6 @@ unsafe impl PHY for LAN8742A { fn poll_link(sm: &mut S) -> bool { let bsr = sm.smi_read(PHY_REG_BSR); - let ssr = sm.smi_read(PHY_REG_SSR); // No link without autonegotiate if bsr & PHY_REG_BSR_ANDONE == 0 { @@ -77,22 +68,14 @@ unsafe impl PHY for LAN8742A { if bsr & PHY_REG_BSR_UP == 0 { return false; } - // No link if autonegotiate incomplete - if ssr & PHY_REG_SSR_ANDONE == 0 { - return false; - } - // No link if other side isn't 100Mbps full duplex - if ssr & PHY_REG_SSR_SPEED != PHY_REG_SSR_100BASE_FD { - return false; - } // Got link true } } -/// Public functions for the LAN8742A -impl LAN8742A { +/// 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) { sm.smi_write(PHY_REG_CTL, 0x0003); // set address diff --git a/embassy-stm32/src/eth/mod.rs b/embassy-stm32/src/eth/mod.rs index 1e304b789..28f0c178f 100644 --- a/embassy-stm32/src/eth/mod.rs +++ b/embassy-stm32/src/eth/mod.rs @@ -1,10 +1,9 @@ #![macro_use] -#[cfg_attr(eth_v1c, path = "v1c/mod.rs")] +#[cfg_attr(any(eth_v1a, eth_v1b, eth_v1c), path = "v1/mod.rs")] #[cfg_attr(eth_v2, path = "v2/mod.rs")] -#[cfg_attr(eth_v1, path = "v1.rs")] mod _version; -pub mod lan8742a; +pub mod generic_smi; pub use _version::*; diff --git a/embassy-stm32/src/eth/v1.rs b/embassy-stm32/src/eth/v1.rs deleted file mode 100644 index 8b1378917..000000000 --- a/embassy-stm32/src/eth/v1.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/embassy-stm32/src/eth/v1c/descriptors.rs b/embassy-stm32/src/eth/v1/descriptors.rs similarity index 100% rename from embassy-stm32/src/eth/v1c/descriptors.rs rename to embassy-stm32/src/eth/v1/descriptors.rs diff --git a/embassy-stm32/src/eth/v1c/mod.rs b/embassy-stm32/src/eth/v1/mod.rs similarity index 88% rename from embassy-stm32/src/eth/v1c/mod.rs rename to embassy-stm32/src/eth/v1/mod.rs index 8abe2e172..f102f4314 100644 --- a/embassy-stm32/src/eth/v1c/mod.rs +++ b/embassy-stm32/src/eth/v1/mod.rs @@ -12,7 +12,11 @@ use embassy_net::{Device, DeviceCapabilities, LinkState, PacketBuf, MTU}; use crate::gpio::sealed::Pin as __GpioPin; use crate::gpio::{sealed::AFType, AnyPin, Speed}; -use crate::pac::{ETH, RCC, SYSCFG}; +#[cfg(eth_v1a)] +use crate::pac::AFIO; +#[cfg(any(eth_v1b, eth_v1c))] +use crate::pac::SYSCFG; +use crate::pac::{ETH, RCC}; mod descriptors; mod rx_desc; @@ -42,6 +46,33 @@ pub struct Ethernet<'d, T: Instance, P: PHY, const TX: usize, const RX: usize> { mac_addr: [u8; 6], } +#[cfg(eth_v1a)] +macro_rules! config_in_pins { + ($($pin:ident),*) => { + // NOTE(unsafe) Exclusive access to the registers + critical_section::with(|_| { + $( + // TODO properly create a set_as_input function + $pin.set_as_af($pin.af_num(), AFType::Input); + )* + }) + } +} + +#[cfg(eth_v1a)] +macro_rules! config_af_pins { + ($($pin:ident),*) => { + // NOTE(unsafe) Exclusive access to the registers + critical_section::with(|_| { + $( + // We are lucky here, this configures to max speed (50MHz) + $pin.set_as_af($pin.af_num(), AFType::OutputPushPull); + )* + }) + }; +} + +#[cfg(any(eth_v1b, eth_v1c))] macro_rules! config_pins { ($($pin:ident),*) => { // NOTE(unsafe) Exclusive access to the registers @@ -77,6 +108,22 @@ impl<'d, T: Instance, P: PHY, const TX: usize, const RX: usize> Ethernet<'d, T, // Enable the necessary Clocks // NOTE(unsafe) We have exclusive access to the registers + #[cfg(eth_v1a)] + critical_section::with(|_| { + RCC.apb2enr().modify(|w| w.set_afioen(true)); + + // Select RMII (Reduced Media Independent Interface) + // Must be done prior to enabling peripheral clock + AFIO.mapr().modify(|w| w.set_mii_rmii_sel(true)); + + RCC.ahbenr().modify(|w| { + w.set_ethen(true); + w.set_ethtxen(true); + w.set_ethrxen(true); + }); + }); + + #[cfg(any(eth_v1b, eth_v1c))] critical_section::with(|_| { RCC.apb2enr().modify(|w| w.set_syscfgen(true)); RCC.ahb1enr().modify(|w| { @@ -89,6 +136,13 @@ impl<'d, T: Instance, P: PHY, const TX: usize, const RX: usize> Ethernet<'d, T, SYSCFG.pmc().modify(|w| w.set_mii_rmii_sel(true)); }); + #[cfg(eth_v1a)] + { + config_in_pins!(ref_clk, rx_d0, rx_d1); + config_af_pins!(mdio, mdc, tx_d0, tx_d1, tx_en); + } + + #[cfg(any(eth_v1b, eth_v1c))] config_pins!(ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en); // NOTE(unsafe) We are ourselves not leak-safe. diff --git a/embassy-stm32/src/eth/v1c/rx_desc.rs b/embassy-stm32/src/eth/v1/rx_desc.rs similarity index 100% rename from embassy-stm32/src/eth/v1c/rx_desc.rs rename to embassy-stm32/src/eth/v1/rx_desc.rs diff --git a/embassy-stm32/src/eth/v1c/tx_desc.rs b/embassy-stm32/src/eth/v1/tx_desc.rs similarity index 100% rename from embassy-stm32/src/eth/v1c/tx_desc.rs rename to embassy-stm32/src/eth/v1/tx_desc.rs diff --git a/examples/stm32f7/src/bin/eth.rs b/examples/stm32f7/src/bin/eth.rs index 446756c29..33e41de9c 100644 --- a/examples/stm32f7/src/bin/eth.rs +++ b/examples/stm32f7/src/bin/eth.rs @@ -11,7 +11,7 @@ use embassy::util::Forever; use embassy_net::{ Config as NetConfig, Ipv4Address, Ipv4Cidr, StackResources, StaticConfigurator, TcpSocket, }; -use embassy_stm32::eth::lan8742a::LAN8742A; +use embassy_stm32::eth::generic_smi::GenericSMI; use embassy_stm32::eth::{Ethernet, State}; use embassy_stm32::interrupt; use embassy_stm32::peripherals::ETH; @@ -26,7 +26,7 @@ use panic_probe as _; #[embassy::task] async fn main_task( - device: &'static mut Ethernet<'static, ETH, LAN8742A, 4, 4>, + device: &'static mut Ethernet<'static, ETH, GenericSMI, 4, 4>, config: &'static mut StaticConfigurator, spawner: Spawner, ) { @@ -82,7 +82,7 @@ static mut RNG_INST: Option> = None; static EXECUTOR: Forever = Forever::new(); static STATE: Forever> = Forever::new(); -static ETH: Forever> = Forever::new(); +static ETH: Forever> = Forever::new(); static CONFIG: Forever = Forever::new(); static NET_RESOURCES: Forever> = Forever::new(); @@ -112,7 +112,7 @@ fn main() -> ! { let eth = unsafe { ETH.put(Ethernet::new( state, p.ETH, eth_int, p.PA1, p.PA2, p.PC1, p.PA7, p.PC4, p.PC5, p.PG13, p.PB13, - p.PG11, LAN8742A, mac_addr, 0, + p.PG11, GenericSMI, mac_addr, 0, )) }; diff --git a/examples/stm32h7/src/bin/eth.rs b/examples/stm32h7/src/bin/eth.rs index 4eb5421a8..9a2e7a33d 100644 --- a/examples/stm32h7/src/bin/eth.rs +++ b/examples/stm32h7/src/bin/eth.rs @@ -14,7 +14,7 @@ use embassy::util::Forever; use embassy_net::{ Config as NetConfig, Ipv4Address, Ipv4Cidr, StackResources, StaticConfigurator, TcpSocket, }; -use embassy_stm32::eth::lan8742a::LAN8742A; +use embassy_stm32::eth::generic_smi::GenericSMI; use embassy_stm32::eth::{Ethernet, State}; use embassy_stm32::interrupt; use embassy_stm32::peripherals::ETH; @@ -26,7 +26,7 @@ use heapless::Vec; #[embassy::task] async fn main_task( - device: &'static mut Ethernet<'static, ETH, LAN8742A, 4, 4>, + device: &'static mut Ethernet<'static, ETH, GenericSMI, 4, 4>, config: &'static mut StaticConfigurator, spawner: Spawner, ) { @@ -82,7 +82,7 @@ static mut RNG_INST: Option> = None; static EXECUTOR: Forever = Forever::new(); static STATE: Forever> = Forever::new(); -static ETH: Forever> = Forever::new(); +static ETH: Forever> = Forever::new(); static CONFIG: Forever = Forever::new(); static NET_RESOURCES: Forever> = Forever::new(); @@ -114,7 +114,7 @@ fn main() -> ! { let eth = unsafe { ETH.put(Ethernet::new( state, p.ETH, eth_int, p.PA1, p.PA2, p.PC1, p.PA7, p.PC4, p.PC5, p.PG13, p.PB13, - p.PG11, LAN8742A, mac_addr, 0, + p.PG11, GenericSMI, mac_addr, 0, )) }; diff --git a/stm32-data b/stm32-data index b71707e52..9abfa9d2b 160000 --- a/stm32-data +++ b/stm32-data @@ -1 +1 @@ -Subproject commit b71707e525e336f0afb9a74f3c436d3dd540ffcf +Subproject commit 9abfa9d2b51e6071fdc7e680b4a171e4fa20c2fb