mirror of
https://github.com/openglow-org/forgefirm.git
synced 2026-09-27 16:51:12 -07:00
docs: describe the firmware that exists; ship the NXP firmware EULA
README: replace the stalled REST/GUI roadmap with what the firmware does - GRBL mode over TCP for LightBurn/UGS/cncjs, optional cloud mode, the web control panel, cameras, A/B install beside the factory firmware - plus the supported hardware incl. the 8 MP camera limitation and a real roadmap. kas/README: xvclk is the board's 24 MHz oscillator; the pin/push rule covers every source repo; camera and motion sections are hardware-validated, with the OV8856 caveat spelled out; the device-tree item closes with the control_12v residue named; forgectrl is the machine-services daemon with two supervised controllers. LIGHTBURN.md: drop the pre-first-light status line. BUILD.md: state the NXP firmware licensing and where the EULA lives on the machine. The image now installs firmware-imx-lic, so the EULA text ships beside the VPU/EPDC blobs it covers; a bbappend declares that package at parse time, which is what makes it installable from an image recipe.
This commit is contained in:
@@ -70,6 +70,15 @@ kas lock kas/forgefirm-glowforge.yml
|
||||
See [`kas/README.md`](kas/README.md) for details, the container-build option,
|
||||
and the Scarthgap migration backlog.
|
||||
|
||||
## Third-party firmware licensing
|
||||
|
||||
The i.MX6 BSP installs NXP firmware blobs (VPU, EPDC) that are distributed
|
||||
under NXP's firmware EULA. The build config accepts it
|
||||
(`ACCEPT_FSL_EULA = "1"`), and the image ships the license text alongside the
|
||||
blobs at `/usr/share/licenses/firmware-imx/EULA` — keep it there in any
|
||||
redistributed image. The SDMA firmware comes from `linux-firmware`, which
|
||||
carries its own license package.
|
||||
|
||||
## Write to an SD card
|
||||
|
||||
```console
|
||||
|
||||
@@ -1,15 +1,60 @@
|
||||
# OpenGlow/ForgeFIRM Firmware for Glowforge
|
||||
This repository contains opensource firmware for Glowforge brand CNC lasers.
|
||||
|
||||
* [Latest Release](https://github.com/ScottW514/forgefirm/releases)
|
||||
* [Installation Instructions](https://github.com/ScottW514/forgefirm/blob/master/INSTALL.md)
|
||||
* [Build Instructions](https://github.com/ScottW514/forgefirm/blob/master/BUILD.md)
|
||||
* [Community Support](https://community.openglow.org)
|
||||
|
||||
# Roadmap
|
||||
* Base image that supports all Glowforge hardware (complete)
|
||||
* Support Glowforge web service - Python implementation (mostly complete)
|
||||
* REST API w/ G-Code support (~~in progress~~) Stalled
|
||||
* Browser-based GUI (~~pending~~) Stalled
|
||||
|
||||
This project is for experimental purposes only, and is not supported or endorsed by Glowforge.
|
||||
# OpenGlow/ForgeFIRM Firmware for Glowforge
|
||||
|
||||
Open-source firmware for Glowforge brand CNC lasers. ForgeFIRM replaces the
|
||||
cloud-dependent factory software on the **stock control board** — no hardware
|
||||
modification — and gives the machine a local controller, a local web control
|
||||
panel, and a standard Grbl interface.
|
||||
|
||||
* [Latest Release](https://github.com/ScottW514/forgefirm/releases)
|
||||
* [Installation Instructions](https://github.com/ScottW514/forgefirm/blob/master/INSTALL.md)
|
||||
* [Build Instructions](https://github.com/ScottW514/forgefirm/blob/master/BUILD.md)
|
||||
* [Connecting LightBurn](https://github.com/ScottW514/forgefirm/blob/master/docs/LIGHTBURN.md)
|
||||
* [Community Support](https://community.openglow.org)
|
||||
|
||||
## What it does
|
||||
|
||||
**Two controller modes, selected in the web panel and switchable while the
|
||||
machine is idle:**
|
||||
|
||||
* **GRBL mode** — [grblHAL](https://github.com/grblHAL) runs on the machine and
|
||||
speaks Grbl 1.1 over TCP port 23, so LightBurn, UGS, and cncjs drive the
|
||||
laser directly. Motion runs on the board's own hardware step engine (SDMA +
|
||||
EPIT), fed live by the planner. M3/M4 dynamic laser power, coolant-flow
|
||||
verification, over-temp holds, and an operator button press to arm the laser
|
||||
for each job.
|
||||
* **Cloud mode** — the machine presents itself as a stock Glowforge to the
|
||||
Glowforge web service, so the phone and web apps work as they always did.
|
||||
Optional, and off by default; nothing about GRBL mode needs it.
|
||||
|
||||
**Around both modes:**
|
||||
|
||||
* A **web control panel** on port 8080: machine status and position, coolant
|
||||
and fan telemetry, safety-switch states, camera view, machine settings,
|
||||
hardware diagnostics, firmware updates, and boot-slot management.
|
||||
* Both **cameras** as MJPEG streams and full-resolution snapshots — the lid
|
||||
camera feeds LightBurn's camera overlay directly.
|
||||
* **Camera-referenced homing**: `$H` from any sender runs the factory-style
|
||||
camera homing cycle through the Glowforge service, and the machine records
|
||||
where it is.
|
||||
* **Installs alongside the factory firmware** in the unused A/B rootfs slot,
|
||||
archiving every factory version first, so the machine can be switched back
|
||||
to stock at any time without the Glowforge cloud.
|
||||
|
||||
## Hardware
|
||||
|
||||
The control board is common to Glowforge Basic, Plus, and Pro. The 5 MP
|
||||
(OV5648) camera modules are fully supported; the 8 MP (OV8856) modules found in
|
||||
"HD" units bind but do not capture yet — see the camera note in
|
||||
[kas/README.md](kas/README.md).
|
||||
|
||||
## Roadmap
|
||||
|
||||
* Limit-switch homing as an alternative to camera-referenced homing.
|
||||
* Camera lens calibration and bed alignment for the LightBurn overlay.
|
||||
* Capture support for the 8 MP (OV8856) camera modules.
|
||||
* Cloud mode: stream jobs into the motion ring during the run, lifting the
|
||||
job-length cap that buffering the whole job imposes.
|
||||
|
||||
**A very important warning: this is experimental software. Use of this software
|
||||
could seriously maim or kill you or others, and voids your warranty. It is not
|
||||
affiliated with or endorsed by Glowforge. Use it at your own risk.**
|
||||
|
||||
+1
-3
@@ -1,8 +1,6 @@
|
||||
# LightBurn setup & operation (ForgeFIRM)
|
||||
|
||||
Status: laser software implemented, **first light pending** (see
|
||||
BRINGUP.md for the commissioning record). The laser fires only inside
|
||||
an operator-armed window:
|
||||
The laser fires only inside an operator-armed window:
|
||||
|
||||
- **Starting a job that fires: press the button.** At the first
|
||||
laser-on command of a job the machine unlocks its laser latch,
|
||||
|
||||
+44
-31
@@ -89,11 +89,13 @@ kas auto-loads the lockfile on subsequent runs. Commit it; refresh deliberately.
|
||||
The build is only reproducible when recipe pins, layer branches, and the kas
|
||||
config move in the right order. The sequence, with current status:
|
||||
|
||||
1. **Source repos pushed & pinned** — **DONE.**
|
||||
`kernel-module-glowforge` (`029dfb6`) and `python3-gfhardware` (`9bf31fd`)
|
||||
pushed to GitHub master; both recipes in meta-openglow pin those exact
|
||||
SRCREVs (no `AUTOREV` anywhere). Whenever either repo changes: push it,
|
||||
then bump the recipe `SRCREV` in meta-openglow deliberately.
|
||||
1. **Source repos pushed & pinned** — **DONE.** Every source repo
|
||||
(`kernel-module-glowforge`, `python3-gfhardware`, `Glowforge-Utilities`,
|
||||
`grblHAL-glowforge`, `forgectrl`) is on GitHub and its recipe pins an exact
|
||||
`SRCREV` — no `AUTOREV` anywhere. Whenever a source repo changes: push it,
|
||||
then bump the recipe `SRCREV` deliberately (BSP recipes in meta-openglow,
|
||||
ForgeFIRM components in meta-forgefirm) and re-verify with
|
||||
`bitbake -c fetch <recipe>`.
|
||||
2. **meta-openglow pushed** — **DONE.** The Scarthgap port lives on
|
||||
the **`scarthgap` branch** (Yocto layer convention; the Dunfell-era `master`
|
||||
is untouched). Development continues on the local sibling checkout; push /
|
||||
@@ -104,9 +106,6 @@ config move in the right order. The sequence, with current status:
|
||||
4. **At release time**:
|
||||
- flip `meta-openglow` in `forgefirm-glowforge.yml` from the local-sibling
|
||||
block to the pinned-remote block (commented FUTURE block in the file);
|
||||
- drop meta-openglow's `kernel-module-glowforge.bbappend` (externalsrc to
|
||||
the local sibling — its perl-native DEPENDS is already carried in the
|
||||
base recipe) so a fresh clone is fully self-contained;
|
||||
- refresh `kas lock`, tag all repos, and prove self-containment by building
|
||||
from a **fresh clone**.
|
||||
5. **GitHub release**: run `scripts/release.sh <version>` on the build
|
||||
@@ -120,8 +119,11 @@ config move in the right order. The sequence, with current status:
|
||||
`v<version>` = `FORGEFIRM_RELEASE` = the rootfs `/etc/forgefirm-version`
|
||||
= the `.fw` meta-version; `release.sh` enforces the agreement.
|
||||
|
||||
For gfhardware development, either bump the recipe pin per iteration or add a
|
||||
tracked externalsrc bbappend mirroring the kernel-module pattern.
|
||||
All recipes fetch their pinned revision from GitHub, so an image build is
|
||||
reproducible from the repos alone. For fast iteration on a source repo, bump
|
||||
its pin per iteration, or add a **local, untracked** `externalsrc` bbappend
|
||||
pointing at the sibling checkout — never commit one, or released images stop
|
||||
matching the pins.
|
||||
|
||||
## Scarthgap migration backlog
|
||||
|
||||
@@ -145,8 +147,9 @@ Scarthgap, but the legacy (Dunfell/Gatesgarth) layers won't build clean until:
|
||||
`st,lis2hh12` ×3 + `national,lm75b` + `ti,wl1805` + gpio keys/leds bind to
|
||||
mainline drivers; `reg-userspace-consumer` enabled via `glowforge.cfg`.
|
||||
(SPI-delay / PWM-prescaler dispositions are under Motion polish below.)
|
||||
- **Motion path — DONE (builds clean; runtime needs hardware).** The whole
|
||||
chain forward-ports and compiles on 6.12:
|
||||
- **Motion path — DONE and hardware-validated** (live-fed pulse stream,
|
||||
real gantry motion, laser fire). The whole chain forward-ports and
|
||||
compiles on 6.12:
|
||||
- **EPIT API**: `epit_api.c` in `arch/arm/mach-imx` (`CONFIG_MXC_EPIT_API`),
|
||||
in vmlinux, symbols exported; `&epit1/&epit2` in the DT.
|
||||
- **SDMA-expose**: re-created `dma-imx-sdma.h` + `0003-imx-sdma-*.patch`
|
||||
@@ -166,16 +169,22 @@ Scarthgap, but the legacy (Dunfell/Gatesgarth) layers won't build clean until:
|
||||
`spi_imx_setupxfer` (write `MX51_ECSPI_PERIODREG` from `t->word_delay`,
|
||||
guarded to ECSPI) and verify the wait-states on a scope. pic.c keeps the
|
||||
inter-transfer delay meanwhile. `glowforge,imx-pwm-audio` (buzzer) deferred.
|
||||
- **Camera — DONE (builds clean; runtime needs hardware).** The factory
|
||||
- **Camera — DONE and hardware-validated.** The factory
|
||||
`ov5648_mipi.c` (NXP's removed `v4l2_int_device`/`mxc_v4l2_capture`) is
|
||||
replaced by the mainline `ovti,ov5648` subdev + imx6 `imx-media` (IPU CSI)
|
||||
+ `imx6-mipi-csi2` receiver. The factory CAM_SEL MIPI switch is modelled
|
||||
with the mainline `video-mux` (gpio-mux on `gpio7 10`): both `ov5648`s →
|
||||
video-mux → `mipi_csi` → IPU CSI. Sensor `xvclk` (25 MHz fixed-clock) +
|
||||
avdd/dovdd/dvdd rails in the DT. All drivers build as modules and
|
||||
`glowforge.dtb` compiles with the full pipeline. **HW bring-up:** confirm
|
||||
the real supply rails, CSI-2 lane count/order and CAM_SEL polarity, then
|
||||
validate with `media-ctl` + a v4l2 capture.
|
||||
with the mainline `video-mux` (gpio-mux on `gpio7 10`): both sensors →
|
||||
video-mux → `mipi_csi` → IPU CSI. Sensor `xvclk` is the board's 24 MHz
|
||||
fixed oscillator (matching the factory DTB); avdd/dovdd/dvdd rails are in
|
||||
the DT. Both cameras stream live through forgectrl (MJPEG at 15 fps with
|
||||
VPU JPEG encode, full-resolution snapshots, mux arbitration).
|
||||
**HD-unit caveat:** the DT lists both `ovti,ov5648` (5 MP) and
|
||||
`ovti,ov8856` (8 MP) at 0x36 so one image covers both, and the driver
|
||||
matching the chip ID wins — but mainline `ov8856` expects a 19.2 MHz
|
||||
xvclk and only warns at 24 MHz, and the capture path is written to
|
||||
ov5648's SBGGR8 2592×1944 format set. 8 MP "HD" modules therefore bind
|
||||
but do not capture; adding 24 MHz PLL modes plus a sensor-aware capture
|
||||
path is the open work.
|
||||
3. **u-boot** — **DONE.** The `glowforge` u-boot is
|
||||
a standalone `u-boot_2020.01.bb` (Scarthgap's poky has no u-boot 2020.01
|
||||
base recipe to extend). It reuses poky's
|
||||
@@ -186,8 +195,11 @@ Scarthgap, but the legacy (Dunfell/Gatesgarth) layers won't build clean until:
|
||||
`fw_printenv`/`fw_setenv` from `u-boot-fw-utils` to `libubootenv`
|
||||
(`PREFERRED_PROVIDER_u-boot-fw-utils` in `glowforge.inc`) when the rootfs needs
|
||||
them.
|
||||
4. **Device tree** — revalidate the `glowforge` `.dts` against the linux-fslc
|
||||
6.12 DT bindings (paired with the kernel forward-port in #2).
|
||||
4. **Device tree — DONE.** The `glowforge` `.dts` is validated against the
|
||||
linux-fslc 6.12 bindings and against the running board (motion, safety
|
||||
readbacks, cameras, sensors all bind and work). Residue: `control_12v`
|
||||
still uses the `reg-userspace-consumer` compatible, which matches no 6.12
|
||||
driver — convert it to `regulator-output` or drop the node.
|
||||
5. **Real-time strategy — decided.** The kernel runs
|
||||
`CONFIG_PREEMPT=y` (factory behavior; `imx_v6_v7_defconfig` alone gives only
|
||||
`PREEMPT_VOLUNTARY`). **PREEMPT_RT is not selectable on arm32 6.12** (no
|
||||
@@ -200,14 +212,14 @@ Scarthgap, but the legacy (Dunfell/Gatesgarth) layers won't build clean until:
|
||||
the underrun bench ever contradicts this arithmetic. (Bench: 5 s of
|
||||
continuous feed at a 1 s buffer depth, zero underruns.)
|
||||
|
||||
6. **gfui-client → forgectrl** — the Glowforge **cloud client is excluded**
|
||||
6. **gfui-client → forgectrl — DONE.** The stock `gfui-client` is excluded
|
||||
from `forgefirm-image` (`IMAGE_INSTALL:remove = "gfui-client"` in
|
||||
`meta-forgefirm/recipes-forgefirm/images/forgefirm-image.bb`) — it connected to
|
||||
Glowforge's servers, the dependency ForgeFIRM exists to cut. Its slot is
|
||||
filled by `forgectrl` (github.com/ScottW514/forgectrl — the ForgeFIRM
|
||||
control daemon; camera MJPEG service today, hardware status/control and
|
||||
GRBL-vs-cloud mode selection planned) plus the `grblhal-glowforge`
|
||||
motion controller (both in the images with boot autostart).
|
||||
`meta-forgefirm/recipes-forgefirm/images/forgefirm-image.bb`). Its slot is
|
||||
filled by `forgectrl` (github.com/ScottW514/forgectrl — the machine-services
|
||||
daemon: web control panel, cameras, telemetry, settings, diagnostics,
|
||||
cooling engine, updates, and controller-mode supervision) plus the two
|
||||
controllers it supervises, `grblhal-glowforge` (Grbl over TCP:23) and
|
||||
`gfcloud` (the optional Glowforge web-service client, off unless selected).
|
||||
|
||||
---
|
||||
|
||||
@@ -215,6 +227,7 @@ Scarthgap, but the legacy (Dunfell/Gatesgarth) layers won't build clean until:
|
||||
stack and deploys `forgefirm-image-glowforge.rootfs.wic.gz` (+ `zImage`,
|
||||
`glowforge.dtb`, `u-boot-glowforge.imx`) under `build/tmp/deploy/images/glowforge/`.
|
||||
Build-time prerequisites baked into the config: `ACCEPT_FSL_EULA = "1"` (NXP
|
||||
firmware-imx) and the kernel default in `glowforge.conf`. Everything compiles;
|
||||
on-hardware bring-up (motion timing, laser/safety chain, camera pipeline) is the
|
||||
remaining validation and needs a real board.
|
||||
firmware-imx — the image also installs `firmware-imx-lic` so the EULA text
|
||||
ships beside the blobs) and the kernel default in `glowforge.conf`. The stack
|
||||
is hardware-validated end to end: motion timing, the laser and safety chain,
|
||||
the camera pipeline, both controller modes, and the A/B install path.
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
# NXP distributes the i.MX VPU/EPDC firmware blobs under its firmware EULA
|
||||
# (accepted with ACCEPT_FSL_EULA), so an image carrying those blobs has to
|
||||
# carry the license text with them.
|
||||
#
|
||||
# LICENSE_CREATE_PACKAGE builds the license package, but license.bbclass adds
|
||||
# it to PACKAGES during do_package - too late for an image to depend on the
|
||||
# name. Declaring it here makes it resolvable at parse time; the class then
|
||||
# logs one "package already existed" note for this recipe, which is why FILES
|
||||
# is set here as well.
|
||||
LICENSE_CREATE_PACKAGE = "1"
|
||||
|
||||
PACKAGES:prepend = "${PN}-lic "
|
||||
FILES:${PN}-lic = "${datadir}/licenses/${PN}"
|
||||
@@ -25,6 +25,11 @@ IMAGE_INSTALL:remove = "gfui-client"
|
||||
# slotmigrate: boot-time reclaim of the legacy p4 layout (grows /data).
|
||||
IMAGE_INSTALL:append = " grblhal-glowforge forgectrl gfhome gfcloud v4l-utils fwup ffboot slotmigrate"
|
||||
|
||||
# NXP's firmware EULA covers the i.MX VPU/EPDC blobs the BSP installs, so the
|
||||
# image ships the license text with them (/usr/share/licenses/firmware-imx).
|
||||
# The SDMA firmware brings its own -license package through linux-firmware.
|
||||
IMAGE_INSTALL:append = " firmware-imx-lic"
|
||||
|
||||
# The release rootfs must fit a 200 MiB factory eMMC slot (409600 blocks).
|
||||
# Sizing: content + 40 MiB working space, hard-capped at the slot size —
|
||||
# the build fails rather than emit an unflashable image. The raw ext4 is
|
||||
|
||||
Reference in New Issue
Block a user