#![no_std]
#![deny(missing_docs)]
#[cfg(not(feature = "device-selected"))]
compile_error!("No device was selected! Exactly one stm32fxxx feature must be selected.");
#[cfg(feature = "stm32f7xx-hal")]
pub use stm32f7xx_hal as hal;
#[cfg(feature = "stm32f4xx-hal")]
pub use stm32f4xx_hal as hal;
#[cfg(feature = "stm32f1xx-hal")]
pub use stm32f1xx_hal as hal;
#[cfg(feature = "device-selected")]
pub use hal::pac as stm32;
#[cfg(feature = "device-selected")]
use hal::rcc::Clocks;
#[cfg(feature = "device-selected")]
pub mod dma;
#[cfg(feature = "device-selected")]
pub mod mac;
#[cfg(feature = "device-selected")]
pub mod setup;
#[doc(inline)]
#[cfg(feature = "device-selected")]
pub use setup::{EthPins, Parts, PartsIn};
#[cfg(feature = "device-selected")]
pub(crate) mod peripherals;
#[cfg(feature = "ptp")]
pub mod ptp;
#[cfg(feature = "smoltcp-phy")]
pub use smoltcp;
#[cfg(feature = "device-selected")]
use {
dma::{EthernetDMA, RxRingEntry, TxRingEntry},
mac::{EthernetMAC, EthernetMACWithMii, MdcPin, MdioPin, Speed, WrongClock},
setup::*,
};
#[cfg(all(feature = "device-selected", feature = "ptp"))]
use ptp::EthernetPTP;
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct InterruptReason {
pub rx: bool,
pub tx: bool,
pub dma_error: bool,
#[cfg(all(feature = "ptp", not(feature = "stm32f1xx-hal")))]
pub time_passed: bool,
}
#[cfg(feature = "device-selected")]
pub fn eth_interrupt_handler() -> InterruptReason {
let dma = EthernetDMA::interrupt_handler();
#[cfg(all(feature = "ptp", not(feature = "stm32f1xx-hal")))]
let is_time_trigger = EthernetPTP::interrupt_handler();
InterruptReason {
rx: dma.is_rx,
tx: dma.is_tx,
dma_error: dma.is_error,
#[cfg(all(feature = "ptp", not(feature = "stm32f1xx-hal")))]
time_passed: is_time_trigger,
}
}
#[cfg(feature = "device-selected")]
pub fn new<'rx, 'tx, REFCLK, CRS, TXEN, TXD0, TXD1, RXD0, RXD1>(
parts: PartsIn,
rx_buffer: &'rx mut [RxRingEntry],
tx_buffer: &'tx mut [TxRingEntry],
clocks: Clocks,
pins: EthPins<REFCLK, CRS, TXEN, TXD0, TXD1, RXD0, RXD1>,
) -> Result<Parts<'rx, 'tx, EthernetMAC>, WrongClock>
where
REFCLK: RmiiRefClk + AlternateVeryHighSpeed,
CRS: RmiiCrsDv + AlternateVeryHighSpeed,
TXEN: RmiiTxEN + AlternateVeryHighSpeed,
TXD0: RmiiTxD0 + AlternateVeryHighSpeed,
TXD1: RmiiTxD1 + AlternateVeryHighSpeed,
RXD0: RmiiRxD0 + AlternateVeryHighSpeed,
RXD1: RmiiRxD1 + AlternateVeryHighSpeed,
{
pins.setup_pins();
setup::setup();
let eth_mac = parts.mac.into();
let dma = EthernetDMA::new(parts.dma.into(), rx_buffer, tx_buffer);
#[cfg(feature = "ptp")]
let ptp = EthernetPTP::new(parts.ptp.into(), clocks, &dma);
let mac = EthernetMAC::new(eth_mac, parts.mmc, clocks, Speed::FullDuplexBase100Tx, &dma)?;
let parts = Parts {
mac,
dma,
#[cfg(feature = "ptp")]
ptp,
};
Ok(parts)
}
#[cfg(feature = "device-selected")]
pub fn new_with_mii<'rx, 'tx, REFCLK, CRS, TXEN, TXD0, TXD1, RXD0, RXD1, MDIO, MDC>(
parts: PartsIn,
rx_buffer: &'rx mut [RxRingEntry],
tx_buffer: &'tx mut [TxRingEntry],
clocks: Clocks,
pins: EthPins<REFCLK, CRS, TXEN, TXD0, TXD1, RXD0, RXD1>,
mdio: MDIO,
mdc: MDC,
) -> Result<Parts<'rx, 'tx, EthernetMACWithMii<MDIO, MDC>>, WrongClock>
where
REFCLK: RmiiRefClk + AlternateVeryHighSpeed,
CRS: RmiiCrsDv + AlternateVeryHighSpeed,
TXEN: RmiiTxEN + AlternateVeryHighSpeed,
TXD0: RmiiTxD0 + AlternateVeryHighSpeed,
TXD1: RmiiTxD1 + AlternateVeryHighSpeed,
RXD0: RmiiRxD0 + AlternateVeryHighSpeed,
RXD1: RmiiRxD1 + AlternateVeryHighSpeed,
MDIO: MdioPin,
MDC: MdcPin,
{
pins.setup_pins();
setup::setup();
let eth_mac = parts.mac.into();
let dma = EthernetDMA::new(parts.dma.into(), rx_buffer, tx_buffer);
#[cfg(feature = "ptp")]
let ptp = EthernetPTP::new(parts.ptp.into(), clocks, &dma);
let mac = EthernetMAC::new(eth_mac, parts.mmc, clocks, Speed::FullDuplexBase100Tx, &dma)?
.with_mii(mdio, mdc);
let parts = Parts {
mac,
dma,
#[cfg(feature = "ptp")]
ptp,
};
Ok(parts)
}
#[cfg(doctest)]
mod test_readme {
macro_rules! external_doc_test {
($x:expr) => {
#[doc = $x]
extern "C" {}
};
}
external_doc_test!(include_str!("../README.md"));
}