stm32/eth: rename PHY->Phy, GenericSMI -> GenericPhy. Remove unneeded unsafes.

We shouldn't use `unsafe` to mark merely "dangerous" actions, only actions that
actually cause UB.
This commit is contained in:
Dario Nieuwenhuis 2025-01-26 22:42:13 +01:00
parent c8d29a1e2c
commit b1245858f3
12 changed files with 56 additions and 66 deletions

View File

@ -7,7 +7,7 @@ use embassy_time::{Duration, Timer};
#[cfg(feature = "time")] #[cfg(feature = "time")]
use futures_util::FutureExt; use futures_util::FutureExt;
use super::{StationManagement, PHY}; use super::{Phy, StationManagement};
#[allow(dead_code)] #[allow(dead_code)]
mod phy_consts { mod phy_consts {
@ -43,13 +43,13 @@ mod phy_consts {
use self::phy_consts::*; use self::phy_consts::*;
/// Generic SMI Ethernet PHY implementation /// Generic SMI Ethernet PHY implementation
pub struct GenericSMI { pub struct GenericPhy {
phy_addr: u8, phy_addr: u8,
#[cfg(feature = "time")] #[cfg(feature = "time")]
poll_interval: Duration, poll_interval: Duration,
} }
impl GenericSMI { impl GenericPhy {
/// Construct the PHY. It assumes the address `phy_addr` in the SMI communication /// Construct the PHY. It assumes the address `phy_addr` in the SMI communication
/// ///
/// # Panics /// # Panics
@ -89,7 +89,7 @@ fn blocking_delay_us(us: u32) {
} }
} }
unsafe impl PHY for GenericSMI { impl Phy for GenericPhy {
fn phy_reset<S: StationManagement>(&mut self, sm: &mut S) { fn phy_reset<S: StationManagement>(&mut self, sm: &mut S) {
// Detect SMI address // Detect SMI address
if self.phy_addr == 0xFF { if self.phy_addr == 0xFF {
@ -148,7 +148,7 @@ unsafe impl PHY for GenericSMI {
} }
/// Public functions for the PHY /// Public functions for the PHY
impl GenericSMI { impl GenericPhy {
/// Set the SMI polling interval. /// Set the SMI polling interval.
#[cfg(feature = "time")] #[cfg(feature = "time")]
pub fn set_poll_interval(&mut self, poll_interval: Duration) { pub fn set_poll_interval(&mut self, poll_interval: Duration) {

View File

@ -4,7 +4,7 @@
#[cfg_attr(any(eth_v1a, eth_v1b, eth_v1c), path = "v1/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_v2, path = "v2/mod.rs")]
mod _version; mod _version;
pub mod generic_smi; mod generic_phy;
use core::mem::MaybeUninit; use core::mem::MaybeUninit;
use core::task::Context; use core::task::Context;
@ -13,6 +13,7 @@ use embassy_net_driver::{Capabilities, HardwareAddress, LinkState};
use embassy_sync::waitqueue::AtomicWaker; use embassy_sync::waitqueue::AtomicWaker;
pub use self::_version::{InterruptHandler, *}; pub use self::_version::{InterruptHandler, *};
pub use self::generic_phy::*;
use crate::rcc::RccPeripheral; use crate::rcc::RccPeripheral;
#[allow(unused)] #[allow(unused)]
@ -71,7 +72,7 @@ impl<const TX: usize, const RX: usize> PacketQueue<TX, RX> {
static WAKER: AtomicWaker = AtomicWaker::new(); static WAKER: AtomicWaker = AtomicWaker::new();
impl<'d, T: Instance, P: PHY> embassy_net_driver::Driver for Ethernet<'d, T, P> { impl<'d, T: Instance, P: Phy> embassy_net_driver::Driver for Ethernet<'d, T, P> {
type RxToken<'a> type RxToken<'a>
= RxToken<'a, 'd> = RxToken<'a, 'd>
where where
@ -156,23 +157,15 @@ impl<'a, 'd> embassy_net_driver::TxToken for TxToken<'a, 'd> {
} }
/// Station Management Interface (SMI) on an ethernet PHY /// Station Management Interface (SMI) on an ethernet PHY
/// pub trait StationManagement {
/// # Safety
///
/// The methods cannot move out of self
pub unsafe trait StationManagement {
/// Read a register over SMI. /// Read a register over SMI.
fn smi_read(&mut self, phy_addr: u8, reg: u8) -> u16; fn smi_read(&mut self, phy_addr: u8, reg: u8) -> u16;
/// Write a register over SMI. /// Write a register over SMI.
fn smi_write(&mut self, phy_addr: u8, reg: u8, val: u16); fn smi_write(&mut self, phy_addr: u8, reg: u8, val: u16);
} }
/// Traits for an Ethernet PHY /// Trait for an Ethernet PHY
/// pub trait Phy {
/// # Safety
///
/// The methods cannot move S
pub unsafe trait PHY {
/// Reset PHY and wait for it to come out of reset. /// Reset PHY and wait for it to come out of reset.
fn phy_reset<S: StationManagement>(&mut self, sm: &mut S); fn phy_reset<S: StationManagement>(&mut self, sm: &mut S);
/// PHY initialisation. /// PHY initialisation.
@ -181,18 +174,23 @@ pub unsafe trait PHY {
fn poll_link<S: StationManagement>(&mut self, sm: &mut S, cx: &mut Context) -> bool; fn poll_link<S: StationManagement>(&mut self, sm: &mut S, cx: &mut Context) -> bool;
} }
impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> {
/// Directly expose the SMI interface used by the Ethernet driver. /// Directly expose the SMI interface used by the Ethernet driver.
/// ///
/// This can be used to for example configure special PHY registers for compliance testing. /// This can be used to for example configure special PHY registers for compliance testing.
/// pub fn station_management(&mut self) -> &mut impl StationManagement {
/// # Safety
///
/// Revert any temporary PHY register changes such as to enable test modes before handing
/// the Ethernet device over to the networking stack otherwise things likely won't work.
pub unsafe fn station_management(&mut self) -> &mut impl StationManagement {
&mut self.station_management &mut self.station_management
} }
/// Access the user-supplied `Phy`.
pub fn phy(&self) -> &P {
&self.phy
}
/// Mutably access the user-supplied `Phy`.
pub fn phy_mut(&mut self) -> &mut P {
&mut self.phy
}
} }
trait SealedInstance { trait SealedInstance {

View File

@ -46,7 +46,7 @@ impl interrupt::typelevel::Handler<interrupt::typelevel::ETH> for InterruptHandl
} }
/// Ethernet driver. /// Ethernet driver.
pub struct Ethernet<'d, T: Instance, P: PHY> { pub struct Ethernet<'d, T: Instance, P: Phy> {
_peri: PeripheralRef<'d, T>, _peri: PeripheralRef<'d, T>,
pub(crate) tx: TDesRing<'d>, pub(crate) tx: TDesRing<'d>,
pub(crate) rx: RDesRing<'d>, pub(crate) rx: RDesRing<'d>,
@ -91,7 +91,7 @@ macro_rules! config_pins {
}; };
} }
impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> {
/// safety: the returned instance is not leak-safe /// safety: the returned instance is not leak-safe
pub fn new<const TX: usize, const RX: usize>( pub fn new<const TX: usize, const RX: usize>(
queue: &'d mut PacketQueue<TX, RX>, queue: &'d mut PacketQueue<TX, RX>,
@ -272,12 +272,12 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
} }
/// Ethernet station management interface. /// Ethernet station management interface.
pub struct EthernetStationManagement<T: Instance> { pub(crate) struct EthernetStationManagement<T: Instance> {
peri: PhantomData<T>, peri: PhantomData<T>,
clock_range: Cr, clock_range: Cr,
} }
unsafe impl<T: Instance> StationManagement for EthernetStationManagement<T> { impl<T: Instance> StationManagement for EthernetStationManagement<T> {
fn smi_read(&mut self, phy_addr: u8, reg: u8) -> u16 { fn smi_read(&mut self, phy_addr: u8, reg: u8) -> u16 {
let mac = T::regs().ethernet_mac(); let mac = T::regs().ethernet_mac();
@ -307,7 +307,7 @@ unsafe impl<T: Instance> StationManagement for EthernetStationManagement<T> {
} }
} }
impl<'d, T: Instance, P: PHY> Drop for Ethernet<'d, T, P> { impl<'d, T: Instance, P: Phy> Drop for Ethernet<'d, T, P> {
fn drop(&mut self) { fn drop(&mut self) {
let dma = T::regs().ethernet_dma(); let dma = T::regs().ethernet_dma();
let mac = T::regs().ethernet_mac(); let mac = T::regs().ethernet_mac();

View File

@ -36,7 +36,7 @@ impl interrupt::typelevel::Handler<interrupt::typelevel::ETH> for InterruptHandl
} }
/// Ethernet driver. /// Ethernet driver.
pub struct Ethernet<'d, T: Instance, P: PHY> { pub struct Ethernet<'d, T: Instance, P: Phy> {
_peri: PeripheralRef<'d, T>, _peri: PeripheralRef<'d, T>,
pub(crate) tx: TDesRing<'d>, pub(crate) tx: TDesRing<'d>,
pub(crate) rx: RDesRing<'d>, pub(crate) rx: RDesRing<'d>,
@ -63,7 +63,7 @@ macro_rules! config_pins {
}; };
} }
impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { 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 9 pins.
pub fn new<const TX: usize, const RX: usize>( pub fn new<const TX: usize, const RX: usize>(
queue: &'d mut PacketQueue<TX, RX>, queue: &'d mut PacketQueue<TX, RX>,
@ -304,7 +304,7 @@ pub struct EthernetStationManagement<T: Instance> {
clock_range: u8, clock_range: u8,
} }
unsafe impl<T: Instance> StationManagement for EthernetStationManagement<T> { impl<T: Instance> StationManagement for EthernetStationManagement<T> {
fn smi_read(&mut self, phy_addr: u8, reg: u8) -> u16 { fn smi_read(&mut self, phy_addr: u8, reg: u8) -> u16 {
let mac = T::regs().ethernet_mac(); let mac = T::regs().ethernet_mac();
@ -334,7 +334,7 @@ unsafe impl<T: Instance> StationManagement for EthernetStationManagement<T> {
} }
} }
impl<'d, T: Instance, P: PHY> Drop for Ethernet<'d, T, P> { impl<'d, T: Instance, P: Phy> Drop for Ethernet<'d, T, P> {
fn drop(&mut self) { fn drop(&mut self) {
let dma = T::regs().ethernet_dma(); let dma = T::regs().ethernet_dma();
let mac = T::regs().ethernet_mac(); let mac = T::regs().ethernet_mac();

View File

@ -5,8 +5,7 @@ use defmt::*;
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_net::tcp::TcpSocket; use embassy_net::tcp::TcpSocket;
use embassy_net::{Ipv4Address, StackResources}; use embassy_net::{Ipv4Address, StackResources};
use embassy_stm32::eth::generic_smi::GenericSMI; use embassy_stm32::eth::{Ethernet, GenericPhy, PacketQueue};
use embassy_stm32::eth::{Ethernet, PacketQueue};
use embassy_stm32::peripherals::ETH; use embassy_stm32::peripherals::ETH;
use embassy_stm32::rng::Rng; use embassy_stm32::rng::Rng;
use embassy_stm32::time::Hertz; use embassy_stm32::time::Hertz;
@ -21,7 +20,7 @@ bind_interrupts!(struct Irqs {
HASH_RNG => rng::InterruptHandler<peripherals::RNG>; HASH_RNG => rng::InterruptHandler<peripherals::RNG>;
}); });
type Device = Ethernet<'static, ETH, GenericSMI>; type Device = Ethernet<'static, ETH, GenericPhy>;
#[embassy_executor::task] #[embassy_executor::task]
async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! { async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! {
@ -76,7 +75,7 @@ async fn main(spawner: Spawner) -> ! {
p.PG13, p.PG13,
p.PB13, p.PB13,
p.PG11, p.PG11,
GenericSMI::new_auto(), GenericPhy::new_auto(),
mac_addr, mac_addr,
); );

View File

@ -3,8 +3,7 @@
use defmt::*; use defmt::*;
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_stm32::eth::generic_smi::GenericSMI; use embassy_stm32::eth::{Ethernet, GenericPhy, PacketQueue, StationManagement};
use embassy_stm32::eth::{Ethernet, PacketQueue, StationManagement};
use embassy_stm32::time::Hertz; use embassy_stm32::time::Hertz;
use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config};
use embassy_time::Timer; use embassy_time::Timer;
@ -59,11 +58,11 @@ async fn main(_spawner: Spawner) -> ! {
p.PG13, p.PG13,
p.PB13, p.PB13,
p.PG11, p.PG11,
GenericSMI::new(PHY_ADDR), GenericPhy::new(PHY_ADDR),
mac_addr, mac_addr,
); );
let sm = unsafe { device.station_management() }; let sm = device.station_management();
// Just an example. Exact register settings depend on the specific PHY and test. // Just an example. Exact register settings depend on the specific PHY and test.
sm.smi_write(PHY_ADDR, 0, 0x2100); sm.smi_write(PHY_ADDR, 0, 0x2100);

View File

@ -5,8 +5,7 @@ use defmt::*;
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_net::tcp::TcpSocket; use embassy_net::tcp::TcpSocket;
use embassy_net::{Ipv4Address, StackResources}; use embassy_net::{Ipv4Address, StackResources};
use embassy_stm32::eth::generic_smi::GenericSMI; use embassy_stm32::eth::{Ethernet, GenericPhy, PacketQueue};
use embassy_stm32::eth::{Ethernet, PacketQueue};
use embassy_stm32::peripherals::ETH; use embassy_stm32::peripherals::ETH;
use embassy_stm32::rng::Rng; use embassy_stm32::rng::Rng;
use embassy_stm32::time::Hertz; use embassy_stm32::time::Hertz;
@ -22,7 +21,7 @@ bind_interrupts!(struct Irqs {
HASH_RNG => rng::InterruptHandler<peripherals::RNG>; HASH_RNG => rng::InterruptHandler<peripherals::RNG>;
}); });
type Device = Ethernet<'static, ETH, GenericSMI>; type Device = Ethernet<'static, ETH, GenericPhy>;
#[embassy_executor::task] #[embassy_executor::task]
async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! { async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! {
@ -77,7 +76,7 @@ async fn main(spawner: Spawner) -> ! {
p.PG13, p.PG13,
p.PB13, p.PB13,
p.PG11, p.PG11,
GenericSMI::new_auto(), GenericPhy::new_auto(),
mac_addr, mac_addr,
); );

View File

@ -5,8 +5,7 @@ use defmt::*;
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_net::tcp::TcpSocket; use embassy_net::tcp::TcpSocket;
use embassy_net::{Ipv4Address, StackResources}; use embassy_net::{Ipv4Address, StackResources};
use embassy_stm32::eth::generic_smi::GenericSMI; use embassy_stm32::eth::{Ethernet, GenericPhy, PacketQueue};
use embassy_stm32::eth::{Ethernet, PacketQueue};
use embassy_stm32::peripherals::ETH; use embassy_stm32::peripherals::ETH;
use embassy_stm32::rcc::{ use embassy_stm32::rcc::{
AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllDiv, PllMul, PllPreDiv, PllSource, Sysclk, VoltageScale, AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllDiv, PllMul, PllPreDiv, PllSource, Sysclk, VoltageScale,
@ -25,7 +24,7 @@ bind_interrupts!(struct Irqs {
RNG => rng::InterruptHandler<peripherals::RNG>; RNG => rng::InterruptHandler<peripherals::RNG>;
}); });
type Device = Ethernet<'static, ETH, GenericSMI>; type Device = Ethernet<'static, ETH, GenericPhy>;
#[embassy_executor::task] #[embassy_executor::task]
async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! { async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! {
@ -80,7 +79,7 @@ async fn main(spawner: Spawner) -> ! {
p.PG13, p.PG13,
p.PB15, p.PB15,
p.PG11, p.PG11,
GenericSMI::new_auto(), GenericPhy::new_auto(),
mac_addr, mac_addr,
); );

View File

@ -5,8 +5,7 @@ use defmt::*;
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_net::tcp::TcpSocket; use embassy_net::tcp::TcpSocket;
use embassy_net::{Ipv4Address, StackResources}; use embassy_net::{Ipv4Address, StackResources};
use embassy_stm32::eth::generic_smi::GenericSMI; use embassy_stm32::eth::{Ethernet, GenericPhy, PacketQueue};
use embassy_stm32::eth::{Ethernet, PacketQueue};
use embassy_stm32::peripherals::ETH; use embassy_stm32::peripherals::ETH;
use embassy_stm32::rng::Rng; use embassy_stm32::rng::Rng;
use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config};
@ -21,7 +20,7 @@ bind_interrupts!(struct Irqs {
RNG => rng::InterruptHandler<peripherals::RNG>; RNG => rng::InterruptHandler<peripherals::RNG>;
}); });
type Device = Ethernet<'static, ETH, GenericSMI>; type Device = Ethernet<'static, ETH, GenericPhy>;
#[embassy_executor::task] #[embassy_executor::task]
async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! { async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! {
@ -79,7 +78,7 @@ async fn main(spawner: Spawner) -> ! {
p.PG13, // TX_D0: Transmit Bit 0 p.PG13, // TX_D0: Transmit Bit 0
p.PB13, // TX_D1: Transmit Bit 1 p.PB13, // TX_D1: Transmit Bit 1
p.PG11, // TX_EN: Transmit Enable p.PG11, // TX_EN: Transmit Enable
GenericSMI::new_auto(), GenericPhy::new_auto(),
mac_addr, mac_addr,
); );

View File

@ -7,8 +7,7 @@ use defmt::*;
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_net::tcp::client::{TcpClient, TcpClientState}; use embassy_net::tcp::client::{TcpClient, TcpClientState};
use embassy_net::StackResources; use embassy_net::StackResources;
use embassy_stm32::eth::generic_smi::GenericSMI; use embassy_stm32::eth::{Ethernet, GenericPhy, PacketQueue};
use embassy_stm32::eth::{Ethernet, PacketQueue};
use embassy_stm32::peripherals::ETH; use embassy_stm32::peripherals::ETH;
use embassy_stm32::rng::Rng; use embassy_stm32::rng::Rng;
use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config};
@ -24,7 +23,7 @@ bind_interrupts!(struct Irqs {
RNG => rng::InterruptHandler<peripherals::RNG>; RNG => rng::InterruptHandler<peripherals::RNG>;
}); });
type Device = Ethernet<'static, ETH, GenericSMI>; type Device = Ethernet<'static, ETH, GenericPhy>;
#[embassy_executor::task] #[embassy_executor::task]
async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! { async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! {
@ -81,7 +80,7 @@ async fn main(spawner: Spawner) -> ! {
p.PG13, p.PG13,
p.PB13, p.PB13,
p.PG11, p.PG11,
GenericSMI::new_auto(), GenericPhy::new_auto(),
mac_addr, mac_addr,
); );

View File

@ -7,8 +7,7 @@ use defmt::*;
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_net::tcp::client::{TcpClient, TcpClientState}; use embassy_net::tcp::client::{TcpClient, TcpClientState};
use embassy_net::StackResources; use embassy_net::StackResources;
use embassy_stm32::eth::generic_smi::GenericSMI; use embassy_stm32::eth::{Ethernet, GenericPhy, PacketQueue};
use embassy_stm32::eth::{Ethernet, PacketQueue};
use embassy_stm32::peripherals::ETH; use embassy_stm32::peripherals::ETH;
use embassy_stm32::rng::Rng; use embassy_stm32::rng::Rng;
use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config};
@ -24,7 +23,7 @@ bind_interrupts!(struct Irqs {
RNG => rng::InterruptHandler<peripherals::RNG>; RNG => rng::InterruptHandler<peripherals::RNG>;
}); });
type Device = Ethernet<'static, ETH, GenericSMI>; type Device = Ethernet<'static, ETH, GenericPhy>;
#[embassy_executor::task] #[embassy_executor::task]
async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! { async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! {
@ -86,7 +85,7 @@ async fn main(spawner: Spawner) -> ! {
p.PC2, p.PC2,
p.PE2, p.PE2,
p.PG11, p.PG11,
GenericSMI::new_auto(), GenericPhy::new_auto(),
mac_addr, mac_addr,
); );
info!("Device created"); info!("Device created");

View File

@ -7,8 +7,7 @@ mod common;
use common::*; use common::*;
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_net::StackResources; use embassy_net::StackResources;
use embassy_stm32::eth::generic_smi::GenericSMI; use embassy_stm32::eth::{Ethernet, GenericPhy, PacketQueue};
use embassy_stm32::eth::{Ethernet, PacketQueue};
use embassy_stm32::peripherals::ETH; use embassy_stm32::peripherals::ETH;
use embassy_stm32::rng::Rng; use embassy_stm32::rng::Rng;
use embassy_stm32::{bind_interrupts, eth, peripherals, rng}; use embassy_stm32::{bind_interrupts, eth, peripherals, rng};
@ -29,7 +28,7 @@ bind_interrupts!(struct Irqs {
RNG => rng::InterruptHandler<peripherals::RNG>; RNG => rng::InterruptHandler<peripherals::RNG>;
}); });
type Device = Ethernet<'static, ETH, GenericSMI>; type Device = Ethernet<'static, ETH, GenericPhy>;
#[embassy_executor::task] #[embassy_executor::task]
async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! { async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! {
@ -87,7 +86,7 @@ async fn main(spawner: Spawner) {
#[cfg(feature = "stm32h563zi")] #[cfg(feature = "stm32h563zi")]
p.PB15, p.PB15,
p.PG11, p.PG11,
GenericSMI::new_auto(), GenericPhy::new_auto(),
mac_addr, mac_addr,
); );