-
-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
fc3ceea
commit 4ae71ea
Showing
6 changed files
with
589 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
[target.'cfg(all(target_arch = "arm", target_os = "none"))'] | ||
runner = "probe-rs run --chip STM32F429ZITx" | ||
rustflags = [ | ||
"-C", "link-arg=-Tlink.x", | ||
"-C", "link-arg=-Tdefmt.x", | ||
] | ||
|
||
|
||
[build] | ||
target = "thumbv7em-none-eabi" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
target/ | ||
Cargo.lock |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
[package] | ||
version = "0.1.0" | ||
name = "stm32-rtic" | ||
edition = "2021" | ||
resolver = "2" | ||
|
||
[dependencies] | ||
volatile-register = "0.2" | ||
aligned = "0.4" | ||
stm32f4xx-hal = { version = "0.14", features = ["stm32f429"] } | ||
stm32f4 = { version = "0.15" } | ||
ieee802_3_miim = "0.8" | ||
defmt = { version = "0.3" } | ||
futures = { version = "0.3", default-features = false, features = [ | ||
"async-await", | ||
] } | ||
cortex-m = { version = "0.7", features = ["critical-section-single-core"] } | ||
cortex-m-rt = "0.7" | ||
fugit = "0.3" | ||
defmt-rtt = "0.4" | ||
panic-probe = { version = "0.3", features = ["print-defmt"] } | ||
systick-monotonic = "1.0" | ||
rtic = { version = "2.0.1", features = ["thumbv7-backend"] } | ||
stm32-eth = { version = "0.5.2", default-features = false, features = ["defmt", "stm32f429", "async-await"] } | ||
|
||
[profile.release] | ||
debug = 2 | ||
lto = true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
[toolchain] | ||
channel = "nightly" | ||
components = ["llvm-tools"] | ||
targets = ["thumbv7em-none-eabi"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,284 @@ | ||
//! Common features used in examples. | ||
//! | ||
//! Note that this module isn't an example by itself. | ||
|
||
use defmt_rtt as _; | ||
use panic_probe as _; | ||
|
||
use stm32_eth::{ | ||
hal::{ | ||
gpio::{GpioExt, *}, | ||
rcc::Clocks, | ||
}, | ||
EthPins, PartsIn, | ||
}; | ||
|
||
use fugit::RateExtU32; | ||
use stm32_eth::hal::rcc::RccExt; | ||
|
||
/// Setup the clocks and return clocks and a GPIO struct that | ||
/// can be used to set up all of the pins. | ||
/// | ||
/// This configures HCLK to be at least 25 MHz, which is the minimum required | ||
/// for ethernet operation to be valid. | ||
pub fn setup_peripherals(p: stm32_eth::stm32::Peripherals) -> (Clocks, Gpio, PartsIn) { | ||
let ethernet = PartsIn { | ||
dma: p.ETHERNET_DMA, | ||
mac: p.ETHERNET_MAC, | ||
mmc: p.ETHERNET_MMC, | ||
#[cfg(feature = "ptp")] | ||
ptp: p.ETHERNET_PTP, | ||
}; | ||
|
||
let rcc = p.RCC.constrain(); | ||
|
||
let clocks = rcc.cfgr.sysclk(96.MHz()).hclk(96.MHz()); | ||
|
||
#[cfg(feature = "stm32f4xx-hal")] | ||
let clocks = { | ||
if cfg!(hse = "bypass") { | ||
clocks.use_hse(8.MHz()).bypass_hse_oscillator() | ||
} else if cfg!(hse = "oscillator") { | ||
clocks.use_hse(8.MHz()) | ||
} else { | ||
clocks | ||
} | ||
}; | ||
|
||
#[cfg(feature = "stm32f7xx-hal")] | ||
let clocks = { | ||
if cfg!(hse = "bypass") { | ||
clocks.hse(stm32_eth::hal::rcc::HSEClock::new( | ||
8.MHz(), | ||
stm32_eth::hal::rcc::HSEClockMode::Bypass, | ||
)) | ||
} else if cfg!(hse = "oscillator") { | ||
clocks.hse(stm32_eth::hal::rcc::HSEClock::new( | ||
8.MHz(), | ||
stm32_eth::hal::rcc::HSEClockMode::Oscillator, | ||
)) | ||
} else { | ||
clocks | ||
} | ||
}; | ||
|
||
let clocks = clocks.freeze(); | ||
|
||
let gpio = Gpio { | ||
gpioa: p.GPIOA.split(), | ||
gpiob: p.GPIOB.split(), | ||
gpioc: p.GPIOC.split(), | ||
gpiog: p.GPIOG.split(), | ||
}; | ||
|
||
(clocks, gpio, ethernet) | ||
} | ||
|
||
pub struct Gpio { | ||
pub gpioa: gpioa::Parts, | ||
pub gpiob: gpiob::Parts, | ||
pub gpioc: gpioc::Parts, | ||
pub gpiog: gpiog::Parts, | ||
} | ||
|
||
pub type RefClk = PA1<Input>; | ||
pub type Crs = PA7<Input>; | ||
pub type TxD1 = PB13<Input>; | ||
pub type RxD0 = PC4<Input>; | ||
pub type RxD1 = PC5<Input>; | ||
|
||
#[cfg(not(pins = "nucleo"))] | ||
pub type TxEn = PB11<Input>; | ||
#[cfg(not(pins = "nucleo"))] | ||
pub type TxD0 = PB12<Input>; | ||
|
||
#[cfg(pins = "nucleo")] | ||
pub type TxEn = PG11<Input>; | ||
#[cfg(pins = "nucleo")] | ||
pub type TxD0 = PG13<Input>; | ||
|
||
pub type Mdio = PA2<Alternate<11>>; | ||
pub type Mdc = PC1<Alternate<11>>; | ||
|
||
#[cfg(not(pps = "alternate"))] | ||
pub type Pps = PB5<Output<PushPull>>; | ||
|
||
#[cfg(pps = "alternate")] | ||
pub type Pps = PG8<Output<PushPull>>; | ||
|
||
pub fn setup_pins( | ||
gpio: Gpio, | ||
) -> ( | ||
EthPins<RefClk, Crs, TxEn, TxD0, TxD1, RxD0, RxD1>, | ||
Mdio, | ||
Mdc, | ||
Pps, | ||
) { | ||
#[allow(unused_variables)] | ||
let Gpio { | ||
gpioa, | ||
gpiob, | ||
gpioc, | ||
gpiog, | ||
} = gpio; | ||
|
||
let ref_clk = gpioa.pa1.into_floating_input(); | ||
let crs = gpioa.pa7.into_floating_input(); | ||
let tx_d1 = gpiob.pb13.into_floating_input(); | ||
let rx_d0 = gpioc.pc4.into_floating_input(); | ||
let rx_d1 = gpioc.pc5.into_floating_input(); | ||
|
||
#[cfg(not(pins = "nucleo"))] | ||
let (tx_en, tx_d0) = ( | ||
gpiob.pb11.into_floating_input(), | ||
gpiob.pb12.into_floating_input(), | ||
); | ||
|
||
#[cfg(pins = "nucleo")] | ||
let (tx_en, tx_d0) = { | ||
( | ||
gpiog.pg11.into_floating_input(), | ||
gpiog.pg13.into_floating_input(), | ||
) | ||
}; | ||
|
||
#[cfg(feature = "stm32f4xx-hal")] | ||
let (mdio, mdc) = { | ||
let mut mdio = gpioa.pa2.into_alternate(); | ||
mdio.set_speed(Speed::VeryHigh); | ||
let mut mdc = gpioc.pc1.into_alternate(); | ||
mdc.set_speed(Speed::VeryHigh); | ||
(mdio, mdc) | ||
}; | ||
|
||
#[cfg(any(feature = "stm32f7xx-hal"))] | ||
let (mdio, mdc) = ( | ||
gpioa.pa2.into_alternate().set_speed(Speed::VeryHigh), | ||
gpioc.pc1.into_alternate().set_speed(Speed::VeryHigh), | ||
); | ||
|
||
#[cfg(not(pps = "alternate"))] | ||
let pps = gpiob.pb5.into_push_pull_output(); | ||
#[cfg(pps = "alternate")] | ||
let pps = gpiog.pg8.into_push_pull_output(); | ||
|
||
( | ||
EthPins { | ||
ref_clk, | ||
crs, | ||
tx_en, | ||
tx_d0, | ||
tx_d1, | ||
rx_d0, | ||
rx_d1, | ||
}, | ||
mdio, | ||
mdc, | ||
pps, | ||
) | ||
} | ||
|
||
use ieee802_3_miim::{ | ||
phy::{ | ||
lan87xxa::{LAN8720A, LAN8742A}, | ||
BarePhy, KSZ8081R, | ||
}, | ||
Miim, Pause, Phy, | ||
}; | ||
|
||
/// An ethernet PHY | ||
pub enum EthernetPhy<M: Miim> { | ||
/// LAN8720A | ||
LAN8720A(LAN8720A<M>), | ||
/// LAN8742A | ||
LAN8742A(LAN8742A<M>), | ||
/// KSZ8081R | ||
KSZ8081R(KSZ8081R<M>), | ||
} | ||
|
||
impl<M: Miim> Phy<M> for EthernetPhy<M> { | ||
fn best_supported_advertisement(&self) -> ieee802_3_miim::AutoNegotiationAdvertisement { | ||
match self { | ||
EthernetPhy::LAN8720A(phy) => phy.best_supported_advertisement(), | ||
EthernetPhy::LAN8742A(phy) => phy.best_supported_advertisement(), | ||
EthernetPhy::KSZ8081R(phy) => phy.best_supported_advertisement(), | ||
} | ||
} | ||
|
||
fn get_miim(&mut self) -> &mut M { | ||
match self { | ||
EthernetPhy::LAN8720A(phy) => phy.get_miim(), | ||
EthernetPhy::LAN8742A(phy) => phy.get_miim(), | ||
EthernetPhy::KSZ8081R(phy) => phy.get_miim(), | ||
} | ||
} | ||
|
||
fn get_phy_addr(&self) -> u8 { | ||
match self { | ||
EthernetPhy::LAN8720A(phy) => phy.get_phy_addr(), | ||
EthernetPhy::LAN8742A(phy) => phy.get_phy_addr(), | ||
EthernetPhy::KSZ8081R(phy) => phy.get_phy_addr(), | ||
} | ||
} | ||
} | ||
|
||
impl<M: Miim> EthernetPhy<M> { | ||
/// Attempt to create one of the known PHYs from the given | ||
/// MIIM. | ||
/// | ||
/// Returns an error if the PHY does not support the extended register | ||
/// set, or if the PHY's identifier does not correspond to a known PHY. | ||
pub fn from_miim(miim: M, phy_addr: u8) -> Result<Self, M> { | ||
let mut bare = BarePhy::new(miim, phy_addr, Pause::NoPause); | ||
let phy_ident = if let Some(id) = bare.phy_ident() { | ||
id.raw_u32() | ||
} else { | ||
return Err(bare.release()); | ||
}; | ||
let miim = bare.release(); | ||
match phy_ident & 0xFFFFFFF0 { | ||
0x0007C0F0 => Ok(Self::LAN8720A(LAN8720A::new(miim, phy_addr))), | ||
0x0007C130 => Ok(Self::LAN8742A(LAN8742A::new(miim, phy_addr))), | ||
0x00221560 => Ok(Self::KSZ8081R(KSZ8081R::new(miim, phy_addr))), | ||
_ => Err(miim), | ||
} | ||
} | ||
|
||
/// Get a string describing the type of PHY | ||
pub const fn ident_string(&self) -> &'static str { | ||
match self { | ||
EthernetPhy::LAN8720A(_) => "LAN8720A", | ||
EthernetPhy::LAN8742A(_) => "LAN8742A", | ||
EthernetPhy::KSZ8081R(_) => "KSZ8081R", | ||
} | ||
} | ||
|
||
/// Initialize the PHY | ||
pub fn phy_init(&mut self) { | ||
match self { | ||
EthernetPhy::LAN8720A(phy) => phy.phy_init(), | ||
EthernetPhy::LAN8742A(phy) => phy.phy_init(), | ||
EthernetPhy::KSZ8081R(phy) => { | ||
phy.set_autonegotiation_advertisement(phy.best_supported_advertisement()); | ||
} | ||
} | ||
} | ||
|
||
#[allow(dead_code)] | ||
pub fn speed(&mut self) -> Option<ieee802_3_miim::phy::PhySpeed> { | ||
match self { | ||
EthernetPhy::LAN8720A(phy) => phy.link_speed(), | ||
EthernetPhy::LAN8742A(phy) => phy.link_speed(), | ||
EthernetPhy::KSZ8081R(phy) => phy.link_speed(), | ||
} | ||
} | ||
|
||
#[allow(dead_code)] | ||
pub fn release(self) -> M { | ||
match self { | ||
EthernetPhy::LAN8720A(phy) => phy.release(), | ||
EthernetPhy::LAN8742A(phy) => phy.release(), | ||
EthernetPhy::KSZ8081R(phy) => phy.release(), | ||
} | ||
} | ||
} |
Oops, something went wrong.