aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/eth
diff options
context:
space:
mode:
authorGabriel Górski <[email protected]>2023-10-06 17:45:04 +0200
committerGabriel Górski <[email protected]>2023-10-09 13:46:56 +0200
commit7526b8edba9bbfec7831959afef7736f2d1a39b1 (patch)
tree27604443308a117bbde8fadf0d8757a7afe95c3b /embassy-stm32/src/eth
parentc3ef98a73d0a087b28a560dcbc1c03d45e50d853 (diff)
stm32/eth: Move `phy_addr` from `Ethernet` to `PHY`
Previously, PHY addressing was a concern of the `Ethernet` struct which limited the `PHY` implementations which very often have to manage multiple PHYs internally and thus possibly need to address many of them. This change extends `StationManagement` to allow addressing different PHY addresses via SMI.
Diffstat (limited to 'embassy-stm32/src/eth')
-rw-r--r--embassy-stm32/src/eth/generic_smi.rs33
-rw-r--r--embassy-stm32/src/eth/mod.rs4
-rw-r--r--embassy-stm32/src/eth/v1/mod.rs11
-rw-r--r--embassy-stm32/src/eth/v2/mod.rs11
4 files changed, 27 insertions, 32 deletions
diff --git a/embassy-stm32/src/eth/generic_smi.rs b/embassy-stm32/src/eth/generic_smi.rs
index 2ed46ca2c..1e1094a1c 100644
--- a/embassy-stm32/src/eth/generic_smi.rs
+++ b/embassy-stm32/src/eth/generic_smi.rs
@@ -41,39 +41,40 @@ mod phy_consts {
41} 41}
42use self::phy_consts::*; 42use self::phy_consts::*;
43 43
44/// Generic SMI Ethernet PHY 44/// Generic SMI Ethernet PHY implementation
45pub struct GenericSMI { 45pub struct GenericSMI {
46 phy_addr: u8,
46 #[cfg(feature = "time")] 47 #[cfg(feature = "time")]
47 poll_interval: Duration, 48 poll_interval: Duration,
48 #[cfg(not(feature = "time"))]
49 _private: (),
50} 49}
51 50
52impl GenericSMI { 51impl GenericSMI {
53 pub fn new() -> Self { 52 /// Construct the PHY. It assumes the address `phy_addr` in the SMI communication
53 pub fn new(phy_addr: u8) -> Self {
54 Self { 54 Self {
55 phy_addr,
55 #[cfg(feature = "time")] 56 #[cfg(feature = "time")]
56 poll_interval: Duration::from_millis(500), 57 poll_interval: Duration::from_millis(500),
57 #[cfg(not(feature = "time"))]
58 _private: (),
59 } 58 }
60 } 59 }
61} 60}
62 61
63unsafe impl PHY for GenericSMI { 62unsafe impl PHY for GenericSMI {
64 /// Reset PHY and wait for it to come out of reset.
65 fn phy_reset<S: StationManagement>(&mut self, sm: &mut S) { 63 fn phy_reset<S: StationManagement>(&mut self, sm: &mut S) {
66 sm.smi_write(PHY_REG_BCR, PHY_REG_BCR_RESET); 64 sm.smi_write(self.phy_addr, PHY_REG_BCR, PHY_REG_BCR_RESET);
67 while sm.smi_read(PHY_REG_BCR) & PHY_REG_BCR_RESET == PHY_REG_BCR_RESET {} 65 while sm.smi_read(self.phy_addr, PHY_REG_BCR) & PHY_REG_BCR_RESET == PHY_REG_BCR_RESET {}
68 } 66 }
69 67
70 /// PHY initialisation.
71 fn phy_init<S: StationManagement>(&mut self, sm: &mut S) { 68 fn phy_init<S: StationManagement>(&mut self, sm: &mut S) {
72 // Clear WU CSR 69 // Clear WU CSR
73 self.smi_write_ext(sm, PHY_REG_WUCSR, 0); 70 self.smi_write_ext(sm, PHY_REG_WUCSR, 0);
74 71
75 // Enable auto-negotiation 72 // Enable auto-negotiation
76 sm.smi_write(PHY_REG_BCR, PHY_REG_BCR_AN | PHY_REG_BCR_ANRST | PHY_REG_BCR_100M); 73 sm.smi_write(
74 self.phy_addr,
75 PHY_REG_BCR,
76 PHY_REG_BCR_AN | PHY_REG_BCR_ANRST | PHY_REG_BCR_100M,
77 );
77 } 78 }
78 79
79 fn poll_link<S: StationManagement>(&mut self, sm: &mut S, cx: &mut Context) -> bool { 80 fn poll_link<S: StationManagement>(&mut self, sm: &mut S, cx: &mut Context) -> bool {
@@ -83,7 +84,7 @@ unsafe impl PHY for GenericSMI {
83 #[cfg(feature = "time")] 84 #[cfg(feature = "time")]
84 let _ = Timer::after(self.poll_interval).poll_unpin(cx); 85 let _ = Timer::after(self.poll_interval).poll_unpin(cx);
85 86
86 let bsr = sm.smi_read(PHY_REG_BSR); 87 let bsr = sm.smi_read(self.phy_addr, PHY_REG_BSR);
87 88
88 // No link without autonegotiate 89 // No link without autonegotiate
89 if bsr & PHY_REG_BSR_ANDONE == 0 { 90 if bsr & PHY_REG_BSR_ANDONE == 0 {
@@ -108,9 +109,9 @@ impl GenericSMI {
108 109
109 // Writes a value to an extended PHY register in MMD address space 110 // Writes a value to an extended PHY register in MMD address space
110 fn smi_write_ext<S: StationManagement>(&mut self, sm: &mut S, reg_addr: u16, reg_data: u16) { 111 fn smi_write_ext<S: StationManagement>(&mut self, sm: &mut S, reg_addr: u16, reg_data: u16) {
111 sm.smi_write(PHY_REG_CTL, 0x0003); // set address 112 sm.smi_write(self.phy_addr, PHY_REG_CTL, 0x0003); // set address
112 sm.smi_write(PHY_REG_ADDAR, reg_addr); 113 sm.smi_write(self.phy_addr, PHY_REG_ADDAR, reg_addr);
113 sm.smi_write(PHY_REG_CTL, 0x4003); // set data 114 sm.smi_write(self.phy_addr, PHY_REG_CTL, 0x4003); // set data
114 sm.smi_write(PHY_REG_ADDAR, reg_data); 115 sm.smi_write(self.phy_addr, PHY_REG_ADDAR, reg_data);
115 } 116 }
116} 117}
diff --git a/embassy-stm32/src/eth/mod.rs b/embassy-stm32/src/eth/mod.rs
index 1e057235a..556aadd73 100644
--- a/embassy-stm32/src/eth/mod.rs
+++ b/embassy-stm32/src/eth/mod.rs
@@ -134,9 +134,9 @@ impl<'a, 'd> embassy_net_driver::TxToken for TxToken<'a, 'd> {
134/// The methods cannot move out of self 134/// The methods cannot move out of self
135pub unsafe trait StationManagement { 135pub unsafe trait StationManagement {
136 /// Read a register over SMI. 136 /// Read a register over SMI.
137 fn smi_read(&mut self, reg: u8) -> u16; 137 fn smi_read(&mut self, phy_addr: u8, reg: u8) -> u16;
138 /// Write a register over SMI. 138 /// Write a register over SMI.
139 fn smi_write(&mut self, reg: u8, val: u16); 139 fn smi_write(&mut self, phy_addr: u8, reg: u8, val: u16);
140} 140}
141 141
142/// Traits for an Ethernet PHY 142/// Traits for an Ethernet PHY
diff --git a/embassy-stm32/src/eth/v1/mod.rs b/embassy-stm32/src/eth/v1/mod.rs
index 4d19103dd..631a9377f 100644
--- a/embassy-stm32/src/eth/v1/mod.rs
+++ b/embassy-stm32/src/eth/v1/mod.rs
@@ -107,7 +107,6 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
107 tx_en: impl Peripheral<P = impl TXEnPin<T>> + 'd, 107 tx_en: impl Peripheral<P = impl TXEnPin<T>> + 'd,
108 phy: P, 108 phy: P,
109 mac_addr: [u8; 6], 109 mac_addr: [u8; 6],
110 phy_addr: u8,
111 ) -> Self { 110 ) -> Self {
112 into_ref!(peri, ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en); 111 into_ref!(peri, ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en);
113 112
@@ -227,7 +226,6 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
227 station_management: EthernetStationManagement { 226 station_management: EthernetStationManagement {
228 peri: PhantomData, 227 peri: PhantomData,
229 clock_range: clock_range, 228 clock_range: clock_range,
230 phy_addr: phy_addr,
231 }, 229 },
232 mac_addr, 230 mac_addr,
233 tx: TDesRing::new(&mut queue.tx_desc, &mut queue.tx_buf), 231 tx: TDesRing::new(&mut queue.tx_desc, &mut queue.tx_buf),
@@ -271,15 +269,14 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
271pub struct EthernetStationManagement<T: Instance> { 269pub struct EthernetStationManagement<T: Instance> {
272 peri: PhantomData<T>, 270 peri: PhantomData<T>,
273 clock_range: Cr, 271 clock_range: Cr,
274 phy_addr: u8,
275} 272}
276 273
277unsafe impl<T: Instance> StationManagement for EthernetStationManagement<T> { 274unsafe impl<T: Instance> StationManagement for EthernetStationManagement<T> {
278 fn smi_read(&mut self, reg: u8) -> u16 { 275 fn smi_read(&mut self, phy_addr: u8, reg: u8) -> u16 {
279 let mac = ETH.ethernet_mac(); 276 let mac = ETH.ethernet_mac();
280 277
281 mac.macmiiar().modify(|w| { 278 mac.macmiiar().modify(|w| {
282 w.set_pa(self.phy_addr); 279 w.set_pa(phy_addr);
283 w.set_mr(reg); 280 w.set_mr(reg);
284 w.set_mw(Mw::READ); // read operation 281 w.set_mw(Mw::READ); // read operation
285 w.set_cr(self.clock_range); 282 w.set_cr(self.clock_range);
@@ -289,12 +286,12 @@ unsafe impl<T: Instance> StationManagement for EthernetStationManagement<T> {
289 mac.macmiidr().read().md() 286 mac.macmiidr().read().md()
290 } 287 }
291 288
292 fn smi_write(&mut self, reg: u8, val: u16) { 289 fn smi_write(&mut self, phy_addr: u8, reg: u8, val: u16) {
293 let mac = ETH.ethernet_mac(); 290 let mac = ETH.ethernet_mac();
294 291
295 mac.macmiidr().write(|w| w.set_md(val)); 292 mac.macmiidr().write(|w| w.set_md(val));
296 mac.macmiiar().modify(|w| { 293 mac.macmiiar().modify(|w| {
297 w.set_pa(self.phy_addr); 294 w.set_pa(phy_addr);
298 w.set_mr(reg); 295 w.set_mr(reg);
299 w.set_mw(Mw::WRITE); // write 296 w.set_mw(Mw::WRITE); // write
300 w.set_cr(self.clock_range); 297 w.set_cr(self.clock_range);
diff --git a/embassy-stm32/src/eth/v2/mod.rs b/embassy-stm32/src/eth/v2/mod.rs
index 6efd40e3e..12cf618aa 100644
--- a/embassy-stm32/src/eth/v2/mod.rs
+++ b/embassy-stm32/src/eth/v2/mod.rs
@@ -71,7 +71,6 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
71 tx_en: impl Peripheral<P = impl TXEnPin<T>> + 'd, 71 tx_en: impl Peripheral<P = impl TXEnPin<T>> + 'd,
72 phy: P, 72 phy: P,
73 mac_addr: [u8; 6], 73 mac_addr: [u8; 6],
74 phy_addr: u8,
75 ) -> Self { 74 ) -> Self {
76 into_ref!(peri, ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en); 75 into_ref!(peri, ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en);
77 76
@@ -202,7 +201,6 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
202 station_management: EthernetStationManagement { 201 station_management: EthernetStationManagement {
203 peri: PhantomData, 202 peri: PhantomData,
204 clock_range: clock_range, 203 clock_range: clock_range,
205 phy_addr: phy_addr,
206 }, 204 },
207 mac_addr, 205 mac_addr,
208 }; 206 };
@@ -242,15 +240,14 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
242pub struct EthernetStationManagement<T: Instance> { 240pub struct EthernetStationManagement<T: Instance> {
243 peri: PhantomData<T>, 241 peri: PhantomData<T>,
244 clock_range: u8, 242 clock_range: u8,
245 phy_addr: u8,
246} 243}
247 244
248unsafe impl<T: Instance> StationManagement for EthernetStationManagement<T> { 245unsafe impl<T: Instance> StationManagement for EthernetStationManagement<T> {
249 fn smi_read(&mut self, reg: u8) -> u16 { 246 fn smi_read(&mut self, phy_addr: u8, reg: u8) -> u16 {
250 let mac = ETH.ethernet_mac(); 247 let mac = ETH.ethernet_mac();
251 248
252 mac.macmdioar().modify(|w| { 249 mac.macmdioar().modify(|w| {
253 w.set_pa(self.phy_addr); 250 w.set_pa(phy_addr);
254 w.set_rda(reg); 251 w.set_rda(reg);
255 w.set_goc(0b11); // read 252 w.set_goc(0b11); // read
256 w.set_cr(self.clock_range); 253 w.set_cr(self.clock_range);
@@ -260,12 +257,12 @@ unsafe impl<T: Instance> StationManagement for EthernetStationManagement<T> {
260 mac.macmdiodr().read().md() 257 mac.macmdiodr().read().md()
261 } 258 }
262 259
263 fn smi_write(&mut self, reg: u8, val: u16) { 260 fn smi_write(&mut self, phy_addr: u8, reg: u8, val: u16) {
264 let mac = ETH.ethernet_mac(); 261 let mac = ETH.ethernet_mac();
265 262
266 mac.macmdiodr().write(|w| w.set_md(val)); 263 mac.macmdiodr().write(|w| w.set_md(val));
267 mac.macmdioar().modify(|w| { 264 mac.macmdioar().modify(|w| {
268 w.set_pa(self.phy_addr); 265 w.set_pa(phy_addr);
269 w.set_rda(reg); 266 w.set_rda(reg);
270 w.set_goc(0b01); // write 267 w.set_goc(0b01); // write
271 w.set_cr(self.clock_range); 268 w.set_cr(self.clock_range);