aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/eth/generic_phy.rs
diff options
context:
space:
mode:
authorRaul Alimbekov <[email protected]>2025-12-16 09:05:22 +0300
committerGitHub <[email protected]>2025-12-16 09:05:22 +0300
commitc9a04b4b732b7a3b696eb8223664c1a7942b1875 (patch)
tree6dbe5c02e66eed8d8762f13f95afd24f8db2b38c /embassy-stm32/src/eth/generic_phy.rs
parentcde24a3ef1117653ba5ed4184102b33f745782fb (diff)
parent5ae6e060ec1c90561719aabdc29d5b6e7b8b0a82 (diff)
Merge branch 'main' into main
Diffstat (limited to 'embassy-stm32/src/eth/generic_phy.rs')
-rw-r--r--embassy-stm32/src/eth/generic_phy.rs64
1 files changed, 30 insertions, 34 deletions
diff --git a/embassy-stm32/src/eth/generic_phy.rs b/embassy-stm32/src/eth/generic_phy.rs
index 774beef80..0a5f41de0 100644
--- a/embassy-stm32/src/eth/generic_phy.rs
+++ b/embassy-stm32/src/eth/generic_phy.rs
@@ -8,6 +8,7 @@ use embassy_time::{Duration, Timer};
8use futures_util::FutureExt; 8use futures_util::FutureExt;
9 9
10use super::{Phy, StationManagement}; 10use super::{Phy, StationManagement};
11use crate::block_for_us as blocking_delay_us;
11 12
12#[allow(dead_code)] 13#[allow(dead_code)]
13mod phy_consts { 14mod phy_consts {
@@ -43,21 +44,23 @@ mod phy_consts {
43use self::phy_consts::*; 44use self::phy_consts::*;
44 45
45/// Generic SMI Ethernet PHY implementation 46/// Generic SMI Ethernet PHY implementation
46pub struct GenericPhy { 47pub struct GenericPhy<SM: StationManagement> {
47 phy_addr: u8, 48 phy_addr: u8,
49 sm: SM,
48 #[cfg(feature = "time")] 50 #[cfg(feature = "time")]
49 poll_interval: Duration, 51 poll_interval: Duration,
50} 52}
51 53
52impl GenericPhy { 54impl<SM: StationManagement> GenericPhy<SM> {
53 /// Construct the PHY. It assumes the address `phy_addr` in the SMI communication 55 /// Construct the PHY. It assumes the address `phy_addr` in the SMI communication
54 /// 56 ///
55 /// # Panics 57 /// # Panics
56 /// `phy_addr` must be in range `0..32` 58 /// `phy_addr` must be in range `0..32`
57 pub fn new(phy_addr: u8) -> Self { 59 pub fn new(sm: SM, phy_addr: u8) -> Self {
58 assert!(phy_addr < 32); 60 assert!(phy_addr < 32);
59 Self { 61 Self {
60 phy_addr, 62 phy_addr,
63 sm,
61 #[cfg(feature = "time")] 64 #[cfg(feature = "time")]
62 poll_interval: Duration::from_millis(500), 65 poll_interval: Duration::from_millis(500),
63 } 66 }
@@ -67,8 +70,9 @@ impl GenericPhy {
67 /// 70 ///
68 /// # Panics 71 /// # Panics
69 /// Initialization panics if PHY didn't respond on any address 72 /// Initialization panics if PHY didn't respond on any address
70 pub fn new_auto() -> Self { 73 pub fn new_auto(sm: SM) -> Self {
71 Self { 74 Self {
75 sm,
72 phy_addr: 0xFF, 76 phy_addr: 0xFF,
73 #[cfg(feature = "time")] 77 #[cfg(feature = "time")]
74 poll_interval: Duration::from_millis(500), 78 poll_interval: Duration::from_millis(500),
@@ -76,27 +80,14 @@ impl GenericPhy {
76 } 80 }
77} 81}
78 82
79// TODO: Factor out to shared functionality 83impl<SM: StationManagement> Phy for GenericPhy<SM> {
80fn blocking_delay_us(us: u32) { 84 fn phy_reset(&mut self) {
81 #[cfg(feature = "time")]
82 embassy_time::block_for(Duration::from_micros(us as u64));
83 #[cfg(not(feature = "time"))]
84 {
85 let freq = unsafe { crate::rcc::get_freqs() }.sys.to_hertz().unwrap().0 as u64;
86 let us = us as u64;
87 let cycles = freq * us / 1_000_000;
88 cortex_m::asm::delay(cycles as u32);
89 }
90}
91
92impl Phy for GenericPhy {
93 fn phy_reset<S: StationManagement>(&mut self, sm: &mut S) {
94 // Detect SMI address 85 // Detect SMI address
95 if self.phy_addr == 0xFF { 86 if self.phy_addr == 0xFF {
96 for addr in 0..32 { 87 for addr in 0..32 {
97 sm.smi_write(addr, PHY_REG_BCR, PHY_REG_BCR_RESET); 88 self.sm.smi_write(addr, PHY_REG_BCR, PHY_REG_BCR_RESET);
98 for _ in 0..10 { 89 for _ in 0..10 {
99 if sm.smi_read(addr, PHY_REG_BCR) & PHY_REG_BCR_RESET != PHY_REG_BCR_RESET { 90 if self.sm.smi_read(addr, PHY_REG_BCR) & PHY_REG_BCR_RESET != PHY_REG_BCR_RESET {
100 trace!("Found ETH PHY on address {}", addr); 91 trace!("Found ETH PHY on address {}", addr);
101 self.phy_addr = addr; 92 self.phy_addr = addr;
102 return; 93 return;
@@ -108,30 +99,30 @@ impl Phy for GenericPhy {
108 panic!("PHY did not respond"); 99 panic!("PHY did not respond");
109 } 100 }
110 101
111 sm.smi_write(self.phy_addr, PHY_REG_BCR, PHY_REG_BCR_RESET); 102 self.sm.smi_write(self.phy_addr, PHY_REG_BCR, PHY_REG_BCR_RESET);
112 while sm.smi_read(self.phy_addr, PHY_REG_BCR) & PHY_REG_BCR_RESET == PHY_REG_BCR_RESET {} 103 while self.sm.smi_read(self.phy_addr, PHY_REG_BCR) & PHY_REG_BCR_RESET == PHY_REG_BCR_RESET {}
113 } 104 }
114 105
115 fn phy_init<S: StationManagement>(&mut self, sm: &mut S) { 106 fn phy_init(&mut self) {
116 // Clear WU CSR 107 // Clear WU CSR
117 self.smi_write_ext(sm, PHY_REG_WUCSR, 0); 108 self.smi_write_ext(PHY_REG_WUCSR, 0);
118 109
119 // Enable auto-negotiation 110 // Enable auto-negotiation
120 sm.smi_write( 111 self.sm.smi_write(
121 self.phy_addr, 112 self.phy_addr,
122 PHY_REG_BCR, 113 PHY_REG_BCR,
123 PHY_REG_BCR_AN | PHY_REG_BCR_ANRST | PHY_REG_BCR_100M, 114 PHY_REG_BCR_AN | PHY_REG_BCR_ANRST | PHY_REG_BCR_100M,
124 ); 115 );
125 } 116 }
126 117
127 fn poll_link<S: StationManagement>(&mut self, sm: &mut S, cx: &mut Context) -> bool { 118 fn poll_link(&mut self, cx: &mut Context) -> bool {
128 #[cfg(not(feature = "time"))] 119 #[cfg(not(feature = "time"))]
129 cx.waker().wake_by_ref(); 120 cx.waker().wake_by_ref();
130 121
131 #[cfg(feature = "time")] 122 #[cfg(feature = "time")]
132 let _ = Timer::after(self.poll_interval).poll_unpin(cx); 123 let _ = Timer::after(self.poll_interval).poll_unpin(cx);
133 124
134 let bsr = sm.smi_read(self.phy_addr, PHY_REG_BSR); 125 let bsr = self.sm.smi_read(self.phy_addr, PHY_REG_BSR);
135 126
136 // No link without autonegotiate 127 // No link without autonegotiate
137 if bsr & PHY_REG_BSR_ANDONE == 0 { 128 if bsr & PHY_REG_BSR_ANDONE == 0 {
@@ -148,7 +139,7 @@ impl Phy for GenericPhy {
148} 139}
149 140
150/// Public functions for the PHY 141/// Public functions for the PHY
151impl GenericPhy { 142impl<SM: StationManagement> GenericPhy<SM> {
152 /// Set the SMI polling interval. 143 /// Set the SMI polling interval.
153 #[cfg(feature = "time")] 144 #[cfg(feature = "time")]
154 pub fn set_poll_interval(&mut self, poll_interval: Duration) { 145 pub fn set_poll_interval(&mut self, poll_interval: Duration) {
@@ -156,10 +147,15 @@ impl GenericPhy {
156 } 147 }
157 148
158 // Writes a value to an extended PHY register in MMD address space 149 // Writes a value to an extended PHY register in MMD address space
159 fn smi_write_ext<S: StationManagement>(&mut self, sm: &mut S, reg_addr: u16, reg_data: u16) { 150 fn smi_write_ext(&mut self, reg_addr: u16, reg_data: u16) {
160 sm.smi_write(self.phy_addr, PHY_REG_CTL, 0x0003); // set address 151 self.sm.smi_write(self.phy_addr, PHY_REG_CTL, 0x0003); // set address
161 sm.smi_write(self.phy_addr, PHY_REG_ADDAR, reg_addr); 152 self.sm.smi_write(self.phy_addr, PHY_REG_ADDAR, reg_addr);
162 sm.smi_write(self.phy_addr, PHY_REG_CTL, 0x4003); // set data 153 self.sm.smi_write(self.phy_addr, PHY_REG_CTL, 0x4003); // set data
163 sm.smi_write(self.phy_addr, PHY_REG_ADDAR, reg_data); 154 self.sm.smi_write(self.phy_addr, PHY_REG_ADDAR, reg_data);
155 }
156
157 /// Access the underlying station management.
158 pub fn station_management(&mut self) -> &mut SM {
159 &mut self.sm
164 } 160 }
165} 161}