Skip to main content

esp_emac/
lib.rs

1// SPDX-License-Identifier: GPL-2.0-or-later OR Apache-2.0
2// Copyright (c) Viacheslav Bocharov <v@baodeep.com> and JetHome (r)
3
4//! Native ESP32 Ethernet MAC driver for `#![no_std]` Rust.
5//!
6//! Owns the DMA engine and brings the EMAC peripheral up directly via
7//! memory-mapped register helpers — no `ph-esp32-mac`, no `esp-idf-svc`,
8//! no `esp-eth`.
9//!
10//! Pairs with [`eth-phy-lan87xx`](https://crates.io/crates/eth-phy-lan87xx)
11//! (or any [`eth_mdio_phy::PhyDriver`](https://docs.rs/eth-mdio-phy)
12//! implementation) for the PHY side, and with
13//! [`embassy-net`](https://crates.io/crates/embassy-net) for the
14//! TCP/IP stack.
15//!
16//! See the crate [README](https://github.com/jethub-iot/esp-emac-rs#readme)
17//! for an installation guide, embassy-net example, ISR setup, and
18//! troubleshooting checklist.
19//!
20//! # Quick start (embassy-net + LAN8720A)
21//!
22//! ```no_run
23//! # #![cfg_attr(not(feature = "embassy-net"), allow(unused))]
24//! # #[cfg(feature = "embassy-net")]
25//! # mod __doc {
26//! use esp_emac::config::{ClkGpio, EmacConfig, RmiiClockConfig, RmiiPins, XtalFreq};
27//! use esp_emac::EmacDefault;
28//! use esp_emac::embassy::EmacDriverState;
29//!
30//! // `Emac::new` (and therefore `EmacDefault::new`) is a `const fn`.
31//! // Storing the EMAC in a `static mut` gives compile-time BSS init
32//! // — no runtime stack temporary, deterministic on cold boot.
33//! //
34//! // The default ring sizing is currently 10 RX / 10 TX / 1600-byte
35//! // buffers (~32 KiB), sourced from `DEFAULT_RX` / `DEFAULT_TX` /
36//! // `DEFAULT_BUF`. At that size a `StaticCell::init(EmacDefault::new(..))`
37//! // pattern would risk materialising the full struct on the caller's
38//! // stack before moving it into static storage; `static mut` avoids
39//! // that path entirely.
40//! static mut EMAC: EmacDefault = EmacDefault::new(EmacConfig {
41//!     clock: RmiiClockConfig::InternalApll {
42//!         gpio: ClkGpio::Gpio17,
43//!         xtal: XtalFreq::Mhz40,
44//!     },
45//!     pins: RmiiPins { mdc: 23, mdio: 18 },
46//! });
47//! static EMAC_STATE: EmacDriverState = EmacDriverState::new();
48//!
49//! // In `main`, take the `&'static mut` once. SAFETY: `EMAC` is touched
50//! // only here — single owner — so there is no aliasing.
51//! # fn doc() {
52//! let _emac: &'static mut EmacDefault =
53//!     unsafe { &mut *core::ptr::addr_of_mut!(EMAC) };
54//! # }
55//! # }
56//! ```
57//!
58//! Full bring-up (PHY init, link wait, embassy-net plumbing, DHCP) is
59//! shown in [`examples/embassy_net_lan8720a.rs`](https://github.com/jethub-iot/esp-emac-rs/blob/main/examples/embassy_net_lan8720a.rs).
60//!
61//! # Crate features
62//!
63//! | Feature | Default | When to enable |
64//! | --- | --- | --- |
65//! | `esp-hal` | off | Always for hardware bring-up — pulls in [`esp_hal::interrupt`] for ISR binding. |
66//! | `mdio-phy` | off | When using a `PhyDriver`-based PHY driver via [`mdio::EspMdio`]. |
67//! | `embassy-net` | off | When using [`embassy-net`] — exposes [`embassy::EmacDriver`]. |
68//! | `async` | off | When using [`reset::async_impl::AsyncResetController`]. |
69//! | `defmt` | off | Adds `defmt::Format` derives on public types. |
70//!
71//! # Compatibility
72//!
73//! - **Target:** `xtensa-esp32-none-elf` (original ESP32, Xtensa LX6)
74//! - **MSRV:** 1.88 (constrained by `esp-hal = "1.1"`'s declared `rust-version`)
75//! - **`esp-hal`:** 1.1.x
76//! - **`embassy-net`:** 0.9.x
77//! - **`embassy-executor`:** 0.10.x
78//!
79//! Other ESP variants (S2/S3/C-series/H2) have **no** built-in EMAC.
80//! ESP32-P4 has a newer Synopsys GMAC revision and is not yet supported
81//! (planned through a chip-feature split in `regs/*`).
82//!
83//! Pure register-arithmetic unit tests build and run on the host
84//! (`cargo test --target $HOST_TARGET`), which is how `regs/*` is
85//! exercised in CI.
86
87#![no_std]
88
89pub mod clock;
90pub mod config;
91pub mod dma;
92pub mod emac;
93#[cfg(feature = "embassy-net")]
94pub mod embassy;
95pub mod error;
96pub mod interrupt;
97pub mod mdio;
98pub mod regs;
99pub mod reset;
100
101pub use config::{ClkGpio, EmacConfig, RmiiClockConfig, RmiiPins, XtalFreq};
102#[cfg(feature = "mdio-phy")]
103pub use emac::{Duplex, Speed};
104pub use emac::{Emac, EmacDefault, EmacSmall, EmacState};
105pub use error::EmacError;
106pub use interrupt::InterruptStatus;
107pub use mdio::{EspMdio, MdcClockDivider};