Add build/flash/backup documentation for Pi firmware
This commit is contained in:
172
.pi/BUILD.md
Normal file
172
.pi/BUILD.md
Normal file
@@ -0,0 +1,172 @@
|
||||
# Onefinity CNC Firmware — Build, Flash & Backup
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
The Onefinity controller is a **Raspberry Pi 2/3** (armv7l, Raspbian Stretch, Python 3.5) connected to an **ATxmega192a3u** AVR microcontroller over serial. The Pi runs a Tornado web server (`bbctrl`) that serves the UI and plans G-code motion. The AVR executes realtime step/direction pulses.
|
||||
|
||||
```
|
||||
Browser ←WebSocket→ Pi (Tornado/Python) → GCode Planner → Serial → AVR → Stepper drivers
|
||||
```
|
||||
|
||||
The firmware package (`bbctrl-X.Y.Z.tar.bz2`) contains:
|
||||
- **Python backend** (`src/py/bbctrl/`) — Tornado web server, planner, state machine
|
||||
- **Web frontend** (`build/http/`) — Pug/Stylus/Svelte compiled to static HTML/JS/CSS
|
||||
- **AVR firmware** (`src/avr/bbctrl-avr-firmware.hex`) — realtime motion controller
|
||||
- **gplan.so** (`src/py/camotics/gplan.so`) — CAMotics G-code planner (native ARM .so)
|
||||
- **Install scripts** (`scripts/install.sh`, etc.)
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Docker (for the devcontainer build environment)
|
||||
- The devcontainer image: `docker build -t onefin-dev -f .devcontainer/Dockerfile .devcontainer/`
|
||||
- SSH access to the Pi: `ssh bbmc@10.1.10.55` (password: `onefinity`)
|
||||
|
||||
## Building
|
||||
|
||||
### Full build (frontend + AVR + package)
|
||||
|
||||
```bash
|
||||
docker run --rm -v "$(pwd):/workspace" -w /workspace onefin-dev \
|
||||
bash -c 'make all && python3 ./setup.py sdist'
|
||||
```
|
||||
|
||||
Produces: `dist/bbctrl-1.6.7.tar.bz2` (~3MB)
|
||||
|
||||
### What `make all` builds
|
||||
|
||||
| Component | Command | Output |
|
||||
|---|---|---|
|
||||
| Web frontend | `npm install`, pug/stylus/svelte compile | `build/http/` |
|
||||
| AVR firmware | `make -C src/avr` (avr-g++) | `src/avr/bbctrl-avr-firmware.hex` |
|
||||
| Bootloader | `make -C src/boot` | `src/boot/bbctrl-avr-boot.hex` |
|
||||
| Power MCU | `make -C src/pwr` | `src/pwr/bbctrl-pwr-firmware.hex` |
|
||||
| Jig firmware | `make -C src/jig` | `src/jig/bbctrl-jig-firmware.hex` |
|
||||
|
||||
### gplan.so — the critical gotcha
|
||||
|
||||
`gplan.so` is the CAMotics G-code planner compiled as a Python C extension. It **must be a 32-bit ARM binary** linked against **Python 3.5** to run on the Pi.
|
||||
|
||||
**Do NOT build gplan.so in the devcontainer.** The devcontainer runs arm64/Debian Bullseye with Python 3.9. The resulting `.so` will be the wrong architecture and wrong Python ABI. Cross-compiling also fails because SCons ignores CC/CXX overrides.
|
||||
|
||||
**Where to get it:**
|
||||
1. From the official release: `https://github.com/OneFinityCNC/onefinity-firmware/releases/download/v1.6.6/onefinity-1.6.6.tar.bz2` — extract `src/py/camotics/gplan.so`
|
||||
2. From a working Pi: `scp bbmc@10.1.10.55:/usr/local/lib/python3.5/dist-packages/bbctrl-*.egg/camotics/gplan.so src/py/camotics/`
|
||||
3. From a backup image
|
||||
|
||||
The correct file is:
|
||||
```
|
||||
ELF 32-bit LSB shared object, ARM, EABI5 version 1 (GNU/Linux), dynamically linked
|
||||
```
|
||||
|
||||
If you see `ELF 64-bit LSB shared object, ARM aarch64` — that's the wrong one.
|
||||
|
||||
### bbserial.ko — kernel module
|
||||
|
||||
The `bbserial.ko` kernel module requires cross-compiling against the Pi's exact kernel headers (4.9.59-v7+). The `make pkg` target tries to build it but it's rarely needed — the Pi already has a matching `.ko` installed. The `install.sh` script skips it gracefully if the file is missing (`cp: cannot stat 'src/bbserial/bbserial.ko': No such file or directory`).
|
||||
|
||||
### AVR emulator (for local demo mode)
|
||||
|
||||
```bash
|
||||
docker run --rm -v "$(pwd):/workspace" -w /workspace/src/avr/emu onefin-dev make
|
||||
```
|
||||
|
||||
Produces `src/avr/emu/bbemu` — a native binary that emulates the AVR for demo mode.
|
||||
|
||||
## Flashing
|
||||
|
||||
### Via web API (recommended, machine must be running)
|
||||
|
||||
```bash
|
||||
curl -X PUT \
|
||||
-H "Content-Type: multipart/form-data" \
|
||||
-F "firmware=@dist/bbctrl-1.6.7.tar.bz2" \
|
||||
-F "password=onefinity" \
|
||||
http://10.1.10.55/api/firmware/update
|
||||
```
|
||||
|
||||
Or: `make update HOST=10.1.10.55 PASSWORD=onefinity`
|
||||
|
||||
### Via SSH (if web UI is down / crash-looping)
|
||||
|
||||
```bash
|
||||
scp dist/bbctrl-1.6.7.tar.bz2 bbmc@10.1.10.55:/tmp/
|
||||
|
||||
ssh bbmc@10.1.10.55 'echo onefinity | sudo -S bash -c "
|
||||
systemctl stop bbctrl
|
||||
mkdir -p /var/lib/bbctrl/firmware
|
||||
cp /tmp/bbctrl-1.6.7.tar.bz2 /var/lib/bbctrl/firmware/update.tar.bz2
|
||||
/usr/local/bin/update-bbctrl
|
||||
"'
|
||||
```
|
||||
|
||||
### What happens during flash
|
||||
|
||||
1. `update-bbctrl` stops bbctrl, extracts tarball to `/tmp/update/`
|
||||
2. `install.sh` runs:
|
||||
- Flashes AVR via `scripts/avr109-flash.py` (serial bootloader protocol)
|
||||
- `setup.py install --force` — installs Python package + frontend + gplan.so
|
||||
- Restarts `bbctrl` systemd service
|
||||
- May reboot if boot config or kernel module changed
|
||||
|
||||
### Recovery if flash breaks the Pi
|
||||
|
||||
If bbctrl is crash-looping after a bad flash:
|
||||
1. SSH still works: `ssh bbmc@10.1.10.55`
|
||||
2. Check the error: `sudo python3 /usr/local/bin/bbctrl 2>&1 | head -20`
|
||||
3. Common fix: replace gplan.so with correct ARM binary (see above)
|
||||
4. Nuclear option: restore from SD card backup (see below)
|
||||
|
||||
## Running locally (demo mode)
|
||||
|
||||
Run the full stack in Docker with the AVR emulator:
|
||||
|
||||
```bash
|
||||
# Build everything first (make all + bbemu + gplan.so for arm64 devcontainer)
|
||||
# Then:
|
||||
docker run --rm -d --name onefin-demo \
|
||||
-v "$(pwd):/workspace" -w /workspace -p 8765:80 \
|
||||
onefin-dev bash -c '
|
||||
pip3 install -q tornado sockjs-tornado pyserial watchdog
|
||||
cp src/avr/emu/bbemu /usr/local/bin/
|
||||
pip3 install -q -e .
|
||||
exec bbctrl --demo --port 80 --addr 0.0.0.0 --disable-camera
|
||||
'
|
||||
```
|
||||
|
||||
Note: demo mode needs its own gplan.so matching the container's arch (arm64 + Python 3.9). Build it with the gplan build procedure in the Makefile, or use the one already in `src/py/camotics/` if it matches.
|
||||
|
||||
Open http://localhost:8765 — full UI with emulated AVR.
|
||||
|
||||
## SD Card Backup & Restore
|
||||
|
||||
```bash
|
||||
# Backup (streams raw dd from Pi, compresses locally with gzip, ~50 min)
|
||||
./backup/onefinity-backup.sh backup
|
||||
|
||||
# Verify
|
||||
./backup/onefinity-backup.sh verify backup/onefinity-20260430.img.gz
|
||||
|
||||
# Restore to local SD card
|
||||
./backup/onefinity-backup.sh restore backup/onefinity-20260430.img.gz /dev/diskN
|
||||
```
|
||||
|
||||
See `backup/onefinity-backup.sh` for details. Environment variables: `ONEFINITY_HOST` (default 10.1.10.55), `ONEFINITY_USER` (bbmc), `ONEFINITY_PASS` (onefinity).
|
||||
|
||||
## Pi Details
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Host | `10.1.10.55` |
|
||||
| SSH user | `bbmc` |
|
||||
| sudo password | `onefinity` |
|
||||
| OS | Raspbian Stretch (Debian 9) |
|
||||
| Kernel | 4.9.59-v7+ |
|
||||
| Python | 3.5.3 |
|
||||
| Arch | armv7l (32-bit ARM) |
|
||||
| SD card | 30GB |
|
||||
| Service | `systemctl {start,stop,restart,status} bbctrl` |
|
||||
| Log | `/var/log/bbctrl.log` or `journalctl -u bbctrl` |
|
||||
| Config | `/var/lib/bbctrl/config.json` |
|
||||
| Uploads | `/var/lib/bbctrl/upload/` |
|
||||
| Web root | `/usr/local/lib/python3.5/dist-packages/bbctrl-*.egg/bbctrl/http/` |
|
||||
| AVR serial | `/dev/ttyAMA0` at 230400 baud |
|
||||
Reference in New Issue
Block a user