1use core::ops::{Deref, DerefMut};
4
5use crate::{dma::EthernetDMA, hal::rcc::Clocks, peripherals::ETHERNET_MAC, stm32::ETHERNET_MMC};
6
7mod miim;
8pub use miim::*;
9
10#[cfg_attr(feature = "defmt", derive(defmt::Format))]
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13pub enum Speed {
14 HalfDuplexBase10T,
16 FullDuplexBase10T,
18 HalfDuplexBase100Tx,
20 FullDuplexBase100Tx,
22}
23
24mod consts {
25 pub const ETH_MACMIIAR_CR_HCLK_DIV_42: u8 = 0;
27 pub const ETH_MACMIIAR_CR_HCLK_DIV_62: u8 = 1;
29 pub const ETH_MACMIIAR_CR_HCLK_DIV_16: u8 = 2;
31 pub const ETH_MACMIIAR_CR_HCLK_DIV_26: u8 = 3;
33 pub const ETH_MACMIIAR_CR_HCLK_DIV_102: u8 = 4;
35}
36use self::consts::*;
37
38#[derive(Debug)]
42pub struct WrongClock;
43
44pub struct EthernetMAC {
49 eth_mac: ETHERNET_MAC,
50}
51
52impl EthernetMAC {
53 pub(crate) fn new(
63 eth_mac: ETHERNET_MAC,
64 eth_mmc: ETHERNET_MMC,
65 clocks: Clocks,
66 initial_speed: Speed,
67 _dma: &EthernetDMA,
71 ) -> Result<Self, WrongClock> {
72 let clock_frequency = clocks.hclk().to_Hz();
73
74 let clock_range = match clock_frequency {
75 0..=24_999_999 => return Err(WrongClock),
76 25_000_000..=34_999_999 => ETH_MACMIIAR_CR_HCLK_DIV_16,
77 35_000_000..=59_999_999 => ETH_MACMIIAR_CR_HCLK_DIV_26,
78 60_000_000..=99_999_999 => ETH_MACMIIAR_CR_HCLK_DIV_42,
79 100_000_000..=149_999_999 => ETH_MACMIIAR_CR_HCLK_DIV_62,
80 _ => ETH_MACMIIAR_CR_HCLK_DIV_102,
81 };
82
83 eth_mac
85 .macmiiar
86 .modify(|_, w| unsafe { w.cr().bits(clock_range) });
87
88 eth_mac.maccr.modify(|_, w| {
90 #[cfg(any(feature = "stm32f4xx-hal", feature = "stm32f7xx-hal"))]
92 let w = w.cstf().set_bit();
93
94 w.fes()
96 .set_bit()
97 .dm()
99 .set_bit()
100 .ipco()
102 .set_bit()
103 .apcs()
105 .set_bit()
106 .rd()
108 .set_bit()
109 .re()
111 .set_bit()
112 .te()
114 .set_bit()
115 });
116
117 eth_mac.macffr.modify(|_, w| {
119 w.ra()
121 .set_bit()
122 .pm()
124 .set_bit()
125 });
126
127 eth_mac.macfcr.modify(|_, w| {
129 w.pt().bits(0x100)
131 });
132
133 eth_mmc
135 .mmcrimr
136 .write(|w| w.rgufm().set_bit().rfaem().set_bit().rfcem().set_bit());
137
138 eth_mmc
140 .mmctimr
141 .write(|w| w.tgfm().set_bit().tgfmscm().set_bit().tgfscm().set_bit());
142
143 eth_mmc
146 .mmctimr
147 .modify(|r, w| unsafe { w.bits(r.bits() | (1 << 21)) });
148
149 let mut me = Self { eth_mac };
150
151 me.set_speed(initial_speed);
152
153 Ok(me)
154 }
155
156 pub fn mii<'eth, 'pins, Mdio, Mdc>(
164 &'eth mut self,
165 mdio: &'pins mut Mdio,
166 mdc: &'pins mut Mdc,
167 ) -> Stm32Mii<'eth, 'pins, Mdio, Mdc>
168 where
169 Mdio: MdioPin,
170 Mdc: MdcPin,
171 {
172 Stm32Mii::new(self, mdio, mdc)
173 }
174
175 pub fn with_mii<MDIO, MDC>(self, mdio: MDIO, mdc: MDC) -> EthernetMACWithMii<MDIO, MDC>
177 where
178 MDIO: MdioPin,
179 MDC: MdcPin,
180 {
181 EthernetMACWithMii {
182 eth_mac: self,
183 mdio,
184 mdc,
185 }
186 }
187
188 pub fn set_speed(&mut self, speed: Speed) {
194 self.eth_mac.maccr.modify(|_, w| match speed {
195 Speed::HalfDuplexBase10T => w.fes().clear_bit().dm().clear_bit(),
196 Speed::FullDuplexBase10T => w.fes().clear_bit().dm().set_bit(),
197 Speed::HalfDuplexBase100Tx => w.fes().set_bit().dm().clear_bit(),
198 Speed::FullDuplexBase100Tx => w.fes().set_bit().dm().set_bit(),
199 });
200 }
201
202 pub fn get_speed(&self) -> Speed {
204 let cr = self.eth_mac.maccr.read();
205 match (cr.fes().bit_is_set(), cr.dm().bit_is_set()) {
206 (false, false) => Speed::HalfDuplexBase10T,
207 (false, true) => Speed::FullDuplexBase10T,
208 (true, false) => Speed::HalfDuplexBase100Tx,
209 (true, true) => Speed::FullDuplexBase100Tx,
210 }
211 }
212
213 #[cfg(feature = "ptp")]
214 pub(crate) fn mask_timestamp_trigger_interrupt() {
215 let mac = &unsafe { &*ETHERNET_MAC::ptr() };
217 mac.macimr.write(|w| w.tstim().set_bit());
218 }
219
220 #[allow(dead_code)]
222 pub(crate) fn unmask_timestamp_trigger_interrupt() {
223 let macimr = &unsafe { &*ETHERNET_MAC::ptr() }.macimr;
225 macimr.write(|w| w.tstim().clear_bit());
226 }
227}
228
229pub struct EthernetMACWithMii<MDIO, MDC>
235where
236 MDIO: MdioPin,
237 MDC: MdcPin,
238{
239 pub(crate) eth_mac: EthernetMAC,
240 mdio: MDIO,
241 mdc: MDC,
242}
243
244impl<MDIO, MDC> EthernetMACWithMii<MDIO, MDC>
245where
246 MDIO: MdioPin,
247 MDC: MdcPin,
248{
249 pub fn new(eth_mac: EthernetMAC, mdio: MDIO, mdc: MDC) -> Self {
256 Self { eth_mac, mdio, mdc }
257 }
258
259 pub fn release_pins(self) -> (EthernetMAC, MDIO, MDC) {
262 (self.eth_mac, self.mdio, self.mdc)
263 }
264}
265
266impl<MDIO, MDC> Deref for EthernetMACWithMii<MDIO, MDC>
267where
268 MDIO: MdioPin,
269 MDC: MdcPin,
270{
271 type Target = EthernetMAC;
272
273 fn deref(&self) -> &Self::Target {
274 &self.eth_mac
275 }
276}
277
278impl<MDIO, MDC> DerefMut for EthernetMACWithMii<MDIO, MDC>
279where
280 MDIO: MdioPin,
281 MDC: MdcPin,
282{
283 fn deref_mut(&mut self) -> &mut Self::Target {
284 &mut self.eth_mac
285 }
286}
287
288impl<MDIO, MDC> EthernetMACWithMii<MDIO, MDC>
289where
290 MDIO: MdioPin,
291 MDC: MdcPin,
292{
293 pub fn read(&mut self, phy: u8, reg: u8) -> u16 {
295 self.eth_mac
296 .mii(&mut self.mdio, &mut self.mdc)
297 .read(phy, reg)
298 }
299
300 pub fn write(&mut self, phy: u8, reg: u8, data: u16) {
302 self.eth_mac
303 .mii(&mut self.mdio, &mut self.mdc)
304 .write(phy, reg, data)
305 }
306}
307
308impl<MDIO, MDC> miim::Miim for EthernetMACWithMii<MDIO, MDC>
309where
310 MDIO: MdioPin,
311 MDC: MdcPin,
312{
313 fn read(&mut self, phy: u8, reg: u8) -> u16 {
314 self.read(phy, reg)
315 }
316
317 fn write(&mut self, phy: u8, reg: u8, data: u16) {
318 self.write(phy, reg, data)
319 }
320}