Public Access
/dev/ has Debug Builds and the Debug Console (builds and the token, the console and its protocol, files and screenshots, driving the UI, crashes and Safe Mode, the command reference), Build, test and release (including how an update works), the architecture decisions and the milestone plans. Generated from the repository by site/tools/gen_dev_docs.py: the ADRs, the milestones, the README's sections, and the command reference, read from the firmware's own `help` text. The pages are committed (Zola cannot read outside its folder); the Site workflow checks they are current, and now also runs when src/main.cpp changes. M0, M1 and CONTEXT.md are not published. README: the gnss commands that the table lacked. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
57 lines
4.1 KiB
Markdown
57 lines
4.1 KiB
Markdown
+++
|
|
title = "Debug Builds"
|
|
description = "What a Debug Build is, how to build and flash one, how its token works, and why you should keep one in the fallback slot."
|
|
weight = 1
|
|
[extra]
|
|
tag = "Start here"
|
|
+++
|
|
|
|
## What it is
|
|
|
|
A Debug Build is built from the same source as a release, with the `cardputer-adv-debug` environment (it `extends` `cardputer-adv` in `platformio.ini`) and `-DRORO_DEBUG`. Differences:
|
|
|
|
- the **Debug Console** on TCP **2323** (next page);
|
|
- extra commands, only meant for testing: crash on purpose, fake an installed version, damage a download, inject a LoRa packet, fill a folder with files (see the [command reference](/dev/debug/commands/));
|
|
- the version ends in **`+debug`** (`scripts/version.py`) wherever the version shows: Settings, `info`, the Update Service. A `+debug` version compares **equal** to its release counterpart, so going between the two is never refused as a downgrade.
|
|
|
|
**It is compiled out of release builds, not switched off by a setting.** A console that runs commands, presses keys and reboots the device is a remote control; in a release build nothing listens and the code is not there.
|
|
|
|
## Build and flash one
|
|
|
|
Everything runs in Docker (see [Build, test and release](/dev/build/build-and-test/)). Over USB:
|
|
|
|
```sh
|
|
scripts/flash.sh --debug # builds cardputer-adv-debug, uploads, opens the serial monitor
|
|
```
|
|
|
|
Once a Debug Build is on the device, every later one can go over Wi-Fi, with no cable:
|
|
|
|
```sh
|
|
export RORO_OTA_HOST=10.39.39.12 # the address Settings > Firmware shows
|
|
scripts/flash.sh --debug --ota # builds, signs and pushes; the device installs and restarts
|
|
```
|
|
|
|
The device's address is on **Settings → Firmware** ("Push to", which also gives port 3232, the update port). The Debug Console is on the same address, port 2323. See [Flash and update](/dev/build/flash/) for the update side.
|
|
|
|
## The token
|
|
|
|
The console asks for a secret first. It is **128 random bits**, made the first time any build runs (`scripts/_docker.sh`), kept in `~/.config/roro9stack/debug-token` next to the update-signing key, and passed into the build container as `RORO_DEBUG_TOKEN`. `scripts/debug_flags.py` compiles it into the firmware, and **refuses to build a Debug Build without one**, rather than fall back on a default.
|
|
|
|
- It is **never committed.** Releases have no console, so nothing of it is published: CI builds a Debug Build on a pull request to prove it still compiles, but never publishes it, because each one carries its builder's token.
|
|
- It guards against **the network**, not against someone who holds the device: anyone with USB access can flash anything anyway ([ADR 0003](/dev/decisions/0003-own-signature-check-not-secure-boot/)).
|
|
- To change it, delete the file and build again; the new token goes into the next Debug Build you flash.
|
|
|
|
## Keep a Debug Build in the other slot
|
|
|
|
The device has two app slots, so an update never overwrites the running firmware. If a new firmware crashes during [Probation](/dev/build/how-an-update-works/), the device goes **back to the previous one**, whatever that is. As long as you develop on Debug Builds, **the firmware a crash falls back to has the console too**, so a bad update never costs you remote access. Pushing a *release* build over a Debug Build leaves the Debug Build in the other slot until the next update overwrites it.
|
|
|
|
So the habit is: develop on Debug Builds, release by tag, and think twice before pushing a release over the only Debug Build you have.
|
|
|
|
## Releases and Debug Builds
|
|
|
|
- A Debug Build shows the latest release in Settings → Firmware but **never installs it**: that would replace the console with a release that has none. Update a Debug Build from the PC with `scripts/flash.sh --debug --ota`.
|
|
- A Debug Build still checks and lists releases, which is useful for testing the update path: `update pretend` makes a released version count as newer (see [Drive the UI](/dev/debug/drive-the-ui/)).
|
|
- **Safe Mode** (after 3 crashes in a row) keeps the Debug Console running, so a crash loop is something you fix remotely: see [Crashes and Safe Mode](/dev/debug/crashes/).
|
|
|
|
The reasoning is in [ADR 0004](/dev/decisions/0004-debug-console-in-debug-builds/).
|