diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 4128040..06fe857 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -76,6 +76,16 @@ jobs:
- stm32f777
- stm32f778
- stm32f779
+ - stm32h735
+ - stm32h742
+ - stm32h742v
+ - stm32h743
+ - stm32h743v
+ - stm32h747cm7
+ - stm32h750
+ - stm32h750v
+ - stm32h753
+ - stm32h753v
steps:
- name: Checkout
uses: actions/checkout@v3
@@ -103,6 +113,7 @@ jobs:
- stm32f107
- stm32f407
- stm32f745
+ - stm32h735
steps:
- name: Checkout
uses: actions/checkout@v3
@@ -138,6 +149,7 @@ jobs:
- stm32f107
- stm32f429
- stm32f745
+ - stm32h735
toolchain:
- stable
target:
diff --git a/Cargo.toml b/Cargo.toml
index e867aed..c530d96 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -25,6 +25,7 @@ stm32f7xx-hal = { version = "0.7.0", optional = true }
stm32f4xx-hal = { version = "0.14", optional = true }
stm32f4 = { version = "0.15", optional = true }
stm32f1xx-hal = { version = "0.10", optional = true }
+stm32h7xx-hal = { version = "0.13", optional = true }
ieee802_3_miim = "0.8"
cortex-m = "0.7"
log = { version = "0.4", optional = true }
@@ -40,6 +41,12 @@ default = [ "defmt", "ptp" ]
device-selected = []
fence = []
ptp = [ ]
+f-series = [ ]
+
+stm32f1xx-hal = [ "dep:stm32f1xx-hal", "f-series" ]
+stm32f4xx-hal = [ "dep:stm32f4xx-hal", "f-series" ]
+stm32f7xx-hal = [ "dep:stm32f7xx-hal", "f-series" ]
+stm32h7xx-hal = [ "dep:stm32h7xx-hal" ]
stm32f107 = ["stm32f1xx-hal/stm32f107", "device-selected"]
@@ -62,6 +69,17 @@ stm32f777 = ["stm32f7xx-hal/stm32f777", "device-selected", "fence"]
stm32f778 = ["stm32f7xx-hal/stm32f778", "device-selected", "fence"]
stm32f779 = ["stm32f7xx-hal/stm32f779", "device-selected", "fence"]
+stm32h735 = ["device-selected", "fence", "stm32h7xx-hal/stm32h735", ]
+stm32h742 = ["device-selected", "fence", "stm32h7xx-hal/stm32h742",]
+stm32h742v = ["device-selected", "fence", "stm32h7xx-hal/stm32h742v"]
+stm32h743 = ["device-selected", "fence", "stm32h7xx-hal/stm32h743"]
+stm32h743v = ["device-selected", "fence", "stm32h7xx-hal/stm32h743v"]
+stm32h747cm7 = ["device-selected", "fence", "stm32h7xx-hal/stm32h747cm7"]
+stm32h750 = ["device-selected", "fence", "stm32h7xx-hal/stm32h750"]
+stm32h750v = ["device-selected", "fence", "stm32h7xx-hal/stm32h750v"]
+stm32h753 = ["device-selected", "fence", "stm32h7xx-hal/stm32h753"]
+stm32h753v = ["device-selected", "fence", "stm32h7xx-hal/stm32h753v"]
+
smoltcp-phy = ["smoltcp"]
[dev-dependencies]
@@ -73,6 +91,7 @@ defmt-rtt = "0.4"
panic-probe = { version = "0.3", features = [ "print-defmt" ] }
systick-monotonic = "1.0"
smoltcp = { version = "0.9", features = [ "medium-ethernet", "proto-ipv4", "socket-udp", "socket-tcp", "defmt" ], default-features = false }
+siphasher = "0.3"
[[example]]
name = "pktgen"
diff --git a/README.md b/README.md
index bc7bd67..6dbebad 100644
--- a/README.md
+++ b/README.md
@@ -25,14 +25,14 @@ stm32-eth = { version = "0.3.0", features = ["stm32f107"] } # For stm32f107
In `src/main.rs` add:
```rust,no_run
+use fugit::RateExtU32;
use stm32_eth::{
+ dma::{RxDescriptor, RxDescriptorRing, TxDescriptor, TxDescriptorRing},
hal::gpio::GpioExt,
hal::rcc::RccExt,
stm32::Peripherals,
- dma::{RxRingEntry, TxRingEntry},
- EthPins,
+ EthPins, MTU,
};
-use fugit::RateExtU32;
fn main() {
let p = Peripherals::take().unwrap();
@@ -56,8 +56,13 @@ fn main() {
rx_d1: gpioc.pc5,
};
- let mut rx_ring: [RxRingEntry; 16] = Default::default();
- let mut tx_ring: [TxRingEntry; 8] = Default::default();
+ let mut rx_ring: [RxDescriptor; 16] = Default::default();
+ let mut rx_buffers: [[u8; MTU + 2]; 16] = [[0u8; MTU + 2]; 16];
+ let rx_ring = RxDescriptorRing::new(&mut rx_ring[..], &mut rx_buffers[..]);
+
+ let mut tx_ring: [TxDescriptor; 8] = Default::default();
+ let mut tx_buffers: [[u8; MTU + 2]; 8] = [[0u8; MTU + 2]; 8];
+ let tx_ring = TxDescriptorRing::new(&mut tx_ring[..], &mut tx_buffers[..]);
let parts = stm32_eth::PartsIn {
mac: p.ETHERNET_MAC,
@@ -66,14 +71,11 @@ fn main() {
ptp: p.ETHERNET_PTP,
};
- let stm32_eth::Parts { dma: mut eth_dma, mac: _, ptp: _ } = stm32_eth::new(
- parts,
- &mut rx_ring[..],
- &mut tx_ring[..],
- clocks,
- eth_pins,
- )
- .unwrap();
+ let stm32_eth::Parts {
+ dma: mut eth_dma,
+ mac: _,
+ ptp: _,
+ } = stm32_eth::new(parts, rx_ring, tx_ring, clocks, eth_pins).unwrap();
eth_dma.enable_interrupt();
if let Ok(pkt) = eth_dma.recv_next(None) {
@@ -81,9 +83,11 @@ fn main() {
}
let size = 42;
- eth_dma.send(size, None, |buf| {
- // write up to `size` bytes into buf before it is being sent
- }).expect("send");
+ eth_dma
+ .send(size, None, |buf| {
+ // write up to `size` bytes into buf before it is being sent
+ })
+ .expect("send");
}
```
diff --git a/build.rs b/build.rs
index 9700e20..29386fa 100644
--- a/build.rs
+++ b/build.rs
@@ -1,5 +1,4 @@
fn main() {
- #[cfg(feature = "stm32f1xx-hal")]
println!("cargo:rustc-link-search=memory.x");
let hse = std::env::var("STM32_ETH_EXAMPLE_HSE");
diff --git a/examples/arp.rs b/examples/arp.rs
index 1406a28..129044a 100644
--- a/examples/arp.rs
+++ b/examples/arp.rs
@@ -8,6 +8,7 @@
#![no_main]
use defmt_rtt as _;
+use ieee802_3_miim::{phy::BarePhy, Phy};
use panic_probe as _;
use core::cell::RefCell;
@@ -16,14 +17,13 @@ use cortex_m_rt::{entry, exception};
use cortex_m::interrupt::Mutex;
use stm32_eth::{
- mac::{phy::BarePhy, Phy},
stm32::{interrupt, CorePeripherals, Peripherals, SYST},
Parts,
};
pub mod common;
-use stm32_eth::dma::{RxRingEntry, TxError, TxRingEntry};
+use stm32_eth::dma::TxError;
const PHY_ADDR: u8 = 0;
@@ -43,22 +43,14 @@ fn main() -> ! {
let (eth_pins, mdio, mdc, _) = common::setup_pins(gpio);
- let mut rx_ring: [RxRingEntry; 2] = Default::default();
- let mut tx_ring: [TxRingEntry; 2] = Default::default();
+ let (tx_ring, rx_ring) = crate::common::setup_rings();
let Parts {
mut dma,
mac,
#[cfg(feature = "ptp")]
ptp: _,
- } = stm32_eth::new(
- ethernet,
- &mut rx_ring[..],
- &mut tx_ring[..],
- clocks,
- eth_pins,
- )
- .unwrap();
+ } = stm32_eth::new(ethernet, rx_ring, tx_ring, clocks, eth_pins).unwrap();
dma.enable_interrupt();
let mut last_link_up = false;
@@ -109,14 +101,32 @@ fn main() -> ! {
buf[38..42].copy_from_slice(&TARGET_IP);
});
+ loop {
+ use core::hash::{Hash, Hasher};
+
+ if let Ok(rx_packet) = dma.recv_next(None) {
+ let mut hasher = siphasher::sip::SipHasher::new();
+ rx_packet.hash(&mut hasher);
+
+ defmt::info!(
+ "Received {} bytes. Hash: {:016X}",
+ rx_packet.len(),
+ hasher.finish()
+ );
+ break;
+ }
+ }
+
match r {
Ok(()) => {
defmt::info!("ARP sent");
}
- Err(TxError::WouldBlock) => defmt::info!("ARP failed"),
+ Err(TxError::WouldBlock) => {
+ defmt::info!("ARP failed. {}", dma.tx_state())
+ }
}
} else {
- defmt::info!("Down");
+ // defmt::info!("Down");
}
cortex_m::interrupt::free(|cs| {
diff --git a/examples/common.rs b/examples/common.rs
index c1b095d..af687a9 100644
--- a/examples/common.rs
+++ b/examples/common.rs
@@ -4,16 +4,52 @@
//!
//! Note that this module isn't an example by itself.
+use core::mem::MaybeUninit;
+
use stm32_eth::{
- hal::{gpio::GpioExt, rcc::Clocks},
- PartsIn,
+ dma::{RxDescriptor, RxDescriptorRing, TxDescriptor, TxDescriptorRing},
+ hal::gpio::GpioExt,
+ PartsIn, MTU,
};
+#[cfg(feature = "f-series")]
+use stm32_eth::hal::rcc::Clocks;
+
+#[cfg(feature = "stm32h7xx-hal")]
+use stm32_eth::hal::rcc::CoreClocks as Clocks;
+
pub use pins::{setup_pins, Gpio};
use fugit::RateExtU32;
use stm32_eth::hal::rcc::RccExt;
+const NUM_DESCRIPTORS: usize = 4;
+
+/// On H7s, the ethernet DMA does not have access to the normal ram
+/// so we must explicitly put them in SRAM.
+#[cfg_attr(feature = "stm32h7xx-hal", link_section = ".sram1.eth")]
+static mut TX_DESCRIPTORS: MaybeUninit<[TxDescriptor; NUM_DESCRIPTORS]> = MaybeUninit::uninit();
+#[cfg_attr(feature = "stm32h7xx-hal", link_section = ".sram1.eth")]
+static mut TX_BUFFERS: MaybeUninit<[[u8; MTU + 2]; NUM_DESCRIPTORS]> = MaybeUninit::uninit();
+#[cfg_attr(feature = "stm32h7xx-hal", link_section = ".sram1.eth")]
+static mut RX_DESCRIPTORS: MaybeUninit<[RxDescriptor; NUM_DESCRIPTORS]> = MaybeUninit::uninit();
+#[cfg_attr(feature = "stm32h7xx-hal", link_section = ".sram1.eth")]
+static mut RX_BUFFERS: MaybeUninit<[[u8; MTU + 2]; NUM_DESCRIPTORS]> = MaybeUninit::uninit();
+
+/// Set up the buffers to be used
+pub fn setup_rings() -> (TxDescriptorRing<'static>, RxDescriptorRing<'static>) {
+ let tx_desc = unsafe { TX_DESCRIPTORS.write([TxDescriptor::new(); NUM_DESCRIPTORS]) };
+ let tx_buf = unsafe { TX_BUFFERS.write([[0u8; MTU + 2]; NUM_DESCRIPTORS]) };
+
+ let rx_desc = unsafe { RX_DESCRIPTORS.write([RxDescriptor::new(); NUM_DESCRIPTORS]) };
+ let rx_buf = unsafe { RX_BUFFERS.write([[0u8; MTU + 2]; NUM_DESCRIPTORS]) };
+
+ (
+ TxDescriptorRing::new(tx_desc, tx_buf),
+ RxDescriptorRing::new(rx_desc, rx_buf),
+ )
+}
+
/// Setup the clocks and return clocks and a GPIO struct that
/// can be used to set up all of the pins.
///
@@ -23,8 +59,11 @@ pub fn setup_peripherals(p: stm32_eth::stm32::Peripherals) -> (Clocks, Gpio, Par
let ethernet = PartsIn {
dma: p.ETHERNET_DMA,
mac: p.ETHERNET_MAC,
+ #[cfg(feature = "stm32h7xx-hal")]
+ mtl: p.ETHERNET_MTL,
+ #[cfg(feature = "f-series")]
mmc: p.ETHERNET_MMC,
- #[cfg(feature = "ptp")]
+ #[cfg(all(feature = "ptp", feature = "f-series"))]
ptp: p.ETHERNET_PTP,
};
@@ -99,6 +138,40 @@ pub fn setup_peripherals(p: stm32_eth::stm32::Peripherals) -> (Clocks, Gpio, Par
(clocks, gpio, ethernet)
}
+
+ #[cfg(feature = "stm32h7xx-hal")]
+ {
+ use stm32_eth::hal::pwr::PwrExt;
+
+ let rcc = p.RCC.constrain();
+ let pwr = p.PWR.constrain();
+
+ let syscfg = p.SYSCFG;
+
+ let pwrcfg = pwr.vos0(&syscfg).freeze();
+
+ let rcc = rcc.hclk(240.MHz()).sys_ck(240.MHz());
+
+ let rcc = if cfg!(hse = "bypass") {
+ rcc.bypass_hse().use_hse(8.MHz())
+ } else if cfg!(hse = "oscillator") {
+ rcc.use_hse(8.MHz())
+ } else {
+ rcc
+ };
+
+ let ccdr = rcc.freeze(pwrcfg, &syscfg);
+ let clocks = ccdr.clocks;
+
+ let gpio = Gpio {
+ gpioa: p.GPIOA.split(ccdr.peripheral.GPIOA),
+ gpiob: p.GPIOB.split(ccdr.peripheral.GPIOB),
+ gpioc: p.GPIOC.split(ccdr.peripheral.GPIOC),
+ gpiog: p.GPIOG.split(ccdr.peripheral.GPIOG),
+ };
+
+ (clocks, gpio, ethernet)
+ }
}
pub use pins::*;
@@ -280,6 +353,96 @@ mod pins {
}
}
+#[cfg(feature = "stm32h7xx-hal")]
+mod pins {
+ use stm32_eth::{
+ hal::gpio::{Input, PushPull, *},
+ EthPins,
+ };
+
+ pub struct Gpio {
+ pub gpioa: gpioa::Parts,
+ pub gpiob: gpiob::Parts,
+ pub gpioc: gpioc::Parts,
+ pub gpiog: gpiog::Parts,
+ }
+
+ pub type RefClk = PA1;
+ pub type Crs = PA7;
+
+ #[cfg(pins = "nucleo")]
+ pub type TxEn = PG11;
+ #[cfg(pins = "nucleo")]
+ pub type TxD0 = PG13;
+
+ #[cfg(not(pins = "nucleo"))]
+ pub type TxEn = PB11;
+ #[cfg(not(pins = "nucleo"))]
+ pub type TxD0 = PB12;
+
+ pub type TxD1 = PB13;
+ pub type RxD0 = PC4;
+ pub type RxD1 = PC5;
+
+ #[cfg(not(pps = "alternate"))]
+ pub type Pps = PB5