embassy_stm32/eth/
generic_smi.rs1use core::task::Context;
4
5#[cfg(feature = "time")]
6use embassy_time::{Duration, Timer};
7#[cfg(feature = "time")]
8use futures_util::FutureExt;
9
10use super::{StationManagement, PHY};
11
12#[allow(dead_code)]
13mod phy_consts {
14 pub const PHY_REG_BCR: u8 = 0x00;
15 pub const PHY_REG_BSR: u8 = 0x01;
16 pub const PHY_REG_ID1: u8 = 0x02;
17 pub const PHY_REG_ID2: u8 = 0x03;
18 pub const PHY_REG_ANTX: u8 = 0x04;
19 pub const PHY_REG_ANRX: u8 = 0x05;
20 pub const PHY_REG_ANEXP: u8 = 0x06;
21 pub const PHY_REG_ANNPTX: u8 = 0x07;
22 pub const PHY_REG_ANNPRX: u8 = 0x08;
23 pub const PHY_REG_CTL: u8 = 0x0D; pub const PHY_REG_ADDAR: u8 = 0x0E; pub const PHY_REG_WUCSR: u16 = 0x8010;
27
28 pub const PHY_REG_BCR_COLTEST: u16 = 1 << 7;
29 pub const PHY_REG_BCR_FD: u16 = 1 << 8;
30 pub const PHY_REG_BCR_ANRST: u16 = 1 << 9;
31 pub const PHY_REG_BCR_ISOLATE: u16 = 1 << 10;
32 pub const PHY_REG_BCR_POWERDN: u16 = 1 << 11;
33 pub const PHY_REG_BCR_AN: u16 = 1 << 12;
34 pub const PHY_REG_BCR_100M: u16 = 1 << 13;
35 pub const PHY_REG_BCR_LOOPBACK: u16 = 1 << 14;
36 pub const PHY_REG_BCR_RESET: u16 = 1 << 15;
37
38 pub const PHY_REG_BSR_JABBER: u16 = 1 << 1;
39 pub const PHY_REG_BSR_UP: u16 = 1 << 2;
40 pub const PHY_REG_BSR_FAULT: u16 = 1 << 4;
41 pub const PHY_REG_BSR_ANDONE: u16 = 1 << 5;
42}
43use self::phy_consts::*;
44
45pub struct GenericSMI {
47 phy_addr: u8,
48 #[cfg(feature = "time")]
49 poll_interval: Duration,
50}
51
52impl GenericSMI {
53 pub fn new(phy_addr: u8) -> Self {
55 Self {
56 phy_addr,
57 #[cfg(feature = "time")]
58 poll_interval: Duration::from_millis(500),
59 }
60 }
61}
62
63unsafe impl PHY for GenericSMI {
64 fn phy_reset<S: StationManagement>(&mut self, sm: &mut S) {
65 sm.smi_write(self.phy_addr, PHY_REG_BCR, PHY_REG_BCR_RESET);
66 while sm.smi_read(self.phy_addr, PHY_REG_BCR) & PHY_REG_BCR_RESET == PHY_REG_BCR_RESET {}
67 }
68
69 fn phy_init<S: StationManagement>(&mut self, sm: &mut S) {
70 self.smi_write_ext(sm, PHY_REG_WUCSR, 0);
72
73 sm.smi_write(
75 self.phy_addr,
76 PHY_REG_BCR,
77 PHY_REG_BCR_AN | PHY_REG_BCR_ANRST | PHY_REG_BCR_100M,
78 );
79 }
80
81 fn poll_link<S: StationManagement>(&mut self, sm: &mut S, cx: &mut Context) -> bool {
82 #[cfg(not(feature = "time"))]
83 cx.waker().wake_by_ref();
84
85 #[cfg(feature = "time")]
86 let _ = Timer::after(self.poll_interval).poll_unpin(cx);
87
88 let bsr = sm.smi_read(self.phy_addr, PHY_REG_BSR);
89
90 if bsr & PHY_REG_BSR_ANDONE == 0 {
92 return false;
93 }
94 if bsr & PHY_REG_BSR_UP == 0 {
96 return false;
97 }
98
99 true
101 }
102}
103
104impl GenericSMI {
106 #[cfg(feature = "time")]
108 pub fn set_poll_interval(&mut self, poll_interval: Duration) {
109 self.poll_interval = poll_interval
110 }
111
112 fn smi_write_ext<S: StationManagement>(&mut self, sm: &mut S, reg_addr: u16, reg_data: u16) {
114 sm.smi_write(self.phy_addr, PHY_REG_CTL, 0x0003); sm.smi_write(self.phy_addr, PHY_REG_ADDAR, reg_addr);
116 sm.smi_write(self.phy_addr, PHY_REG_CTL, 0x4003); sm.smi_write(self.phy_addr, PHY_REG_ADDAR, reg_data);
118 }
119}