Skip to content

Building

foonerd edited this page Oct 18, 2026 · 3 revisions

Building

Two toolchains, because two kinds of crate; or one container that has both.

The host workspace (core, hal, runtime, art, sim, the drivers) is ordinary Rust on stable, pinned by the root rust-toolchain.toml. It builds, tests and documents on any machine with rustup; the simulator's window wants libsdl2-dev, and without it the check says so and builds the simulator headless.

Each firmware crate under firmware/ is a workspace of its own on an ESP-IDF std target. Those targets need nightly Rust with rust-src (the standard library is built for the target), the ldproxy linker shim, cmake and ninja for ESP-IDF's own build, and python3 with esptool 5 for the image. Each crate pins its own channel in its rust-toolchain.toml; the first build fetches ESP-IDF and the chip's C toolchain into the crate's .embuild/, which takes several minutes and a few gigabytes.

The builder image

The easier path. scripts/builder/Dockerfile has every prerequisite of both toolchains, and CI uses the same image:

docker build -t companion-builder -f scripts/builder/Dockerfile .
docker run --rm --user "$(id -u):$(id -g)" -e HOME=/tmp -v "$PWD:$PWD" -w "$PWD" companion-builder scripts/check.sh
docker run --rm --user "$(id -u):$(id -g)" -e HOME=/tmp -v "$PWD:$PWD" -w "$PWD" companion-builder scripts/image.sh firmware/waveshare-esp32-c5-touch-lcd-28

The checkout is mounted at its own path, not at some /work: ESP-IDF's build records absolute paths under target/, and a tree built under one path will not rebuild under another. Running as your own user keeps target/ and .embuild/ yours.

Prerequisites, on the machine itself

rustup toolchain install 1.98.1                                  # the host workspace
rustup toolchain install nightly-2026-10-17 -c rust-src,rustfmt,clippy   # the C5 firmware, as its rust-toolchain.toml pins
cargo install ldproxy
sudo apt install cmake ninja-build libsdl2-dev shellcheck         # Debian and friends
pip install esptool

The check

scripts/check.sh

Format, clippy with warnings denied, tests and docs on the host workspace, and the simulator run headless against nothing to prove it draws its status page; core, hal, runtime and the drivers built for bare-metal RISC-V, which proves they are no_std; the scripts under shellcheck; then every firmware crate formatted, linted and built for its device. On a machine without ldproxy, cmake and ninja the check stops at the firmware step and names what is missing; it does not report a pass that never built the product.

The simulator

The application on a desktop, against a real player, in a window or straight to a PNG:

cargo run -p companion-sim -- --player http://volumio.local:3000 --rotation 90 --theme night
cargo run -p companion-sim --no-default-features -- --player http://volumio.local:3000 --snapshot face.png --after 5

The mouse is the finger; Escape quits. --help lists the settings it takes, which are the same keys a device reads from its store: --player, --rotation, --theme, --strip, --status-text, plus --scale for the window and --snapshot/--after for the PNG.

The firmware

cd firmware/waveshare-esp32-c5-touch-lcd-28
cargo build --release

The image carries no network or player of its own. Both come from a microSD card, Card setup, and stay in the device's NVS once read. Without a card the firmware starts Wi-Fi, scans, says no wifi_ssid is set, and runs the application against no network: the status page shows.

The image

From the repository root:

scripts/image.sh firmware/waveshare-esp32-c5-touch-lcd-28

Writes into dist/: the merged image to flash at 0x0, its three parts (bootloader, partition table, application) and a SHA256SUMS. The offsets and flash settings come from the flasher_args.json ESP-IDF wrote for that build, so they follow the crate's sdkconfig.defaults.

Flash and watch

esptool --chip esp32c5 --port /dev/ttyACM0 write-flash 0x0 dist/volumio-esp-companion-waveshare-esp32-c5-touch-lcd-28-0.1.0.bin

Then read the log at 115200 on the same port. What the C5 firmware prints, in order: the chip model and revision as the ROM reports them; the PSRAM detected and the heap figures; the card, if one is in the slot, and what volumio.txt on it set; the settings read from NVS; the Wi-Fi band mode set to both bands and read back; a scan with every access point's band, channel, strength and auth (any access point on a channel above 14 is 5 GHz); the connection and address if wifi_ssid is set; status.txt written to the card; the board's bring-up; "panel lit; the application is running" once the first frame is drawn and the backlight comes on; then a heartbeat every 30 s with the free heap, its low-water mark and whether the player is up.

What each firmware crate's README adds

The stack it was last built with (crate versions, ESP-IDF version, nightly), the board's parts, the bring-up order, and the known gaps of that build.

Clone this wiki locally