diff options
| author | Dario Nieuwenhuis <[email protected]> | 2022-02-10 21:38:03 +0100 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2022-02-10 21:38:03 +0100 |
| commit | b99ab3d5d9d8fdee135956dcbc2111b00abd1d72 (patch) | |
| tree | 53f3723e24ba49b98f0a792aa9835141ef56729e /embassy-stm32/src/eth | |
| parent | 9d682aa1fae81d9bb56bb41304828144b9a0d4a7 (diff) | |
stm32: Add standard crate-wide macros for pin/dma traits, switch all drivers to use them.
Diffstat (limited to 'embassy-stm32/src/eth')
| -rw-r--r-- | embassy-stm32/src/eth/mod.rs | 55 | ||||
| -rw-r--r-- | embassy-stm32/src/eth/v1c/mod.rs | 205 | ||||
| -rw-r--r-- | embassy-stm32/src/eth/v2/mod.rs | 199 |
3 files changed, 152 insertions, 307 deletions
diff --git a/embassy-stm32/src/eth/mod.rs b/embassy-stm32/src/eth/mod.rs index 664c19daa..cf145e393 100644 --- a/embassy-stm32/src/eth/mod.rs +++ b/embassy-stm32/src/eth/mod.rs | |||
| @@ -33,3 +33,58 @@ pub unsafe trait PHY { | |||
| 33 | /// Poll link to see if it is up and FD with 100Mbps | 33 | /// Poll link to see if it is up and FD with 100Mbps |
| 34 | fn poll_link<S: StationManagement>(sm: &mut S) -> bool; | 34 | fn poll_link<S: StationManagement>(sm: &mut S) -> bool; |
| 35 | } | 35 | } |
| 36 | |||
| 37 | pub(crate) mod sealed { | ||
| 38 | pub trait Instance { | ||
| 39 | fn regs() -> crate::pac::eth::Eth; | ||
| 40 | } | ||
| 41 | } | ||
| 42 | |||
| 43 | pub trait Instance: sealed::Instance + Send + 'static {} | ||
| 44 | |||
| 45 | impl sealed::Instance for crate::peripherals::ETH { | ||
| 46 | fn regs() -> crate::pac::eth::Eth { | ||
| 47 | crate::pac::ETH | ||
| 48 | } | ||
| 49 | } | ||
| 50 | impl Instance for crate::peripherals::ETH {} | ||
| 51 | |||
| 52 | pin_trait!(RefClkPin, Instance); | ||
| 53 | pin_trait!(MDIOPin, Instance); | ||
| 54 | pin_trait!(MDCPin, Instance); | ||
| 55 | pin_trait!(CRSPin, Instance); | ||
| 56 | pin_trait!(RXD0Pin, Instance); | ||
| 57 | pin_trait!(RXD1Pin, Instance); | ||
| 58 | pin_trait!(TXD0Pin, Instance); | ||
| 59 | pin_trait!(TXD1Pin, Instance); | ||
| 60 | pin_trait!(TXEnPin, Instance); | ||
| 61 | |||
| 62 | crate::pac::peripheral_pins!( | ||
| 63 | ($inst:ident, eth, ETH, $pin:ident, REF_CLK, $af:expr) => { | ||
| 64 | pin_trait_impl!(RefClkPin, $inst, $pin, $af); | ||
| 65 | }; | ||
| 66 | ($inst:ident, eth, ETH, $pin:ident, MDIO, $af:expr) => { | ||
| 67 | pin_trait_impl!(MDIOPin, $inst, $pin, $af); | ||
| 68 | }; | ||
| 69 | ($inst:ident, eth, ETH, $pin:ident, MDC, $af:expr) => { | ||
| 70 | pin_trait_impl!(MDCPin, $inst, $pin, $af); | ||
| 71 | }; | ||
| 72 | ($inst:ident, eth, ETH, $pin:ident, CRS_DV, $af:expr) => { | ||
| 73 | pin_trait_impl!(CRSPin, $inst, $pin, $af); | ||
| 74 | }; | ||
| 75 | ($inst:ident, eth, ETH, $pin:ident, RXD0, $af:expr) => { | ||
| 76 | pin_trait_impl!(RXD0Pin, $inst, $pin, $af); | ||
| 77 | }; | ||
| 78 | ($inst:ident, eth, ETH, $pin:ident, RXD1, $af:expr) => { | ||
| 79 | pin_trait_impl!(RXD1Pin, $inst, $pin, $af); | ||
| 80 | }; | ||
| 81 | ($inst:ident, eth, ETH, $pin:ident, TXD0, $af:expr) => { | ||
| 82 | pin_trait_impl!(TXD0Pin, $inst, $pin, $af); | ||
| 83 | }; | ||
| 84 | ($inst:ident, eth, ETH, $pin:ident, TXD1, $af:expr) => { | ||
| 85 | pin_trait_impl!(TXD1Pin, $inst, $pin, $af); | ||
| 86 | }; | ||
| 87 | ($inst:ident, eth, ETH, $pin:ident, TX_EN, $af:expr) => { | ||
| 88 | pin_trait_impl!(TXEnPin, $inst, $pin, $af); | ||
| 89 | }; | ||
| 90 | ); | ||
diff --git a/embassy-stm32/src/eth/v1c/mod.rs b/embassy-stm32/src/eth/v1c/mod.rs index 89815c71f..1927a9a26 100644 --- a/embassy-stm32/src/eth/v1c/mod.rs +++ b/embassy-stm32/src/eth/v1c/mod.rs | |||
| @@ -12,29 +12,31 @@ use embassy_net::{Device, DeviceCapabilities, LinkState, PacketBuf, MTU}; | |||
| 12 | 12 | ||
| 13 | use crate::gpio::sealed::Pin as __GpioPin; | 13 | use crate::gpio::sealed::Pin as __GpioPin; |
| 14 | use crate::gpio::Pin as GpioPin; | 14 | use crate::gpio::Pin as GpioPin; |
| 15 | use crate::gpio::{sealed::AFType::OutputPushPull, AnyPin}; | 15 | use crate::gpio::{sealed::AFType, AnyPin, Speed}; |
| 16 | use crate::pac::gpio::vals::Ospeedr; | 16 | use crate::pac::gpio::vals::Ospeedr; |
| 17 | use crate::pac::{ETH, RCC, SYSCFG}; | 17 | use crate::pac::{ETH, RCC, SYSCFG}; |
| 18 | use crate::peripherals; | ||
| 19 | 18 | ||
| 20 | mod descriptors; | 19 | mod descriptors; |
| 21 | mod rx_desc; | 20 | mod rx_desc; |
| 22 | mod tx_desc; | 21 | mod tx_desc; |
| 23 | 22 | ||
| 24 | use super::{StationManagement, PHY}; | 23 | use super::*; |
| 25 | use descriptors::DescriptorRing; | 24 | use descriptors::DescriptorRing; |
| 26 | use stm32_metapac::eth::vals::{ | 25 | use stm32_metapac::eth::vals::{ |
| 27 | Apcs, Cr, Dm, DmaomrSr, Fes, Ftf, Ifg, MbProgress, Mw, Pbl, Rsf, St, Tsf, | 26 | Apcs, Cr, Dm, DmaomrSr, Fes, Ftf, Ifg, MbProgress, Mw, Pbl, Rsf, St, Tsf, |
| 28 | }; | 27 | }; |
| 29 | 28 | ||
| 30 | pub struct State<'d, const TX: usize, const RX: usize>(StateStorage<Inner<'d, TX, RX>>); | 29 | pub struct State<'d, T: Instance, const TX: usize, const RX: usize>( |
| 31 | impl<'d, const TX: usize, const RX: usize> State<'d, TX, RX> { | 30 | StateStorage<Inner<'d, T, TX, RX>>, |
| 32 | pub const fn new() -> Self { | 31 | ); |
| 32 | impl<'d, T: Instance, const TX: usize, const RX: usize> State<'d, T, TX, RX> { | ||
| 33 | pub fn new() -> Self { | ||
| 33 | Self(StateStorage::new()) | 34 | Self(StateStorage::new()) |
| 34 | } | 35 | } |
| 35 | } | 36 | } |
| 36 | pub struct Ethernet<'d, P: PHY, const TX: usize, const RX: usize> { | 37 | |
| 37 | state: PeripheralMutex<'d, Inner<'d, TX, RX>>, | 38 | pub struct Ethernet<'d, T: Instance, P: PHY, const TX: usize, const RX: usize> { |
| 39 | state: PeripheralMutex<'d, Inner<'d, T, TX, RX>>, | ||
| 38 | pins: [AnyPin; 9], | 40 | pins: [AnyPin; 9], |
| 39 | _phy: P, | 41 | _phy: P, |
| 40 | clock_range: Cr, | 42 | clock_range: Cr, |
| @@ -42,21 +44,33 @@ pub struct Ethernet<'d, P: PHY, const TX: usize, const RX: usize> { | |||
| 42 | mac_addr: [u8; 6], | 44 | mac_addr: [u8; 6], |
| 43 | } | 45 | } |
| 44 | 46 | ||
| 45 | impl<'d, P: PHY, const TX: usize, const RX: usize> Ethernet<'d, P, TX, RX> { | 47 | macro_rules! config_pins { |
| 48 | ($($pin:ident),*) => { | ||
| 49 | // NOTE(unsafe) Exclusive access to the registers | ||
| 50 | critical_section::with(|_| unsafe { | ||
| 51 | $( | ||
| 52 | $pin.set_as_af($pin.af_num(), AFType::OutputPushPull); | ||
| 53 | $pin.set_speed(Speed::VeryHigh); | ||
| 54 | )* | ||
| 55 | }) | ||
| 56 | }; | ||
| 57 | } | ||
| 58 | |||
| 59 | impl<'d, T: Instance, P: PHY, const TX: usize, const RX: usize> Ethernet<'d, T, P, TX, RX> { | ||
| 46 | /// safety: the returned instance is not leak-safe | 60 | /// safety: the returned instance is not leak-safe |
| 47 | pub unsafe fn new( | 61 | pub unsafe fn new( |
| 48 | state: &'d mut State<'d, TX, RX>, | 62 | state: &'d mut State<'d, T, TX, RX>, |
| 49 | peri: impl Unborrow<Target = peripherals::ETH> + 'd, | 63 | peri: impl Unborrow<Target = T> + 'd, |
| 50 | interrupt: impl Unborrow<Target = crate::interrupt::ETH> + 'd, | 64 | interrupt: impl Unborrow<Target = crate::interrupt::ETH> + 'd, |
| 51 | ref_clk: impl Unborrow<Target = impl RefClkPin> + 'd, | 65 | ref_clk: impl Unborrow<Target = impl RefClkPin<T>> + 'd, |
| 52 | mdio: impl Unborrow<Target = impl MDIOPin> + 'd, | 66 | mdio: impl Unborrow<Target = impl MDIOPin<T>> + 'd, |
| 53 | mdc: impl Unborrow<Target = impl MDCPin> + 'd, | 67 | mdc: impl Unborrow<Target = impl MDCPin<T>> + 'd, |
| 54 | crs: impl Unborrow<Target = impl CRSPin> + 'd, | 68 | crs: impl Unborrow<Target = impl CRSPin<T>> + 'd, |
| 55 | rx_d0: impl Unborrow<Target = impl RXD0Pin> + 'd, | 69 | rx_d0: impl Unborrow<Target = impl RXD0Pin<T>> + 'd, |
| 56 | rx_d1: impl Unborrow<Target = impl RXD1Pin> + 'd, | 70 | rx_d1: impl Unborrow<Target = impl RXD1Pin<T>> + 'd, |
| 57 | tx_d0: impl Unborrow<Target = impl TXD0Pin> + 'd, | 71 | tx_d0: impl Unborrow<Target = impl TXD0Pin<T>> + 'd, |
| 58 | tx_d1: impl Unborrow<Target = impl TXD1Pin> + 'd, | 72 | tx_d1: impl Unborrow<Target = impl TXD1Pin<T>> + 'd, |
| 59 | tx_en: impl Unborrow<Target = impl TXEnPin> + 'd, | 73 | tx_en: impl Unborrow<Target = impl TXEnPin<T>> + 'd, |
| 60 | phy: P, | 74 | phy: P, |
| 61 | mac_addr: [u8; 6], | 75 | mac_addr: [u8; 6], |
| 62 | phy_addr: u8, | 76 | phy_addr: u8, |
| @@ -77,15 +91,7 @@ impl<'d, P: PHY, const TX: usize, const RX: usize> Ethernet<'d, P, TX, RX> { | |||
| 77 | SYSCFG.pmc().modify(|w| w.set_mii_rmii_sel(true)); | 91 | SYSCFG.pmc().modify(|w| w.set_mii_rmii_sel(true)); |
| 78 | }); | 92 | }); |
| 79 | 93 | ||
| 80 | ref_clk.configure(); | 94 | config_pins!(ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en); |
| 81 | mdio.configure(); | ||
| 82 | mdc.configure(); | ||
| 83 | crs.configure(); | ||
| 84 | rx_d0.configure(); | ||
| 85 | rx_d1.configure(); | ||
| 86 | tx_d0.configure(); | ||
| 87 | tx_d1.configure(); | ||
| 88 | tx_en.configure(); | ||
| 89 | 95 | ||
| 90 | // NOTE(unsafe) We are ourselves not leak-safe. | 96 | // NOTE(unsafe) We are ourselves not leak-safe. |
| 91 | let state = PeripheralMutex::new_unchecked(interrupt, &mut state.0, || Inner::new(peri)); | 97 | let state = PeripheralMutex::new_unchecked(interrupt, &mut state.0, || Inner::new(peri)); |
| @@ -204,8 +210,8 @@ impl<'d, P: PHY, const TX: usize, const RX: usize> Ethernet<'d, P, TX, RX> { | |||
| 204 | } | 210 | } |
| 205 | } | 211 | } |
| 206 | 212 | ||
| 207 | unsafe impl<'d, P: PHY, const TX: usize, const RX: usize> StationManagement | 213 | unsafe impl<'d, T: Instance, P: PHY, const TX: usize, const RX: usize> StationManagement |
| 208 | for Ethernet<'d, P, TX, RX> | 214 | for Ethernet<'d, T, P, TX, RX> |
| 209 | { | 215 | { |
| 210 | fn smi_read(&mut self, reg: u8) -> u16 { | 216 | fn smi_read(&mut self, reg: u8) -> u16 { |
| 211 | // NOTE(unsafe) These registers aren't used in the interrupt and we have `&mut self` | 217 | // NOTE(unsafe) These registers aren't used in the interrupt and we have `&mut self` |
| @@ -242,7 +248,9 @@ unsafe impl<'d, P: PHY, const TX: usize, const RX: usize> StationManagement | |||
| 242 | } | 248 | } |
| 243 | } | 249 | } |
| 244 | 250 | ||
| 245 | impl<'d, P: PHY, const TX: usize, const RX: usize> Device for Ethernet<'d, P, TX, RX> { | 251 | impl<'d, T: Instance, P: PHY, const TX: usize, const RX: usize> Device |
| 252 | for Ethernet<'d, T, P, TX, RX> | ||
| 253 | { | ||
| 246 | fn is_transmit_ready(&mut self) -> bool { | 254 | fn is_transmit_ready(&mut self) -> bool { |
| 247 | self.state.with(|s| s.desc_ring.tx.available()) | 255 | self.state.with(|s| s.desc_ring.tx.available()) |
| 248 | } | 256 | } |
| @@ -279,7 +287,9 @@ impl<'d, P: PHY, const TX: usize, const RX: usize> Device for Ethernet<'d, P, TX | |||
| 279 | } | 287 | } |
| 280 | } | 288 | } |
| 281 | 289 | ||
| 282 | impl<'d, P: PHY, const TX: usize, const RX: usize> Drop for Ethernet<'d, P, TX, RX> { | 290 | impl<'d, T: Instance, P: PHY, const TX: usize, const RX: usize> Drop |
| 291 | for Ethernet<'d, T, P, TX, RX> | ||
| 292 | { | ||
| 283 | fn drop(&mut self) { | 293 | fn drop(&mut self) { |
| 284 | // NOTE(unsafe) We have `&mut self` and the interrupt doesn't use this registers | 294 | // NOTE(unsafe) We have `&mut self` and the interrupt doesn't use this registers |
| 285 | unsafe { | 295 | unsafe { |
| @@ -312,13 +322,13 @@ impl<'d, P: PHY, const TX: usize, const RX: usize> Drop for Ethernet<'d, P, TX, | |||
| 312 | 322 | ||
| 313 | //---------------------------------------------------------------------- | 323 | //---------------------------------------------------------------------- |
| 314 | 324 | ||
| 315 | struct Inner<'d, const TX: usize, const RX: usize> { | 325 | struct Inner<'d, T: Instance, const TX: usize, const RX: usize> { |
| 316 | _peri: PhantomData<&'d mut peripherals::ETH>, | 326 | _peri: PhantomData<&'d mut T>, |
| 317 | desc_ring: DescriptorRing<TX, RX>, | 327 | desc_ring: DescriptorRing<TX, RX>, |
| 318 | } | 328 | } |
| 319 | 329 | ||
| 320 | impl<'d, const TX: usize, const RX: usize> Inner<'d, TX, RX> { | 330 | impl<'d, T: Instance, const TX: usize, const RX: usize> Inner<'d, T, TX, RX> { |
| 321 | pub fn new(_peri: impl Unborrow<Target = peripherals::ETH> + 'd) -> Self { | 331 | pub fn new(_peri: impl Unborrow<Target = T> + 'd) -> Self { |
| 322 | Self { | 332 | Self { |
| 323 | _peri: PhantomData, | 333 | _peri: PhantomData, |
| 324 | desc_ring: DescriptorRing::new(), | 334 | desc_ring: DescriptorRing::new(), |
| @@ -326,7 +336,7 @@ impl<'d, const TX: usize, const RX: usize> Inner<'d, TX, RX> { | |||
| 326 | } | 336 | } |
| 327 | } | 337 | } |
| 328 | 338 | ||
| 329 | impl<'d, const TX: usize, const RX: usize> PeripheralState for Inner<'d, TX, RX> { | 339 | impl<'d, T: Instance, const TX: usize, const RX: usize> PeripheralState for Inner<'d, T, TX, RX> { |
| 330 | type Interrupt = crate::interrupt::ETH; | 340 | type Interrupt = crate::interrupt::ETH; |
| 331 | 341 | ||
| 332 | fn on_interrupt(&mut self) { | 342 | fn on_interrupt(&mut self) { |
| @@ -351,123 +361,4 @@ impl<'d, const TX: usize, const RX: usize> PeripheralState for Inner<'d, TX, RX> | |||
| 351 | } | 361 | } |
| 352 | } | 362 | } |
| 353 | 363 | ||
| 354 | mod sealed { | ||
| 355 | use super::*; | ||
| 356 | |||
| 357 | pub trait RefClkPin: GpioPin { | ||
| 358 | fn configure(&mut self); | ||
| 359 | } | ||
| 360 | |||
| 361 | pub trait MDIOPin: GpioPin { | ||
| 362 | fn configure(&mut self); | ||
| 363 | } | ||
| 364 | |||
| 365 | pub trait MDCPin: GpioPin { | ||
| 366 | fn configure(&mut self); | ||
| 367 | } | ||
| 368 | |||
| 369 | pub trait CRSPin: GpioPin { | ||
| 370 | fn configure(&mut self); | ||
| 371 | } | ||
| 372 | |||
| 373 | pub trait RXD0Pin: GpioPin { | ||
| 374 | fn configure(&mut self); | ||
| 375 | } | ||
| 376 | |||
| 377 | pub trait RXD1Pin: GpioPin { | ||
| 378 | fn configure(&mut self); | ||
| 379 | } | ||
| 380 | |||
| 381 | pub trait TXD0Pin: GpioPin { | ||
| 382 | fn configure(&mut self); | ||
| 383 | } | ||
| 384 | |||
| 385 | pub trait TXD1Pin: GpioPin { | ||
| 386 | fn configure(&mut self); | ||
| 387 | } | ||
| 388 | |||
| 389 | pub trait TXEnPin: GpioPin { | ||
| 390 | fn configure(&mut self); | ||
| 391 | } | ||
| 392 | } | ||
| 393 | |||
| 394 | pub trait RefClkPin: sealed::RefClkPin + 'static {} | ||
| 395 | |||
| 396 | pub trait MDIOPin: sealed::MDIOPin + 'static {} | ||
| 397 | |||
| 398 | pub trait MDCPin: sealed::MDCPin + 'static {} | ||
| 399 | |||
| 400 | pub trait CRSPin: sealed::CRSPin + 'static {} | ||
| 401 | |||
| 402 | pub trait RXD0Pin: sealed::RXD0Pin + 'static {} | ||
| 403 | |||
| 404 | pub trait RXD1Pin: sealed::RXD1Pin + 'static {} | ||
| 405 | |||
| 406 | pub trait TXD0Pin: sealed::TXD0Pin + 'static {} | ||
| 407 | |||
| 408 | pub trait TXD1Pin: sealed::TXD1Pin + 'static {} | ||
| 409 | |||
| 410 | pub trait TXEnPin: sealed::TXEnPin + 'static {} | ||
| 411 | |||
| 412 | static WAKER: AtomicWaker = AtomicWaker::new(); | 364 | static WAKER: AtomicWaker = AtomicWaker::new(); |
| 413 | |||
| 414 | macro_rules! impl_pin { | ||
| 415 | ($pin:ident, $signal:ident, $af:expr) => { | ||
| 416 | impl sealed::$signal for peripherals::$pin { | ||
| 417 | fn configure(&mut self) { | ||
| 418 | // NOTE(unsafe) Exclusive access to the registers | ||
| 419 | critical_section::with(|_| unsafe { | ||
| 420 | self.set_as_af($af, OutputPushPull); | ||
| 421 | self.block() | ||
| 422 | .ospeedr() | ||
| 423 | .modify(|w| w.set_ospeedr(self.pin() as usize, Ospeedr::VERYHIGHSPEED)); | ||
| 424 | }) | ||
| 425 | } | ||
| 426 | } | ||
| 427 | |||
| 428 | impl $signal for peripherals::$pin {} | ||
| 429 | }; | ||
| 430 | } | ||
| 431 | // impl sealed::RefClkPin for peripherals::PA1 { | ||
| 432 | // fn configure(&mut self) { | ||
| 433 | // // NOTE(unsafe) Exclusive access to the registers | ||
| 434 | // critical_section::with(|_| unsafe { | ||
| 435 | // self.set_as_af(11, OutputPushPull); | ||
| 436 | // self.block() | ||
| 437 | // .ospeedr() | ||
| 438 | // .modify(|w| w.set_ospeedr(self.pin() as usize, Ospeedr::VERYHIGHSPEED)); | ||
| 439 | // }) | ||
| 440 | // } | ||
| 441 | // } | ||
| 442 | |||
| 443 | // impl RefClkPin for peripherals::PA1 {} | ||
| 444 | |||
| 445 | crate::pac::peripheral_pins!( | ||
| 446 | ($inst:ident, eth, ETH, $pin:ident, REF_CLK, $af:expr) => { | ||
| 447 | impl_pin!($pin, RefClkPin, $af); | ||
| 448 | }; | ||
| 449 | ($inst:ident, eth, ETH, $pin:ident, MDIO, $af:expr) => { | ||
| 450 | impl_pin!($pin, MDIOPin, $af); | ||
| 451 | }; | ||
| 452 | ($inst:ident, eth, ETH, $pin:ident, MDC, $af:expr) => { | ||
| 453 | impl_pin!($pin, MDCPin, $af); | ||
| 454 | }; | ||
| 455 | ($inst:ident, eth, ETH, $pin:ident, CRS_DV, $af:expr) => { | ||
| 456 | impl_pin!($pin, CRSPin, $af); | ||
| 457 | }; | ||
| 458 | ($inst:ident, eth, ETH, $pin:ident, RXD0, $af:expr) => { | ||
| 459 | impl_pin!($pin, RXD0Pin, $af); | ||
| 460 | }; | ||
| 461 | ($inst:ident, eth, ETH, $pin:ident, RXD1, $af:expr) => { | ||
| 462 | impl_pin!($pin, RXD1Pin, $af); | ||
| 463 | }; | ||
| 464 | ($inst:ident, eth, ETH, $pin:ident, TXD0, $af:expr) => { | ||
| 465 | impl_pin!($pin, TXD0Pin, $af); | ||
| 466 | }; | ||
| 467 | ($inst:ident, eth, ETH, $pin:ident, TXD1, $af:expr) => { | ||
| 468 | impl_pin!($pin, TXD1Pin, $af); | ||
| 469 | }; | ||
| 470 | ($inst:ident, eth, ETH, $pin:ident, TX_EN, $af:expr) => { | ||
| 471 | impl_pin!($pin, TXEnPin, $af); | ||
| 472 | }; | ||
| 473 | ); | ||
diff --git a/embassy-stm32/src/eth/v2/mod.rs b/embassy-stm32/src/eth/v2/mod.rs index 2f2dc4f38..ad81b1d51 100644 --- a/embassy-stm32/src/eth/v2/mod.rs +++ b/embassy-stm32/src/eth/v2/mod.rs | |||
| @@ -8,25 +8,24 @@ use embassy_hal_common::peripheral::{PeripheralMutex, PeripheralState, StateStor | |||
| 8 | use embassy_hal_common::unborrow; | 8 | use embassy_hal_common::unborrow; |
| 9 | use embassy_net::{Device, DeviceCapabilities, LinkState, PacketBuf, MTU}; | 9 | use embassy_net::{Device, DeviceCapabilities, LinkState, PacketBuf, MTU}; |
| 10 | 10 | ||
| 11 | use crate::gpio::sealed::Pin as __GpioPin; | 11 | use crate::gpio::sealed::Pin as _; |
| 12 | use crate::gpio::Pin as GpioPin; | 12 | use crate::gpio::{sealed::AFType, AnyPin, Speed}; |
| 13 | use crate::gpio::{sealed::AFType::OutputPushPull, AnyPin}; | ||
| 14 | use crate::pac::gpio::vals::Ospeedr; | ||
| 15 | use crate::pac::{ETH, RCC, SYSCFG}; | 13 | use crate::pac::{ETH, RCC, SYSCFG}; |
| 16 | use crate::peripherals; | ||
| 17 | 14 | ||
| 18 | mod descriptors; | 15 | mod descriptors; |
| 19 | use super::{StationManagement, PHY}; | 16 | use super::*; |
| 20 | use descriptors::DescriptorRing; | 17 | use descriptors::DescriptorRing; |
| 21 | 18 | ||
| 22 | pub struct State<'d, const TX: usize, const RX: usize>(StateStorage<Inner<'d, TX, RX>>); | 19 | pub struct State<'d, T: Instance, const TX: usize, const RX: usize>( |
| 23 | impl<'d, const TX: usize, const RX: usize> State<'d, TX, RX> { | 20 | StateStorage<Inner<'d, T, TX, RX>>, |
| 24 | pub const fn new() -> Self { | 21 | ); |
| 22 | impl<'d, T: Instance, const TX: usize, const RX: usize> State<'d, T, TX, RX> { | ||
| 23 | pub fn new() -> Self { | ||
| 25 | Self(StateStorage::new()) | 24 | Self(StateStorage::new()) |
| 26 | } | 25 | } |
| 27 | } | 26 | } |
| 28 | pub struct Ethernet<'d, P: PHY, const TX: usize, const RX: usize> { | 27 | pub struct Ethernet<'d, T: Instance, P: PHY, const TX: usize, const RX: usize> { |
| 29 | state: PeripheralMutex<'d, Inner<'d, TX, RX>>, | 28 | state: PeripheralMutex<'d, Inner<'d, T, TX, RX>>, |
| 30 | pins: [AnyPin; 9], | 29 | pins: [AnyPin; 9], |
| 31 | _phy: P, | 30 | _phy: P, |
| 32 | clock_range: u8, | 31 | clock_range: u8, |
| @@ -34,21 +33,33 @@ pub struct Ethernet<'d, P: PHY, const TX: usize, const RX: usize> { | |||
| 34 | mac_addr: [u8; 6], | 33 | mac_addr: [u8; 6], |
| 35 | } | 34 | } |
| 36 | 35 | ||
| 37 | impl<'d, P: PHY, const TX: usize, const RX: usize> Ethernet<'d, P, TX, RX> { | 36 | macro_rules! config_pins { |
| 37 | ($($pin:ident),*) => { | ||
| 38 | // NOTE(unsafe) Exclusive access to the registers | ||
| 39 | critical_section::with(|_| unsafe { | ||
| 40 | $( | ||
| 41 | $pin.set_as_af($pin.af_num(), AFType::OutputPushPull); | ||
| 42 | $pin.set_speed(Speed::VeryHigh); | ||
| 43 | )* | ||
| 44 | }) | ||
| 45 | }; | ||
| 46 | } | ||
| 47 | |||
| 48 | impl<'d, T: Instance, P: PHY, const TX: usize, const RX: usize> Ethernet<'d, T, P, TX, RX> { | ||
| 38 | /// safety: the returned instance is not leak-safe | 49 | /// safety: the returned instance is not leak-safe |
| 39 | pub unsafe fn new( | 50 | pub unsafe fn new( |
| 40 | state: &'d mut State<'d, TX, RX>, | 51 | state: &'d mut State<'d, T, TX, RX>, |
| 41 | peri: impl Unborrow<Target = peripherals::ETH> + 'd, | 52 | peri: impl Unborrow<Target = T> + 'd, |
| 42 | interrupt: impl Unborrow<Target = crate::interrupt::ETH> + 'd, | 53 | interrupt: impl Unborrow<Target = crate::interrupt::ETH> + 'd, |
| 43 | ref_clk: impl Unborrow<Target = impl RefClkPin> + 'd, | 54 | ref_clk: impl Unborrow<Target = impl RefClkPin<T>> + 'd, |
| 44 | mdio: impl Unborrow<Target = impl MDIOPin> + 'd, | 55 | mdio: impl Unborrow<Target = impl MDIOPin<T>> + 'd, |
| 45 | mdc: impl Unborrow<Target = impl MDCPin> + 'd, | 56 | mdc: impl Unborrow<Target = impl MDCPin<T>> + 'd, |
| 46 | crs: impl Unborrow<Target = impl CRSPin> + 'd, | 57 | crs: impl Unborrow<Target = impl CRSPin<T>> + 'd, |
| 47 | rx_d0: impl Unborrow<Target = impl RXD0Pin> + 'd, | 58 | rx_d0: impl Unborrow<Target = impl RXD0Pin<T>> + 'd, |
| 48 | rx_d1: impl Unborrow<Target = impl RXD1Pin> + 'd, | 59 | rx_d1: impl Unborrow<Target = impl RXD1Pin<T>> + 'd, |
| 49 | tx_d0: impl Unborrow<Target = impl TXD0Pin> + 'd, | 60 | tx_d0: impl Unborrow<Target = impl TXD0Pin<T>> + 'd, |
| 50 | tx_d1: impl Unborrow<Target = impl TXD1Pin> + 'd, | 61 | tx_d1: impl Unborrow<Target = impl TXD1Pin<T>> + 'd, |
| 51 | tx_en: impl Unborrow<Target = impl TXEnPin> + 'd, | 62 | tx_en: impl Unborrow<Target = impl TXEnPin<T>> + 'd, |
| 52 | phy: P, | 63 | phy: P, |
| 53 | mac_addr: [u8; 6], | 64 | mac_addr: [u8; 6], |
| 54 | phy_addr: u8, | 65 | phy_addr: u8, |
| @@ -69,15 +80,7 @@ impl<'d, P: PHY, const TX: usize, const RX: usize> Ethernet<'d, P, TX, RX> { | |||
| 69 | SYSCFG.pmcr().modify(|w| w.set_epis(0b100)); | 80 | SYSCFG.pmcr().modify(|w| w.set_epis(0b100)); |
| 70 | }); | 81 | }); |
| 71 | 82 | ||
| 72 | ref_clk.configure(); | 83 | config_pins!(ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en); |
| 73 | mdio.configure(); | ||
| 74 | mdc.configure(); | ||
| 75 | crs.configure(); | ||
| 76 | rx_d0.configure(); | ||
| 77 | rx_d1.configure(); | ||
| 78 | tx_d0.configure(); | ||
| 79 | tx_d1.configure(); | ||
| 80 | tx_en.configure(); | ||
| 81 | 84 | ||
| 82 | // NOTE(unsafe) We are ourselves not leak-safe. | 85 | // NOTE(unsafe) We are ourselves not leak-safe. |
| 83 | let state = PeripheralMutex::new_unchecked(interrupt, &mut state.0, || Inner::new(peri)); | 86 | let state = PeripheralMutex::new_unchecked(interrupt, &mut state.0, || Inner::new(peri)); |
| @@ -193,8 +196,8 @@ impl<'d, P: PHY, const TX: usize, const RX: usize> Ethernet<'d, P, TX, RX> { | |||
| 193 | } | 196 | } |
| 194 | } | 197 | } |
| 195 | 198 | ||
| 196 | unsafe impl<'d, P: PHY, const TX: usize, const RX: usize> StationManagement | 199 | unsafe impl<'d, T: Instance, P: PHY, const TX: usize, const RX: usize> StationManagement |
| 197 | for Ethernet<'d, P, TX, RX> | 200 | for Ethernet<'d, T, P, TX, RX> |
| 198 | { | 201 | { |
| 199 | fn smi_read(&mut self, reg: u8) -> u16 { | 202 | fn smi_read(&mut self, reg: u8) -> u16 { |
| 200 | // NOTE(unsafe) These registers aren't used in the interrupt and we have `&mut self` | 203 | // NOTE(unsafe) These registers aren't used in the interrupt and we have `&mut self` |
| @@ -231,7 +234,9 @@ unsafe impl<'d, P: PHY, const TX: usize, const RX: usize> StationManagement | |||
| 231 | } | 234 | } |
| 232 | } | 235 | } |
| 233 | 236 | ||
| 234 | impl<'d, P: PHY, const TX: usize, const RX: usize> Device for Ethernet<'d, P, TX, RX> { | 237 | impl<'d, T: Instance, P: PHY, const TX: usize, const RX: usize> Device |
| 238 | for Ethernet<'d, T, P, TX, RX> | ||
| 239 | { | ||
| 235 | fn is_transmit_ready(&mut self) -> bool { | 240 | fn is_transmit_ready(&mut self) -> bool { |
| 236 | self.state.with(|s| s.desc_ring.tx.available()) | 241 | self.state.with(|s| s.desc_ring.tx.available()) |
| 237 | } | 242 | } |
| @@ -268,7 +273,9 @@ impl<'d, P: PHY, const TX: usize, const RX: usize> Device for Ethernet<'d, P, TX | |||
| 268 | } | 273 | } |
| 269 | } | 274 | } |
| 270 | 275 | ||
| 271 | impl<'d, P: PHY, const TX: usize, const RX: usize> Drop for Ethernet<'d, P, TX, RX> { | 276 | impl<'d, T: Instance, P: PHY, const TX: usize, const RX: usize> Drop |
| 277 | for Ethernet<'d, T, P, TX, RX> | ||
| 278 | { | ||
| 272 | fn drop(&mut self) { | 279 | fn drop(&mut self) { |
| 273 | // NOTE(unsafe) We have `&mut self` and the interrupt doesn't use this registers | 280 | // NOTE(unsafe) We have `&mut self` and the interrupt doesn't use this registers |
| 274 | unsafe { | 281 | unsafe { |
| @@ -301,9 +308,7 @@ impl<'d, P: PHY, const TX: usize, const RX: usize> Drop for Ethernet<'d, P, TX, | |||
| 301 | // NOTE(unsafe) Exclusive access to the regs | 308 | // NOTE(unsafe) Exclusive access to the regs |
| 302 | critical_section::with(|_| unsafe { | 309 | critical_section::with(|_| unsafe { |
| 303 | pin.set_as_analog(); | 310 | pin.set_as_analog(); |
| 304 | pin.block() | 311 | pin.set_speed(Speed::Low); |
| 305 | .ospeedr() | ||
| 306 | .modify(|w| w.set_ospeedr(pin.pin() as usize, Ospeedr::LOWSPEED)); | ||
| 307 | }) | 312 | }) |
| 308 | } | 313 | } |
| 309 | } | 314 | } |
| @@ -311,13 +316,13 @@ impl<'d, P: PHY, const TX: usize, const RX: usize> Drop for Ethernet<'d, P, TX, | |||
| 311 | 316 | ||
| 312 | //---------------------------------------------------------------------- | 317 | //---------------------------------------------------------------------- |
| 313 | 318 | ||
| 314 | struct Inner<'d, const TX: usize, const RX: usize> { | 319 | struct Inner<'d, T: Instance, const TX: usize, const RX: usize> { |
| 315 | _peri: PhantomData<&'d mut peripherals::ETH>, | 320 | _peri: PhantomData<&'d mut T>, |
| 316 | desc_ring: DescriptorRing<TX, RX>, | 321 | desc_ring: DescriptorRing<TX, RX>, |
| 317 | } | 322 | } |
| 318 | 323 | ||
| 319 | impl<'d, const TX: usize, const RX: usize> Inner<'d, TX, RX> { | 324 | impl<'d, T: Instance, const TX: usize, const RX: usize> Inner<'d, T, TX, RX> { |
| 320 | pub fn new(_peri: impl Unborrow<Target = peripherals::ETH> + 'd) -> Self { | 325 | pub fn new(_peri: impl Unborrow<Target = T> + 'd) -> Self { |
| 321 | Self { | 326 | Self { |
| 322 | _peri: PhantomData, | 327 | _peri: PhantomData, |
| 323 | desc_ring: DescriptorRing::new(), | 328 | desc_ring: DescriptorRing::new(), |
| @@ -325,7 +330,7 @@ impl<'d, const TX: usize, const RX: usize> Inner<'d, TX, RX> { | |||
| 325 | } | 330 | } |
| 326 | } | 331 | } |
| 327 | 332 | ||
| 328 | impl<'d, const TX: usize, const RX: usize> PeripheralState for Inner<'d, TX, RX> { | 333 | impl<'d, T: Instance, const TX: usize, const RX: usize> PeripheralState for Inner<'d, T, TX, RX> { |
| 329 | type Interrupt = crate::interrupt::ETH; | 334 | type Interrupt = crate::interrupt::ETH; |
| 330 | 335 | ||
| 331 | fn on_interrupt(&mut self) { | 336 | fn on_interrupt(&mut self) { |
| @@ -350,110 +355,4 @@ impl<'d, const TX: usize, const RX: usize> PeripheralState for Inner<'d, TX, RX> | |||
| 350 | } | 355 | } |
| 351 | } | 356 | } |
| 352 | 357 | ||
| 353 | mod sealed { | ||
| 354 | use super::*; | ||
| 355 | |||
| 356 | pub trait RefClkPin: GpioPin { | ||
| 357 | fn configure(&mut self); | ||
| 358 | } | ||
| 359 | |||
| 360 | pub trait MDIOPin: GpioPin { | ||
| 361 | fn configure(&mut self); | ||
| 362 | } | ||
| 363 | |||
| 364 | pub trait MDCPin: GpioPin { | ||
| 365 | fn configure(&mut self); | ||
| 366 | } | ||
| 367 | |||
| 368 | pub trait CRSPin: GpioPin { | ||
| 369 | fn configure(&mut self); | ||
| 370 | } | ||
| 371 | |||
| 372 | pub trait RXD0Pin: GpioPin { | ||
| 373 | fn configure(&mut self); | ||
| 374 | } | ||
| 375 | |||
| 376 | pub trait RXD1Pin: GpioPin { | ||
| 377 | fn configure(&mut self); | ||
| 378 | } | ||
| 379 | |||
| 380 | pub trait TXD0Pin: GpioPin { | ||
| 381 | fn configure(&mut self); | ||
| 382 | } | ||
| 383 | |||
| 384 | pub trait TXD1Pin: GpioPin { | ||
| 385 | fn configure(&mut self); | ||
| 386 | } | ||
| 387 | |||
| 388 | pub trait TXEnPin: GpioPin { | ||
| 389 | fn configure(&mut self); | ||
| 390 | } | ||
| 391 | } | ||
| 392 | |||
| 393 | pub trait RefClkPin: sealed::RefClkPin + 'static {} | ||
| 394 | |||
| 395 | pub trait MDIOPin: sealed::MDIOPin + 'static {} | ||
| 396 | |||
| 397 | pub trait MDCPin: sealed::MDCPin + 'static {} | ||
| 398 | |||
| 399 | pub trait CRSPin: sealed::CRSPin + 'static {} | ||
| 400 | |||
| 401 | pub trait RXD0Pin: sealed::RXD0Pin + 'static {} | ||
| 402 | |||
| 403 | pub trait RXD1Pin: sealed::RXD1Pin + 'static {} | ||
| 404 | |||
| 405 | pub trait TXD0Pin: sealed::TXD0Pin + 'static {} | ||
| 406 | |||
| 407 | pub trait TXD1Pin: sealed::TXD1Pin + 'static {} | ||
| 408 | |||
| 409 | pub trait TXEnPin: sealed::TXEnPin + 'static {} | ||
| 410 | |||
| 411 | static WAKER: AtomicWaker = AtomicWaker::new(); | 358 | static WAKER: AtomicWaker = AtomicWaker::new(); |
| 412 | |||
| 413 | macro_rules! impl_pin { | ||
| 414 | ($pin:ident, $signal:ident, $af:expr) => { | ||
| 415 | impl sealed::$signal for peripherals::$pin { | ||
| 416 | fn configure(&mut self) { | ||
| 417 | // NOTE(unsafe) Exclusive access to the registers | ||
| 418 | critical_section::with(|_| unsafe { | ||
| 419 | self.set_as_af($af, OutputPushPull); | ||
| 420 | self.block() | ||
| 421 | .ospeedr() | ||
| 422 | .modify(|w| w.set_ospeedr(self.pin() as usize, Ospeedr::VERYHIGHSPEED)); | ||
| 423 | }) | ||
| 424 | } | ||
| 425 | } | ||
| 426 | |||
| 427 | impl $signal for peripherals::$pin {} | ||
| 428 | }; | ||
| 429 | } | ||
| 430 | |||
| 431 | crate::pac::peripheral_pins!( | ||
| 432 | ($inst:ident, eth, ETH, $pin:ident, REF_CLK, $af:expr) => { | ||
| 433 | impl_pin!($pin, RefClkPin, $af); | ||
| 434 | }; | ||
| 435 | ($inst:ident, eth, ETH, $pin:ident, MDIO, $af:expr) => { | ||
| 436 | impl_pin!($pin, MDIOPin, $af); | ||
| 437 | }; | ||
| 438 | ($inst:ident, eth, ETH, $pin:ident, MDC, $af:expr) => { | ||
| 439 | impl_pin!($pin, MDCPin, $af); | ||
| 440 | }; | ||
| 441 | ($inst:ident, eth, ETH, $pin:ident, CRS_DV, $af:expr) => { | ||
| 442 | impl_pin!($pin, CRSPin, $af); | ||
| 443 | }; | ||
| 444 | ($inst:ident, eth, ETH, $pin:ident, RXD0, $af:expr) => { | ||
| 445 | impl_pin!($pin, RXD0Pin, $af); | ||
| 446 | }; | ||
| 447 | ($inst:ident, eth, ETH, $pin:ident, RXD1, $af:expr) => { | ||
| 448 | impl_pin!($pin, RXD1Pin, $af); | ||
| 449 | }; | ||
| 450 | ($inst:ident, eth, ETH, $pin:ident, TXD0, $af:expr) => { | ||
| 451 | impl_pin!($pin, TXD0Pin, $af); | ||
| 452 | }; | ||
| 453 | ($inst:ident, eth, ETH, $pin:ident, TXD1, $af:expr) => { | ||
| 454 | impl_pin!($pin, TXD1Pin, $af); | ||
| 455 | }; | ||
| 456 | ($inst:ident, eth, ETH, $pin:ident, TX_EN, $af:expr) => { | ||
| 457 | impl_pin!($pin, TXEnPin, $af); | ||
| 458 | }; | ||
| 459 | ); | ||
