Skip to content

Releases: jethub-iot/esp-emac-rs

v0.5.0

09 Jun 14:47
4d81c0f

Choose a tag to compare

Breaking release — propagates the upstream esp_hal::ethernet::mac::LinkState shape + Speed::_10M/_100M renames through the mdio-phy feature re-exports. Final crate in the coordinated 0.3 release wave:

Crate Version
eth-mdio-phy 0.3.0 (publish FIRST)
eth-phy-lan87xx 0.3.0
eth-phy-lan867x 0.2.0
esp-emac 0.5.0 ← this release (publish LAST)

Pre-1.0 SemVer caveat. Cargo's caret on ^0.4 will not pick up 0.5.x. Bump both digits explicitly.

Diff for review

  • Previous tag: v0.4.1d316cee6ec
  • This release: main HEAD — 4d81c0f6fa
  • Full diff: v0.4.1...main

Publish-order precondition

Both eth-mdio-phy 0.3.0 and eth-phy-lan87xx 0.3.0 must be on crates.io before publishing this release (the first is a registry dependency under the mdio-phy feature; the second is a dev-dependency exercised by the bundled embassy_net_lan8720a.rs example).

Why 0.5.0, not 0.4.2

Under the mdio-phy feature, esp-emac re-exports Speed and Duplex from eth_mdio_phy. The eth-mdio-phy 0.2 → 0.3 rename (Mbps10/100_10M/_100M, Option<LinkStatus>LinkState { up, ... }) bleeds through these re-exports and breaks any downstream code that matches on esp_emac::Speed::Mbps100 etc. Cargo SemVer bumps the left-most non-zero component on any breaking change — pre-1.0 that's the minor.

Breaking — transitive eth-mdio-phy 0.3

  • Bump dependency on eth-mdio-phy to ^0.3 and dev-dependency on eth-phy-lan87xx to ^0.3. Under the mdio-phy feature this crate re-exports Speed and Duplex from eth_mdio_phy, so downstream consumers see the upstream renames:
    • Speed::Mbps10 / Speed::Mbps100Speed::_10M / Speed::_100M (matches esp_hal::ethernet::phy::Speed variant naming).
    • LinkStatus { speed, duplex } + Option<LinkStatus> signalling → LinkState { up: bool, speed, duplex }.
    • PHY drivers' poll_link return: Result<Option<LinkStatus>, _>Result<LinkState, _>.

Speed and Duplex are #[non_exhaustive] in the trait crate (eth-mdio-phy) — any remaining match arms over them in downstream code must add a wildcard. LinkState is an open struct, so match/destructure patterns continue to work without ...

Breaking — defmt 1.0

Bump optional defmt dependency from ^0.3 to ^1.0. esp-hal 1.1.x and embassy-net 0.9.x already require defmt ^1.0.1; without this bump any downstream that enables the defmt feature on this crate alongside a current esp-hal / embassy-net release would end up with two defmt versions in its lock graph (defmt global-logger ABI is not version-compatible across 0.3 → 1.0 — real link error, not a noisy warning). Use sites are only defmt::Format derives and defmt::warn!(...) calls, source-compatible across the jump.

Migration

// before (0.4.x with eth-mdio-phy 0.2)
match phy.poll_link(mdio) {
    Ok(Some(link)) => {
        emac.set_speed(link.speed);   // Speed::Mbps100
        emac.set_duplex(link.duplex);
    }
    Ok(None) => { /* link down */ }
    Err(e)   => return Err(e.into()),
}
// after (0.5.0 with eth-mdio-phy 0.3)
match phy.poll_link(mdio) {
    Ok(state) if state.up => {
        emac.set_speed(state.speed);  // Speed::_100M
        emac.set_duplex(state.duplex);
    }
    Ok(_) => { /* link down */ }
    Err(e) => return Err(e.into()),
}

If your firmware copy-pasted the 0.4.x example pattern with use esp_emac::emac::{Duplex as EmacDuplex, Speed as EmacSpeed}; — drop both aliases. Under the mdio-phy feature esp_emac::Speed and Duplex are now the same type identity as eth_mdio_phy::Speed and Duplex, no conversion needed at the seam.

Changed

  • examples/embassy_net_lan8720a.rs: rewrite the PHY poll loop to use the new Result<LinkState, _> shape and drop the PhySpeed / PhyDuplex rename aliases.
  • src/emac.rs: doc-comments and internal match arms updated to the _10M / _100M variant names.
  • README.md: drop the PhySpeed / PhyDuplex alias-naming guidance; correct the HW checksum offload paragraph to reflect 0.4.1's engine-disable (it had still claimed "unconditional" from the 0.3.0 era).

