aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/eth
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2022-02-10 21:38:03 +0100
committerDario Nieuwenhuis <[email protected]>2022-02-10 21:38:03 +0100
commitb99ab3d5d9d8fdee135956dcbc2111b00abd1d72 (patch)
tree53f3723e24ba49b98f0a792aa9835141ef56729e /embassy-stm32/src/eth
parent9d682aa1fae81d9bb56bb41304828144b9a0d4a7 (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.rs55
-rw-r--r--embassy-stm32/src/eth/v1c/mod.rs205
-rw-r--r--embassy-stm32/src/eth/v2/mod.rs199
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
37pub(crate) mod sealed {
38 pub trait Instance {
39 fn regs() -> crate::pac::eth::Eth;
40 }
41}
42
43pub trait Instance: sealed::Instance + Send + 'static {}
44
45impl sealed::Instance for crate::peripherals::ETH {
46 fn regs() -> crate::pac::eth::Eth {
47 crate::pac::ETH
48 }
49}
50impl Instance for crate::peripherals::ETH {}
51
52pin_trait!(RefClkPin, Instance);
53pin_trait!(MDIOPin, Instance);
54pin_trait!(MDCPin, Instance);
55pin_trait!(CRSPin, Instance);
56pin_trait!(RXD0Pin, Instance);
57pin_trait!(RXD1Pin, Instance);
58pin_trait!(TXD0Pin, Instance);
59pin_trait!(TXD1Pin, Instance);
60pin_trait!(TXEnPin, Instance);
61
62crate::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
13use crate::gpio::sealed::Pin as __GpioPin; 13use crate::gpio::sealed::Pin as __GpioPin;
14use crate::gpio::Pin as GpioPin; 14use crate::gpio::Pin as GpioPin;
15use crate::gpio::{sealed::AFType::OutputPushPull, AnyPin}; 15use crate::gpio::{sealed::AFType, AnyPin, Speed};
16use crate::pac::gpio::vals::Ospeedr; 16use crate::pac::gpio::vals::Ospeedr;
17use crate::pac::{ETH, RCC, SYSCFG}; 17use crate::pac::{ETH, RCC, SYSCFG};
18use crate::peripherals;
19 18
20mod descriptors; 19mod descriptors;
21mod rx_desc; 20mod rx_desc;
22mod tx_desc; 21mod tx_desc;
23 22
24use super::{StationManagement, PHY}; 23use super::*;
25use descriptors::DescriptorRing; 24use descriptors::DescriptorRing;
26use stm32_metapac::eth::vals::{ 25use 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
30pub struct State<'d, const TX: usize, const RX: usize>(StateStorage<Inner<'d, TX, RX>>); 29pub struct State<'d, T: Instance, const TX: usize, const RX: usize>(
31impl<'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);
32impl<'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}
36pub struct Ethernet<'d, P: PHY, const TX: usize, const RX: usize> { 37
37 state: PeripheralMutex<'d, Inner<'d, TX, RX>>, 38pub 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
45impl<'d, P: PHY, const TX: usize, const RX: usize> Ethernet<'d, P, TX, RX> { 47macro_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
59impl<'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
207unsafe impl<'d, P: PHY, const TX: usize, const RX: usize> StationManagement 213unsafe 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
245impl<'d, P: PHY, const TX: usize, const RX: usize> Device for Ethernet<'d, P, TX, RX> { 251impl<'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
282impl<'d, P: PHY, const TX: usize, const RX: usize> Drop for Ethernet<'d, P, TX, RX> { 290impl<'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
315struct Inner<'d, const TX: usize, const RX: usize> { 325struct 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
320impl<'d, const TX: usize, const RX: usize> Inner<'d, TX, RX> { 330impl<'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
329impl<'d, const TX: usize, const RX: usize> PeripheralState for Inner<'d, TX, RX> { 339impl<'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
354mod 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
394pub trait RefClkPin: sealed::RefClkPin + 'static {}
395
396pub trait MDIOPin: sealed::MDIOPin + 'static {}
397
398pub trait MDCPin: sealed::MDCPin + 'static {}
399
400pub trait CRSPin: sealed::CRSPin + 'static {}
401
402pub trait RXD0Pin: sealed::RXD0Pin + 'static {}
403
404pub trait RXD1Pin: sealed::RXD1Pin + 'static {}
405
406pub trait TXD0Pin: sealed::TXD0Pin + 'static {}
407
408pub trait TXD1Pin: sealed::TXD1Pin + 'static {}
409
410pub trait TXEnPin: sealed::TXEnPin + 'static {}
411
412static WAKER: AtomicWaker = AtomicWaker::new(); 364static WAKER: AtomicWaker = AtomicWaker::new();
413
414macro_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
445crate::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
8use embassy_hal_common::unborrow; 8use embassy_hal_common::unborrow;
9use embassy_net::{Device, DeviceCapabilities, LinkState, PacketBuf, MTU}; 9use embassy_net::{Device, DeviceCapabilities, LinkState, PacketBuf, MTU};
10 10
11use crate::gpio::sealed::Pin as __GpioPin; 11use crate::gpio::sealed::Pin as _;
12use crate::gpio::Pin as GpioPin; 12use crate::gpio::{sealed::AFType, AnyPin, Speed};
13use crate::gpio::{sealed::AFType::OutputPushPull, AnyPin};
14use crate::pac::gpio::vals::Ospeedr;
15use crate::pac::{ETH, RCC, SYSCFG}; 13use crate::pac::{ETH, RCC, SYSCFG};
16use crate::peripherals;
17 14
18mod descriptors; 15mod descriptors;
19use super::{StationManagement, PHY}; 16use super::*;
20use descriptors::DescriptorRing; 17use descriptors::DescriptorRing;
21 18
22pub struct State<'d, const TX: usize, const RX: usize>(StateStorage<Inner<'d, TX, RX>>); 19pub struct State<'d, T: Instance, const TX: usize, const RX: usize>(
23impl<'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);
22impl<'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}
28pub struct Ethernet<'d, P: PHY, const TX: usize, const RX: usize> { 27pub 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
37impl<'d, P: PHY, const TX: usize, const RX: usize> Ethernet<'d, P, TX, RX> { 36macro_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
48impl<'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
196unsafe impl<'d, P: PHY, const TX: usize, const RX: usize> StationManagement 199unsafe 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
234impl<'d, P: PHY, const TX: usize, const RX: usize> Device for Ethernet<'d, P, TX, RX> { 237impl<'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
271impl<'d, P: PHY, const TX: usize, const RX: usize> Drop for Ethernet<'d, P, TX, RX> { 276impl<'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
314struct Inner<'d, const TX: usize, const RX: usize> { 319struct 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
319impl<'d, const TX: usize, const RX: usize> Inner<'d, TX, RX> { 324impl<'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
328impl<'d, const TX: usize, const RX: usize> PeripheralState for Inner<'d, TX, RX> { 333impl<'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
353mod 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
393pub trait RefClkPin: sealed::RefClkPin + 'static {}
394
395pub trait MDIOPin: sealed::MDIOPin + 'static {}
396
397pub trait MDCPin: sealed::MDCPin + 'static {}
398
399pub trait CRSPin: sealed::CRSPin + 'static {}
400
401pub trait RXD0Pin: sealed::RXD0Pin + 'static {}
402
403pub trait RXD1Pin: sealed::RXD1Pin + 'static {}
404
405pub trait TXD0Pin: sealed::TXD0Pin + 'static {}
406
407pub trait TXD1Pin: sealed::TXD1Pin + 'static {}
408
409pub trait TXEnPin: sealed::TXEnPin + 'static {}
410
411static WAKER: AtomicWaker = AtomicWaker::new(); 358static WAKER: AtomicWaker = AtomicWaker::new();
412
413macro_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
431crate::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);