stm32_eth/mac/
miim.rs

1pub use ieee802_3_miim::Miim;
2
3pub use ieee802_3_miim::*;
4
5use crate::{peripherals::ETHERNET_MAC, stm32::ethernet_mac::MACMIIAR};
6
7use super::EthernetMAC;
8
9/// MDIO pin types.
10///
11/// # Safety
12/// Only pins specified as ETH_MDIO in a part's reference manual
13/// may implement this trait
14pub unsafe trait MdioPin {}
15
16/// MDC pin types.
17///
18/// # Safety
19/// Only pins specified as ETH_MDC in a part's reference manual
20/// may implement this trait
21pub unsafe trait MdcPin {}
22
23#[inline(always)]
24fn miim_wait_ready(iar: &MACMIIAR) {
25    while iar.read().mb().bit_is_set() {}
26}
27
28#[inline(always)]
29fn miim_write(eth_mac: &mut ETHERNET_MAC, phy: u8, reg: u8, data: u16) {
30    miim_wait_ready(&eth_mac.macmiiar);
31    eth_mac.macmiidr.write(|w| w.md().bits(data));
32
33    miim_wait_ready(&eth_mac.macmiiar);
34
35    eth_mac.macmiiar.modify(|_, w| {
36        w.pa()
37            .bits(phy)
38            .mr()
39            .bits(reg)
40            /* Write operation MW=1*/
41            .mw()
42            .set_bit()
43            .mb()
44            .set_bit()
45    });
46    miim_wait_ready(&eth_mac.macmiiar);
47}
48
49#[inline(always)]
50fn miim_read(eth_mac: &mut ETHERNET_MAC, phy: u8, reg: u8) -> u16 {
51    miim_wait_ready(&eth_mac.macmiiar);
52    eth_mac.macmiiar.modify(|_, w| {
53        w.pa()
54            .bits(phy)
55            .mr()
56            .bits(reg)
57            /* Read operation MW=0 */
58            .mw()
59            .clear_bit()
60            .mb()
61            .set_bit()
62    });
63    miim_wait_ready(&eth_mac.macmiiar);
64
65    // Return value:
66    eth_mac.macmiidr.read().md().bits()
67}
68
69/// Serial Management Interface
70///
71/// Borrows an [`EthernetMAC`] and holds a mutable borrow to the SMI pins.
72pub struct Stm32Mii<'mac, 'pins, Mdio, Mdc> {
73    mac: &'mac mut EthernetMAC,
74    _mdio: &'pins mut Mdio,
75    _mdc: &'pins mut Mdc,
76}
77
78impl<'mac, 'pins, Mdio, Mdc> Stm32Mii<'mac, 'pins, Mdio, Mdc>
79where
80    Mdio: MdioPin,
81    Mdc: MdcPin,
82{
83    /// Read MII register `reg` from the PHY at address `phy`
84    pub fn read(&mut self, phy: u8, reg: u8) -> u16 {
85        miim_read(&mut self.mac.eth_mac, phy, reg)
86    }
87
88    /// Write the value `data` to MII register `reg` to the PHY at address `phy`
89    pub fn write(&mut self, phy: u8, reg: u8, data: u16) {
90        miim_write(&mut self.mac.eth_mac, phy, reg, data)
91    }
92}
93
94impl<'eth, 'pins, Mdio, Mdc> Miim for Stm32Mii<'eth, 'pins, Mdio, Mdc>
95where
96    Mdio: MdioPin,
97    Mdc: MdcPin,
98{
99    fn read(&mut self, phy: u8, reg: u8) -> u16 {
100        self.read(phy, reg)
101    }
102
103    fn write(&mut self, phy: u8, reg: u8, data: u16) {
104        self.write(phy, reg, data)
105    }
106}
107
108impl<'eth, 'pins, Mdio, Mdc> Stm32Mii<'eth, 'pins, Mdio, Mdc>
109where
110    Mdio: MdioPin,
111    Mdc: MdcPin,
112{
113    /// Create a temporary [`Stm32Mii`] instance.
114    ///
115    /// Temporarily take exclusive access to the MDIO and MDC pins to ensure they are not used
116    /// elsewhere for the duration of SMI communication.
117    pub fn new(mac: &'eth mut EthernetMAC, _mdio: &'pins mut Mdio, _mdc: &'pins mut Mdc) -> Self {
118        Self { mac, _mdio, _mdc }
119    }
120}
121
122#[cfg(feature = "stm32f4xx-hal")]
123mod pin_impls {
124    use crate::hal::gpio::{gpioa::PA2, gpioc::PC1, Alternate};
125
126    const AF11: u8 = 11;
127
128    unsafe impl super::MdioPin for PA2<Alternate<AF11>> {}
129    unsafe impl super::MdcPin for PC1<Alternate<AF11>> {}
130}
131
132#[cfg(feature = "stm32f7xx-hal")]
133mod pin_impls {
134    use crate::hal::gpio::{gpioa::PA2, gpioc::PC1, Alternate};
135
136    const AF11: u8 = 11;
137
138    unsafe impl super::MdioPin for PA2<Alternate<AF11>> {}
139    unsafe impl super::MdcPin for PC1<Alternate<AF11>> {}
140}
141
142#[cfg(feature = "stm32f1xx-hal")]
143mod pin_impls {
144    use crate::hal::gpio::{gpioa::PA2, gpioc::PC1, Alternate, PushPull};
145
146    unsafe impl super::MdioPin for PA2<Alternate<PushPull>> {}
147    unsafe impl super::MdcPin for PC1<Alternate<PushPull>> {}
148}