diff options
| author | Dario Nieuwenhuis <[email protected]> | 2025-01-26 21:21:06 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-01-26 21:21:06 +0000 |
| commit | c8d29a1e2cd3f28c3afdd52a679fcb49f67e812c (patch) | |
| tree | 56ef4d76ecb959851ca714f1cff7d7026e2ed845 /embassy-stm32 | |
| parent | 7e0c70b1aa6ac6072e2c98cabb10072e4cd9942d (diff) | |
| parent | ff52bde787031493ce174cdc1dcc2434fd16aa1b (diff) | |
Merge pull request #3795 from nikvoid/stm32-phy-addr-detection
STM32: Option to detect Ethernet PHY address automatically
Diffstat (limited to 'embassy-stm32')
| -rw-r--r-- | embassy-stm32/src/eth/generic_smi.rs | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/embassy-stm32/src/eth/generic_smi.rs b/embassy-stm32/src/eth/generic_smi.rs index 3b43051f4..239c52634 100644 --- a/embassy-stm32/src/eth/generic_smi.rs +++ b/embassy-stm32/src/eth/generic_smi.rs | |||
| @@ -51,17 +51,63 @@ pub struct GenericSMI { | |||
| 51 | 51 | ||
| 52 | impl GenericSMI { | 52 | impl GenericSMI { |
| 53 | /// Construct the PHY. It assumes the address `phy_addr` in the SMI communication | 53 | /// Construct the PHY. It assumes the address `phy_addr` in the SMI communication |
| 54 | /// | ||
| 55 | /// # Panics | ||
| 56 | /// `phy_addr` must be in range `0..32` | ||
| 54 | pub fn new(phy_addr: u8) -> Self { | 57 | pub fn new(phy_addr: u8) -> Self { |
| 58 | assert!(phy_addr < 32); | ||
| 55 | Self { | 59 | Self { |
| 56 | phy_addr, | 60 | phy_addr, |
| 57 | #[cfg(feature = "time")] | 61 | #[cfg(feature = "time")] |
| 58 | poll_interval: Duration::from_millis(500), | 62 | poll_interval: Duration::from_millis(500), |
| 59 | } | 63 | } |
| 60 | } | 64 | } |
| 65 | |||
| 66 | /// Construct the PHY. Try to probe all addresses from 0 to 31 during initialization | ||
| 67 | /// | ||
| 68 | /// # Panics | ||
| 69 | /// Initialization panics if PHY didn't respond on any address | ||
| 70 | pub fn new_auto() -> Self { | ||
| 71 | Self { | ||
| 72 | phy_addr: 0xFF, | ||
| 73 | #[cfg(feature = "time")] | ||
| 74 | poll_interval: Duration::from_millis(500), | ||
| 75 | } | ||
| 76 | } | ||
| 77 | } | ||
| 78 | |||
| 79 | // TODO: Factor out to shared functionality | ||
| 80 | fn blocking_delay_us(us: u32) { | ||
| 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 | } | ||
| 61 | } | 90 | } |
| 62 | 91 | ||
| 63 | unsafe impl PHY for GenericSMI { | 92 | unsafe impl PHY for GenericSMI { |
| 64 | fn phy_reset<S: StationManagement>(&mut self, sm: &mut S) { | 93 | fn phy_reset<S: StationManagement>(&mut self, sm: &mut S) { |
| 94 | // Detect SMI address | ||
| 95 | if self.phy_addr == 0xFF { | ||
| 96 | for addr in 0..32 { | ||
| 97 | sm.smi_write(addr, PHY_REG_BCR, PHY_REG_BCR_RESET); | ||
| 98 | for _ in 0..10 { | ||
| 99 | if sm.smi_read(addr, PHY_REG_BCR) & PHY_REG_BCR_RESET != PHY_REG_BCR_RESET { | ||
| 100 | trace!("Found ETH PHY on address {}", addr); | ||
| 101 | self.phy_addr = addr; | ||
| 102 | return; | ||
| 103 | } | ||
| 104 | // Give PHY a total of 100ms to respond | ||
| 105 | blocking_delay_us(10000); | ||
| 106 | } | ||
| 107 | } | ||
| 108 | panic!("PHY did not respond"); | ||
| 109 | } | ||
| 110 | |||
| 65 | sm.smi_write(self.phy_addr, PHY_REG_BCR, PHY_REG_BCR_RESET); | 111 | 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 {} | 112 | while sm.smi_read(self.phy_addr, PHY_REG_BCR) & PHY_REG_BCR_RESET == PHY_REG_BCR_RESET {} |
| 67 | } | 113 | } |