Notes

  • No source-level changes to the public Emac / EmacDriver API surface beyond the transitive type renames above.
  • No behavioural diff observed on JXD-PM380-E1ETH bench vs 0.4.1 across TX/RX paths, DMA descriptor handling, link bring-up sequence, instrumentation. Wave-level smoke test: link UP _100M Full, DHCP, iperf2 cycles complete.

Full changelog

esp-emac 0.4.1 — disable HW checksum offload (TX+RX) on ESP32 rev v3.1

20 May 08:14

Choose a tag to compare

Patch release — disable broken Synopsys GMAC checksum offload in both
directions on ESP32 rev v3.1.

The v0.3.0 release relied on the hardware checksum engine (TDES0.CIC = 0b11
for TX insertion, GMACCONFIG.IPC = 1 for RX verification) and told
smoltcp to skip software computation. Both sides turn out to be unreliable
on at least rev v3.1 silicon:

  • TX: only the first 60-byte iperf2 control header reaches the peer
    intact; every bulk segment that follows carries a wrong TCP/UDP checksum
    and is dropped by the receiver, so the connection collapses after ~15 s.
  • RX: GMACCONFIG.IPC = 1 symmetrically marks incoming valid TCP/UDP
    frames as checksum-errored, which the DMA then silently drops at
    DMAOPERATION.DT = 0 before they reach the CPU descriptor ring.
    Empirical signature: iperf2 downlink throughput collapsing to 0 Mbps
    while uplink still passes data through at a reduced rate.

Both bits are now 0. Driver::capabilities() advertises
ChecksumCapabilities::default(), so smoltcp computes and verifies
IPv4/TCP/UDP/ICMP checksums in software in both directions. A few extra
cycles per frame in exchange for correct frames.

Verified

iperf2 -s against the production server (Linux, iperf 2.1.9) on a
LAN8720A RMII board:

[iperf] done: UP=13 Mbps (16 MB) DN=10 Mbps (11 MB)

i.e. equivalent to the v0.3.0 baseline measured under HW-offload but
now reliable end to end.

Other fixes in this release

  • Layout invariants for TxDescriptor covered by const_assert! +
    offset_of! checks (back-port from rebased descriptor work).
  • Acquire / Release memory fences around DMA descriptor ownership
    flips in dma::engine.
  • current_speed / current_duplex cached fields with idempotency
    guards in Emac::set_link_*.
  • Conditional Checksum import (test-only) — removes a clippy unused-
    import warning under --lib.

Compatibility

No API breaks vs 0.4.0. Drop-in replacement.

Not yet on crates.io

Per the eth-crate publication gate (eth-mdio-phy + eth-phy-lan87xx +
eth-phy-lan867x + esp-emac ship together after a coordinated
review), this tag is git-only. Use a submodule / git dependency until
the bundle is published.

Full changelog: https://github.com/jethub-iot/esp-emac-rs/blob/v0.4.1/CHANGELOG.md

esp-emac v0.3.0

12 May 10:03

Choose a tag to compare

Added

Hardware checksum offload for the EMAC: TX descriptors now request full TCP/UDP/ICMP + IPv4-header checksum insertion (`TDES0.CIC = 0b11`), and `GMACCONFIG.IPC` is set so the DMA verifies received checksums and silently drops bad frames before they reach the host. The embassy-net driver advertises `Checksum::None` for `ipv4`, `tcp`, `udp`, and `icmpv4` so smoltcp skips redundant software computation.

Behavior is correct on either side: a peer talking to us sees normal Ethernet frames with valid checksums, and frames we receive with bad checksums never appear at the application. Two new unit tests cover the descriptor flag and the advertised capabilities.

Verified on jxd-pm380-e1eth + LAN8720A. No measurable throughput delta on the iperf2 loopback (smoltcp packet pipeline is the dominant cost), but eliminates a real per-packet CPU expense and enables future zero-copy work.

Compatibility

Same as 0.2.x: `esp-hal = "1.1"`, `embassy-net = "0.9"`, `embassy-executor = "0.10"`, `xtensa-esp32-none-elf`. MSRV unchanged at 1.88.

See `CHANGELOG.md` for full notes.

esp-emac 0.2.0

07 May 20:06
86f47cb

Choose a tag to compare

First public release of esp-emac on crates.io. Bundled with eth-mdio-phy 0.2.0, eth-phy-lan87xx 0.2.0, and eth-phy-lan867x 0.1.0.

Pre-flight: eth-mdio-phy 0.2.0 must already be on crates.io before this release publishes — cargo publish will pull the registry copy of that trait crate during --verify. Publish in this order: eth-mdio-phyeth-phy-lan87xxeth-phy-lan867xesp-emac.

