Xtensa chips

Install Espressif's Rust fork for the ESP32, S2 and S3, and build Xtensa projects with espx or cargo.

The ESP32, ESP32-S2 and ESP32-S3 use Xtensa cores. Stable Rust has no Xtensa backend, so these chips need Espressif's fork of the Rust compiler, which rustup cannot install by itself. espx installs it through espup, only when you ask for an Xtensa chip.

ChipRust target
esp32xtensa-esp32-none-elf
esp32s2xtensa-esp32s2-none-elf
esp32s3xtensa-esp32s3-none-elf

Install the fork

espx setup --chip esp32s3
espx setup --chip esp32,esp32s2,esp32s3

When the chip list holds an Xtensa chip, setup also downloads espup 0.17.1 into ~/.espx/bin and runs:

espup install --targets esp32s3 --export-file ~/.espx/export-esp.sh

espup installs the fork as a rustup toolchain named esp, with an Xtensa-capable clang and GCC linker, about 1 GB in all:

WhatWhere
The esp toolchain~/.rustup/toolchains/esp
espup's own files~/.espup
The export file (LIBCLANG_PATH and PATH for the fork)~/.espx/export-esp.sh

setup skips espup when the esp toolchain and the export file both exist. Run espx doctor to see them: espup, the esp toolchain and the export file are optional rows, dim when absent, never a failure.

Create and build

espx new radar --chip esp32s3
cd radar
espx build

esp-generate writes channel = "esp" in the project's rust-toolchain.toml. espx sources ~/.espx/export-esp.sh before every cargo command it runs, so espx build, flash and run work with no change to your shell.

If the esp toolchain is missing, espx new for an Xtensa chip and any build of a project on the esp channel stop before cargo runs:

error: the esp32s3 needs the `esp` toolchain (Espressif's Rust fork for Xtensa chips) and rustup has no toolchain named `esp`. Run `espx setup --chip esp32s3`.

rustup's own error for a missing toolchain does not say how to get it, which is why espx checks first.

Plain cargo

To run cargo build --release or cargo run --release outside espx, load the fork's environment into your shell:

eval "$(espx env)"

espx env prints the PATH line for ~/.espx/bin followed by the lines of the export file. espx setup --shell adds eval "$(espx env)" to ~/.zshrc or ~/.bashrc so every new shell has it.

cargo sets RUSTUP_TOOLCHAIN for every process it starts, and that variable overrides a project's rust-toolchain.toml. espx removes it from the environment it gives cargo and rustup, so an Xtensa project builds with the esp toolchain even when espx itself was started from inside cargo.

On the board

Two things differ from the RISC-V chips when you monitor an Xtensa board:

  • The original ESP32 prints an older ROM banner (ets …) whose reset codes mean different things. espx reads the banner and names the boot reason correctly for either family.
  • A CPU exception's backtrace on Xtensa starts inside the exception handler before it reaches the faulting function. The exception event's first frame is the faulting instruction either way.

The ESP32-S3 DevKitC-1 has two USB connectors. The one labelled USB is the chip's native USB; the other goes through a USB serial bridge. If the bridge is a WCH chip on macOS without WCH's driver, flashing fails; see Driver warnings.

Remove the fork

espx uninstall --xtensa

This runs espup uninstall and removes ~/.espup and the export file. The RISC-V setup stays.