Skip to content

Commit 2299acb

Browse files
Merge pull request #53 from datdenkikniet/speed_config
Speed configuration
2 parents 2fa8fec + 4eb2488 commit 2299acb

File tree

6 files changed

+102
-13
lines changed

6 files changed

+102
-13
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* Remove the `smi` feature and always enable miim/smi. Use `ieee802_3_miim` for SMI access
44
* Split MAC and DMA setup into their own separate modules
55
* Update stm32f1xx-hal and stm32f4xx-hal to their latests version as of 15-12-2022.
6+
* Allow for configuration of MAC speed. ([#53](https://github.com/stm32-rs/stm32-eth/pull/53), fixes [#24](https://github.com/stm32-rs/stm32-eth/pull/24))
67
* CI
78
* Test compilability of examples more extensively
89
* Move away from actions-rs

README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -103,12 +103,12 @@ To run or build them, the following steps should be taken:
103103

104104
Besides the feature selecting the correct MCU to be used when building and/or running an example, the following additional features are required:
105105

106-
| Example | Additional required features |
107-
| ------------- | ---------------------------------------------------- |
108-
| `arp` | `defmt` |
109-
| `ip` | `defmt,smoltcp-phy,smoltcp/defmt,smoltcp/socket-tcp` |
110-
| `pktgen` | `defmt` |
111-
| `rtic-echo` | `rtic-echo-example` |
106+
| Example | Additional required features |
107+
| ----------- | ---------------------------------------------------- |
108+
| `arp` | `defmt` |
109+
| `ip` | `defmt,smoltcp-phy,smoltcp/defmt,smoltcp/socket-tcp` |
110+
| `pktgen` | `defmt` |
111+
| `rtic-echo` | `rtic-echo-example` |
112112

113113
#### 144-pin nucleo boards
114114

examples/common.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,11 @@ pub enum EthernetPhy<M: Miim> {
252252

253253
impl<M: Miim> Phy<M> for EthernetPhy<M> {
254254
fn best_supported_advertisement(&self) -> ieee802_3_miim::AutoNegotiationAdvertisement {
255-
unimplemented!()
255+
match self {
256+
EthernetPhy::LAN8720A(phy) => phy.best_supported_advertisement(),
257+
EthernetPhy::LAN8742A(phy) => phy.best_supported_advertisement(),
258+
EthernetPhy::KSZ8081R(phy) => phy.best_supported_advertisement(),
259+
}
256260
}
257261

258262
fn get_miim(&mut self) -> &mut M {
@@ -309,4 +313,13 @@ impl<M: Miim> EthernetPhy<M> {
309313
}
310314
}
311315
}
316+
317+
#[allow(dead_code)]
318+
pub fn speed(&mut self) -> Option<ieee802_3_miim::phy::PhySpeed> {
319+
match self {
320+
EthernetPhy::LAN8720A(phy) => phy.link_speed(),
321+
EthernetPhy::LAN8742A(phy) => phy.link_speed(),
322+
EthernetPhy::KSZ8081R(phy) => phy.link_speed(),
323+
}
324+
}
312325
}

examples/rtic-echo.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,10 @@ mod app {
2525

2626
use crate::common::EthernetPhy;
2727

28+
use ieee802_3_miim::{phy::PhySpeed, Phy};
2829
use systick_monotonic::Systick;
2930

30-
use stm32_eth::{EthernetDMA, RxRingEntry, TxRingEntry};
31+
use stm32_eth::{mac::Speed, EthernetDMA, RxRingEntry, TxRingEntry};
3132

3233
use smoltcp::{
3334
iface::{self, Interface, SocketHandle},
@@ -131,8 +132,20 @@ mod app {
131132
);
132133

133134
phy.phy_init();
135+
136+
if let Some(speed) = phy.speed().map(|s| match s {
137+
PhySpeed::HalfDuplexBase10T => Speed::HalfDuplexBase10T,
138+
PhySpeed::FullDuplexBase10T => Speed::FullDuplexBase10T,
139+
PhySpeed::HalfDuplexBase100Tx => Speed::HalfDuplexBase100Tx,
140+
PhySpeed::FullDuplexBase100Tx => Speed::FullDuplexBase100Tx,
141+
}) {
142+
phy.get_miim().set_speed(speed);
143+
defmt::info!("Detected link speed: {}", speed);
144+
} else {
145+
defmt::warn!("Failed to detect link speed.");
146+
}
134147
} else {
135-
defmt::info!("Not resetting unsupported PHY.");
148+
defmt::info!("Not resetting unsupported PHY. Cannot detect link speed.");
136149
}
137150

138151
defmt::info!("Setup done. Listening at {}", crate::ADDRESS);

src/lib.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#![no_std]
55
#![deny(missing_docs)]
66

7+
use mac::Speed;
78
/// Re-export
89
#[cfg(feature = "stm32f7xx-hal")]
910
pub use stm32f7xx_hal as hal;
@@ -87,6 +88,9 @@ const MTU: usize = 1522;
8788
/// and configures the ETH MAC and DMA peripherals.
8889
/// Automatically sets slew rate to VeryHigh.
8990
///
91+
/// The speed of the MAC is set to [`Speed::FullDuplexBase100Tx`].
92+
/// This can be changed using [`EthernetMAC::set_speed`].
93+
///
9094
/// This method does not initialise the external PHY. Interacting with a PHY
9195
/// can be done by using the struct returned from [`EthernetMAC::mii`].
9296
///
@@ -127,7 +131,7 @@ where
127131
let dma = EthernetDMA::new(eth_dma, &eth_mac, rx_buffer, tx_buffer);
128132

129133
// Configure the ethernet MAC
130-
let mac = EthernetMAC::new(eth_mac, eth_mmc, &dma, clocks)?;
134+
let mac = EthernetMAC::new(eth_mac, eth_mmc, &dma, clocks, Speed::FullDuplexBase100Tx)?;
131135

132136
Ok((dma, mac))
133137
}
@@ -141,6 +145,9 @@ where
141145
///
142146
/// This method does not initialise the external PHY.
143147
///
148+
/// The speed of the MAC is set to [`Speed::FullDuplexBase100Tx`].
149+
/// This can be changed using [`EthernetMAC::set_speed`].
150+
///
144151
/// The MII for the external PHY can be accessed through the
145152
/// returned [`EthernetMACWithMii`], .
146153
///
@@ -185,7 +192,8 @@ where
185192
let dma = EthernetDMA::new(eth_dma, &eth_mac, rx_buffer, tx_buffer);
186193

187194
// Configure the ethernet MAC
188-
let mac = EthernetMAC::new(eth_mac, eth_mmc, &dma, clocks)?.with_mii(mdio, mdc);
195+
let mac = EthernetMAC::new(eth_mac, eth_mmc, &dma, clocks, Speed::FullDuplexBase100Tx)?
196+
.with_mii(mdio, mdc);
189197

190198
Ok((dma, mac))
191199
}

src/mac/mod.rs

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Ethernet MAC driver implementation
22
3-
use core::ops::Deref;
3+
use core::ops::{Deref, DerefMut};
44

55
use crate::{
66
hal::rcc::Clocks,
@@ -11,6 +11,20 @@ use crate::{
1111
mod miim;
1212
pub use miim::*;
1313

14+
/// Speeds at which this MAC can be configured
15+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
16+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
17+
pub enum Speed {
18+
/// 10Base-T half duplex
19+
HalfDuplexBase10T,
20+
/// 10Base-T full duplex
21+
FullDuplexBase10T,
22+
/// 100Base-Tx half duplex
23+
HalfDuplexBase100Tx,
24+
/// 100Base-Tx full duplex
25+
FullDuplexBase100Tx,
26+
}
27+
1428
mod consts {
1529
/* For HCLK 60-100 MHz */
1630
pub const ETH_MACMIIAR_CR_HCLK_DIV_42: u8 = 0;
@@ -54,6 +68,7 @@ impl EthernetMAC {
5468
// this function.
5569
#[allow(unused)] eth_dma: &EthernetDMA,
5670
clocks: Clocks,
71+
initial_speed: Speed,
5772
) -> Result<Self, WrongClock> {
5873
let clock_frequency = clocks.hclk().to_Hz();
5974

@@ -132,7 +147,11 @@ impl EthernetMAC {
132147
.mmctimr
133148
.modify(|r, w| unsafe { w.bits(r.bits() | (1 << 21)) });
134149

135-
Ok(Self { eth_mac })
150+
let mut me = Self { eth_mac };
151+
152+
me.set_speed(initial_speed);
153+
154+
Ok(me)
136155
}
137156

138157
/// Borrow access to the MAC's SMI.
@@ -166,6 +185,31 @@ impl EthernetMAC {
166185
mdc,
167186
}
168187
}
188+
189+
/// Set the Ethernet Speed at which the MAC communicates
190+
///
191+
/// Note that this does _not_ affect the PHY in any way. To
192+
/// configure the PHY, use [`EthernetMACWithMii`] (see: [`Self::with_mii`])
193+
/// or [`Stm32Mii`] (see: [`Self::mii`])
194+
pub fn set_speed(&mut self, speed: Speed) {
195+
self.eth_mac.maccr.modify(|_, w| match speed {
196+
Speed::HalfDuplexBase10T => w.fes().clear_bit().dm().clear_bit(),
197+
Speed::FullDuplexBase10T => w.fes().clear_bit().dm().set_bit(),
198+
Speed::HalfDuplexBase100Tx => w.fes().set_bit().dm().clear_bit(),
199+
Speed::FullDuplexBase100Tx => w.fes().set_bit().dm().set_bit(),
200+
});
201+
}
202+
203+
/// Get the Ethernet Speed at which the MAC communicates
204+
pub fn get_speed(&self) -> Speed {
205+
let cr = self.eth_mac.maccr.read();
206+
match (cr.fes().bit_is_set(), cr.dm().bit_is_set()) {
207+
(false, false) => Speed::HalfDuplexBase10T,
208+
(false, true) => Speed::FullDuplexBase10T,
209+
(true, false) => Speed::HalfDuplexBase100Tx,
210+
(true, true) => Speed::FullDuplexBase100Tx,
211+
}
212+
}
169213
}
170214

171215
/// Ethernet media access control (MAC) with owned MII
@@ -217,6 +261,16 @@ where
217261
}
218262
}
219263

264+
impl<MDIO, MDC> DerefMut for EthernetMACWithMii<MDIO, MDC>
265+
where
266+
MDIO: MdioPin,
267+
MDC: MdcPin,
268+
{
269+
fn deref_mut(&mut self) -> &mut Self::Target {
270+
&mut self.eth_mac
271+
}
272+
}
273+
220274
impl<MDIO, MDC> EthernetMACWithMii<MDIO, MDC>
221275
where
222276
MDIO: MdioPin,

0 commit comments

Comments
 (0)