Files
escape_gallery_obsidian_vault/Projects/ESP32-S3-ETH/Rust Dev Environment for Waveshare ESP32-S3-ETH (W5500).md
T

196 lines
7.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
Working setup, derived from an actual first-time bring-up. Every failure mode below was hit and fixed, in order. Follow this straight through and you skip all of it. (AI generated)
## Board reference
Waveshare ESP32-S3-ETH — ESP32-S3 + onboard W5500 ethernet chip over SPI (not RMII — there's no on-chip MAC/PHY involved, W5500 has its own MAC and does everything over SPI).
Confirmed pin mapping (verify against your board's silkscreen — Waveshare pin assignments have varied slightly across production batches):
|Signal|GPIO|
|---|---|
|SCLK|13|
|MOSI (SDO)|11|
|MISO (SDI)|12|
|CS|14|
|INT|10|
|RST|9|
|SPI host|SPI2|
|Clock|2025 MHz|
W5500 has no burned-in MAC address — you must supply one (a locally-administered address like `02:00:00:12:34:56` works fine).
## Why std (esp-idf-svc), not no_std (esp-hal)
`esp-generate` scaffolds `esp-hal` (`no_std`) projects. That toolchain has no W5500/ethernet driver and no full HTTP server story — its focus is Wi-Fi/BLE via `esp-radio` and `embassy`. For ethernet + a standard HTTP server, use the `std` toolchain via `esp-idf-svc`, which wraps ESP-IDF's C ethernet driver and httpd component.
**Rule of thumb:** if the board has W5500/LAN8720/other wired-ethernet hardware, use `esp-idf-template` (std). Reach for `esp-generate` (no_std) only for pure Wi-Fi/BLE projects.
## 1. Toolchain
```bash
espup install
. $HOME/export-esp.sh # re-run in every new shell, or add to your shell rc
```
Confirm the Xtensa target is present:
```bash
rustc --print target-list | grep xtensa
```
## 2. Scaffold the project
Do **not** use `esp-generate`. Use:
```bash
cargo install cargo-generate
cargo generate esp-rs/esp-idf-template cargo
```
Prompt answers that matter:
|Prompt|Answer|Why|
|---|---|---|
|MCU|`esp32s3`|matches the board|
|Configure advanced options|Yes|need to reach STD toggle|
|STD support|**Yes**|pulls in `esp-idf-svc`; this is the whole point|
|ESP-IDF version|`v5.3.4`|most mature crates.io compatibility; avoid `master`/newest unless you have a reason|
|Use git esp-idf-* crates|**false**|crates.io releases are stable and documented; git HEAD drifts mid-project|
|Install location|**global**|ESP-IDF toolchain reused across projects, saves re-downloading (~12 GB)|
|Dev Containers|false|flashing real hardware over USB is simpler done natively|
|Wokwi simulation|false|Wokwi doesn't model W5500/ethernet peripherals|
|CI files|false|add later if/when you push to GitHub|
## 3. Known environment issues and fixes
These hit in this order on a fresh Arch-based system (Omarchy); adjust distro-specific commands as needed, but expect similar issues on any non-Ubuntu-LTS host.
### a) `esp-clang: error while loading shared libraries: libxml2.so.2`
Rolling-release distros ship a newer libxml2 soname (`.so.16`+) than the pinned `esp-clang` toolchain expects (`.so.2`). Symlink it:
```bash
ldconfig -p | grep libxml2 # find your installed version, e.g. libxml2.so.16
sudo ln -s /usr/lib/libxml2.so.16 /usr/lib/libxml2.so.2 # adjust path/version to match
sudo ldconfig
```
Verify against the actual binary, not just `ldconfig -p` (which may not reflect symlinks immediately):
```bash
/path/to/.embuild/espressif/tools/esp-clang/*/esp-clang/bin/clang --version
```
If a failed build already deleted the tool directory during its own error-recovery, just rebuild — `cargo build` reinstalls it.
### b) `Missing esp-mqtt submodule` / CMake `git_submodule_check` errors
The managed ESP-IDF checkout under `.embuild/espressif/esp-idf/<version>/` needs its git submodules initialized — several ESP-IDF components (mqtt, lwip, mbedtls, wifi/bt libs, etc.) are submodules, and IDF's build requires them present even if your project doesn't use those components.
```bash
cd .embuild/espressif/esp-idf/<version>
git submodule update --init --recursive
cd -
cargo build --release
```
This is a one-time ~500MB1GB download. If it's still broken afterward (partial/shallow clone issues), delete and let `embuild` re-clone fresh:
```bash
rm -rf .embuild/espressif/esp-idf/<version>
cargo build --release
```
### c) Building for host instead of the chip (`Unsupported target 'x86_64-unknown-linux-gnu'`)
`.cargo/config.toml` must set:
```toml
[build]
target = "xtensa-esp32s3-espidf"
```
`esp-idf-template` generates this correctly — if you hit this, something overwrote or is missing that file, or `espup`'s toolchain isn't active in the current shell (`. $HOME/export-esp.sh`).
### d) SPI DMA: `check_trans_valid: txdata transfer > host maximum` / w5500 read-write failures
The default `SpiDriverConfig` has DMA disabled, which caps transfer size below what the W5500 ethernet driver needs to move full frames. Symptom: link never comes up, `wait_netif_up()` hangs, log fills with `w5500_spi_write failed` / `w5500_spi_read failed`. Fix — enable DMA explicitly when constructing the `SpiDriver`:
```rust
use esp_idf_svc::hal::spi::{config::DriverConfig, Dma, SpiDriver};
let spi_driver = SpiDriver::new(
peripherals.spi2,
pins.gpio13, // SCLK
pins.gpio11, // MOSI
Some(pins.gpio12), // MISO
&DriverConfig {
dma: Dma::Auto(4096),
..Default::default()
},
)?;
```
### e) `esp-idf-svc` API drift across versions
The `EthDriver::new_spi` signature has changed across `esp-idf-svc` releases — older versions took raw MOSI/MISO/SCLK pins directly; 0.51+ takes a pre-built `SpiDriver` plus INT/CS/RST only (9 args total: `spi, int, cs, rst, chipset, baudrate, mac_addr, phy_addr, sysloop`). If code from an older tutorial/example doesn't compile, check the exact signature for your pinned version:
```bash
cargo doc --open -p esp-idf-svc
# or browse https://docs.rs/esp-idf-svc/<your-version>/esp_idf_svc/eth/
```
Trust the compiler's error over memory or old examples — it names the exact expected type/arg count.
## 4. sdkconfig.defaults
```
CONFIG_ETH_SPI_ETHERNET_W5500=y
CONFIG_ESP_MAIN_TASK_STACK_SIZE=8000
CONFIG_HTTPD_MAX_REQ_HDR_LEN=1024
```
Without the first line, the W5500 driver component isn't built into ESP-IDF at all — you'll get a runtime or link failure referencing missing eth symbols.
## 5. Cargo.toml essentials
```toml
[dependencies]
esp-idf-svc = { version = "0.51", features = ["std"] }
anyhow = "1"
log = "0.4"
```
## 6. Build / flash / monitor
```bash
cargo build --release
espflash flash --monitor target/xtensa-esp32s3-espidf/release/<binary-name>
```
Watch the serial log for `Got IP: ...` — that confirms both SPI-to-W5500 link and DHCP succeeded. No `Got IP` line + streaming `w5500.mac` errors = revisit DMA config or pin mapping (item d/a above).
## Summary: what each fix actually solved
|Problem|Root cause|Fix|
|---|---|---|
|Config menu had no ethernet option|Wrong scaffolding tool (`esp-generate` = no_std/esp-hal)|Use `esp-idf-template` (std) instead|
|Build targeted host, not chip|Missing/wrong `.cargo/config.toml` target|Ensure `target = "xtensa-esp32s3-espidf"`|
|`esp-clang` failed to load|Host libxml2 soname too new|Symlink `.so.16``.so.2`|
|CMake submodule errors|Managed ESP-IDF git checkout incomplete|`git submodule update --init --recursive`|
|`EthDriver::new_spi` type errors|API changed across esp-idf-svc versions|Match compiler-reported signature exactly, don't trust memorized old examples|
|W5500 never links / SPI transfer errors|DMA disabled by default on SPI bus|`Dma::Auto(4096)` in `DriverConfig`|