Breaking

  • Speed and Duplex are now re-exports of eth_mdio_phy::{Speed, Duplex} (gated by feature mdio-phy) rather than locally defined enums with From<eth_mdio_phy::*> conversions. Call sites that used to write emac.set_speed(status.speed.into()) drop the .into() — the types are literally the same now. Without the mdio-phy feature the symbols are no longer exposed from the crate; drop down to crate::regs::mac::set_speed_100mbps / set_duplex_full for raw register control.
  • Emac::stop() now returns Err(EmacError::TxFlushTimeout) when the FTF poll exhausts TX_FIFO_FLUSH_TIMEOUT_US instead of silently returning Ok(()). The rest of the teardown still runs unconditionally, so the driver state still ends up at Initialized and start() is safe to retry — the new error is a recoverable warning, not a state-machine corruption signal. Callers that pattern-match on Ok(()) need a wildcard or explicit handling of the new variant.
  • MSRV bumped from 1.75 to 1.88, matching what esp-hal = "1.1" declares in its own manifest (esp-hal 1.0 carried the same 1.88 pin). The previous declaration was mis-advertised.
  • Bump eth-mdio-phy dependency pin from ^0.1.1 to ^0.2.0. Trait crate's Speed/Duplex became #[non_exhaustive] in that release.
  • Bump embassy-sync from ^0.7 to ^0.8 (cascade from esp-hal 1.1 requirement).
  • Bump esp-hal from ^1.0.0 to ^1.1.0.

Added

  • EmacError::TxFlushTimeout variant (lands as a non-breaking variant addition because EmacError is #[non_exhaustive]).
  • Emac::set_speed / set_duplex now match each Speed/Duplex variant explicitly. The trait-crate types became #[non_exhaustive] in eth-mdio-phy 0.2, so a future variant (e.g. a hypothetical Speed::Mbps1000) compiles transparently but has no register encoding on ESP32 EMAC. Such inputs are clamped to 100 Mbps (highest mode the peripheral physically supports) / Full duplex, with a defmt::warn! under the defmt feature flagging the mismatch.

Fixed

  • Two clippy errors under cargo +esp clippy --target xtensa-esp32-none-elf -D warnings: redundant_guards at emac.rs:208 (collapsed RmiiClockConfig::InternalApll { gpio, .. } if matches!(gpio, ClkGpio::Gpio0) into RmiiClockConfig::InternalApll { gpio: ClkGpio::Gpio0, .. }) and let_unit_value at emac.rs:474 (esp_hal::interrupt::enable returns (), the prior let _ = was dead).
  • examples/embassy_net_lan8720a.rs now compiles against esp-rtos 0.3.0 and embassy-executor 0.10: esp_rtos::start takes a SoftwareInterrupt<'static, 0> second argument, and Spawner::spawn now returns () while #[task] fns return Result<SpawnToken<_>, SpawnError> (the .unwrap() belongs on the task call, not the spawn).
  • .cargo/config.toml now emits -Tlinkall.x so the xtensa example links from a clean target dir. Pre-existing latent bug — linkall.x shipped from esp-hal's OUT_DIR via cargo:rustc-link-search, but nothing emitted a -T, so a fresh build would fail with hundreds of undefined reference symbols (_stack_end_cpu0, every interrupt-vector entry from the esp32 PAC). Now caught by the example-xtensa CI job.

Documentation

  • New "Recovery from task respawn" section in the embassy-net module rustdoc covering the static mut EMAC re-borrow path: init() is one-shot, so a respawned task must call stop() + start() to bring the engine back up rather than silently ignoring EmacError::AlreadyInitialized.
  • [package.metadata.docs.rs] now sets default-target = "riscv32imc-unknown-none-elf" and drops the esp-hal feature. docs.rs cannot satisfy xtensa-esp32-none-elf (rustc upstream has no xtensa target, and docs.rs does not carry the Microchip fork), so the previous metadata produced a "Documentation: failed" badge. Matches the convention every other esp-rs crate (esp-hal, esp-println, esp-backtrace, esp-storage, esp-radio) already uses.

Compatibility

Component Version
eth-mdio-phy 0.2.0
eth-phy-lan87xx 0.2.0
eth-phy-lan867x 0.1.0
esp-emac (this crate) 0.2.0
esp-hal 1.1.0
esp-rtos 0.3.0
embassy-executor 0.10

Pre-1.0 SemVer note. Cargo's caret on ^0.1 will not pick up 0.2.x — both digits are treated as the major axis below 1.0. Update your esp-emac = "0.1" requirement to "0.2" to pick up this release.

Full CHANGELOG: CHANGELOG.md