Source builds · developer tools
Build and develop.
Work on Gnarlyr from a source checkout. This guide covers the build environment, firmware images and developer USB workflow. To set up a player with a ready-made image, use the Install guide.
Build from your checkout.
These build steps are for owners of a Gnarlyr source checkout. Run the commands on macOS from its root folder. The build wrapper prepares an image on your computer; it does not install it on the player.
- Python 3.14 and
firmware/tools/requirements.txt. - Build tools: CMake, SDL2, FFmpeg, clang-format and the Arm GNU cross-compiler.
- Scratch storage: mount a disposable build-output volume at
/Volumes/Scratch. It keeps generated files separate from your backed-up source. The wrapper createsfirmware/buildas a link to the checkout’s Scratch output.
Set up the build environment
Create a Python virtual environment on Scratch. Set ECHO_VENV to that folder and ECHO_ARM_BIN to the folder containing arm-none-eabi-gcc. Full prerequisite instructions are in the checkout’s README.md.
Build the release image
python3 tools/firmware.py setup python3 tools/firmware.py build --preset release
Record its SHA-256
shasum -a 256 firmware/build/release/GNARLYR.img
The output is firmware/build/release/GNARLYR.img. SHA-256 is a fingerprint of the file: comparing fingerprints tells you whether the copy is identical.
Let the computer handle the repeat steps.
When you are testing developer builds, the macOS helper can do the copy, verification, eject and restart round trip and report which build came back.
Build a developer image with python3 tools/firmware.py build --preset device, then use the matching checkout’s helper:
Install and request a restart
python3 tools/echo_debug.py install firmware/build/device/GNARLYR.img --restart
The helper checks the copied file, asks the developer firmware to restart after installation, ejects the player’s drives, waits for it to leave and return on USB, and reads back the running build. Leave the cable connected for this loop.
Ordinary manual updates use the player’s unplug-and-Power sequence. Automatic restart is a developer-build workflow.
How USB hands storage back to the player.
Eject tells the computer to finish writing and gives the storage back to the player. That is when Gnarlyr can inspect the update file and begin installing it.
- Eject is the handover. While the computer has the drives, it owns file access. Ejecting every drive present at connection returns storage to Gnarlyr and starts the update check.
- The cable can stay connected while it writes. The end of a storage session and removal of the cable are separate events. Wait for “Update installed” before unplugging.
- The new USB code starts with the new firmware. USB and updater code load from the image into a shared memory region. Restarting after installation ensures the running firmware and its USB module match.
- Connection handling follows cable power. Gnarlyr keeps USB power control in sync with the cable state. The stack can retry at full speed if its first high-speed connection does not become usable.
For everyday music copying, eject every drive before unplugging too. Gnarlyr then checks whether the music changed and rescans when needed.
Match the updater to the build you have.
A custom updater checks the image’s identity as well as its name. Older firmware may need a bridge or the recovery route before it can accept a current Gnarlyr image.
For a pre-release or older custom build, use the update instructions supplied with that build. Earlier Gnarlyr development images used FRSHBS.IMG; Doublesharp Echo used DBLSHARP.IMG. Those names describe development history, not public release versions.
The documented Doublesharp Echo route first installs the bridge-frshbs build, then moves to the later firmware. firmware/docs/device-install.md explains which checkout and helper to use at each step. For other starting builds, use the exact-model recovery installation.
An image contains an internal firmware identity too. Renaming the file cannot make an incompatible updater accept it.
Keep a way back to the original software.
Recovery mode belongs to the chip, so it remains the separate route for reinstalling stock firmware when the normal player interface cannot be used.
Keep the full-size ECHO’s official ECHOV200.IMG and the exact-model recovery instructions from your checkout. The official V2.0 image is 39,845,892 bytes, with SHA-256:
c6a3b6c86b141c0a428771f8a611fbd44cc12d561acb033a98640b0bf24f8d57
For a player that does not start, follow firmware/docs/device-recovery.md to restore the official image through maskrom, checking each complete slot readback.
A running Gnarlyr also recognizes the official ECHO image through its updater. Follow the checkout’s return-to-stock instructions for that image; its on-screen messages and restart sequence differ from an ordinary Gnarlyr update.
FiiO’s ECHO firmware page ↗