How ForgeFIRM works¶
This section describes the ForgeFIRM software: what runs on the control board, how the parts connect, and why they have the shape they have. This page is the overview. The other pages of the section detail each part.
What ForgeFIRM is¶
ForgeFIRM is open firmware for stock Glowforge lasers (Basic, Plus, and Pro). It runs on the factory NXP i.MX6 control board already inside the machine, with no hardware modification. It replaces the cloud-dependent factory userspace with an open Linux image that controls the machine locally. A stock Glowforge becomes a standard Grbl and LightBurn controlled laser, with the factory cloud experience still available as an option.
It reuses what the factory hardware already does well, the low-jitter SDMA + EPIT step-stream playback and the OV5648 MIPI cameras, and replaces the cloud userspace with local software.
What is replaced and what is kept¶
The factory machine cannot cut without Glowforge's servers. It downloads serial-locked, gzip-compressed "pulse files" over a pinned-TLS session and clocks that precomputed byte stream out of a DMA ring, through the i.MX6 EPIT timer and the SDMA engine, into a GPIO register: jitter-free hardware step generation. ForgeFIRM keeps the SDMA + EPIT step-stream mechanism and feeds it a live, planner-generated stream from grblHAL instead, which cuts the cloud out entirely. The kernel module also accepts a whole precomputed pulse file, which is how the optional cloud mode works.
The byte format and the playback engine are described under The step engine. The factory software is described under The factory firmware.
Architecture¶
graph TD
senders["LightBurn / UGS / cncjs<br>Grbl over TCP port 23"]
service["Glowforge web service<br>(optional)"]
subgraph controllers["Controllers (one at a time)"]
grbl["grblHAL-glowforge<br>grblHAL core + ForgeFIRM driver"]
gfcloud["gfcloud (Python)<br>factory action dispatch"]
end
forgectrl["forgectrl<br>machine-services daemon, HTTPS 443, HTTP 80"]
ko["glowforge.ko<br>SDMA + EPIT pulse engine, laser latch, safety readbacks"]
cams["Cameras<br>ov5648, video-mux, imx6-mipi-csi2, imx-media, VPU encode"]
senders --> grbl
service --> gfcloud
grbl --> forgectrl
gfcloud --> forgectrl
forgectrl --> ko
forgectrl --> cams
The layers, from the top:
- The senders and the service. In GRBL mode a Grbl sender (LightBurn, UGS, cncjs) connects over TCP port 23. In cloud mode the Glowforge web service drives the machine.
- The controllers. Exactly one runs at a time; the choice is the
mode.
grblHAL-glowforgeis the grblHAL core plus the ForgeFIRM driver: the G-code parser, the planner with look-ahead, and the Grbl protocol; a step backend that resamples step events to pulse bytes and live-feeds the kernel ring; the laser path, which emits power bytes and the FIRE bit under an operator-armed window; and a cooling client that reports job state and enforces the cooling verdict (The grblHAL driver).gfcloudis a Python daemon: it dispatches the factory actions and preloads factory pulse files (Cloud mode). - forgectrl, the machine-services daemon on HTTPS port 443 and HTTP
port 80: the
supervisor that spawns and respawns the selected controller, the
pulse-device broker (one exclusive hold of
/dev/glowforge; the controllers inherit the file descriptor), the motion-liveness gate, the cooling engine (the sole owner of the thermal hardware), the cameras, telemetry, settings, diagnostics, the web control panel, and the A/B updates (forgectrl). - glowforge.ko, the kernel module: SDMA + EPIT playback into the GPIO register that drives the stepper drivers, the laser latch, and the safety readbacks (The kernel module).
- The cameras: the mainline
ov5648driver,video-mux,imx6-mipi-csi2, andimx-media(IPU CSI), with JPEG and H.264 encoding on the VPU (The video pipeline).
A reserved memory pool in the device tree backs the pulse ring. The pool, the ring size, and what the size means for each mode are described under The image and the BSP and The step engine.
Laser safety¶
The hardware chain is the safety boundary, and it stays that way:
LID_SW1 & LID_SW2 & INTERLOCK & HV_OK & supplies-OK -> OK_2_FIRE, and
FIRE & OK_2_FIRE -> LASER_ON. LASER_ON is never a bare GPIO. The chain
is described under The safing chain; the gates
as the operator meets them are in Safety and
GRBL mode.
On top of the chain, software adds gates in front of it, and never a bypass:
- the kernel laser latch, locked by default; the final close of the pulse device relocks it (The kernel module);
- the operator-armed window: the physical button must be pressed before the first fire of a job, and the window relocks after idle (The grblHAL driver);
- the coolant fire gates: flow verification and over-temperature (The cooling engine);
- fail-safe behavior on fault, abort, or underrun (The pulse-feeder contract).
Position counters are not proof of physical motion. The head accelerometer is (see "Who owns the motion hardware" below).
Design decisions¶
- Device ownership. forgectrl holds
/dev/glowforgefor its lifetime, and the controllers inherit the file descriptor. A handover never cycles the 40 V motor rail, because a rail glitch can leave the stepper drivers unserviceable. The rail stays up while the machine is on (forgectrl). - Kernel interface shape. The kernel ring accepts live appends during a
run, with
freeas the backpressure primitive, plus explicit end-of-data, underrun, and dead-man semantics (The pulse-feeder contract). - Real time. The kernel runs with
CONFIG_PREEMPT=y, a deep ring, and aSCHED_FIFOfeeder. PREEMPT_RT is not selectable on arm32 6.12, and the buffer arithmetic makes it unnecessary (The grblHAL driver, The image and the BSP). - Cameras. The mainline
ov5648,video-mux,imx6-mipi-csi2, andimx-mediadrivers, not the factory NXPov5648_mipi.c. forgectrl owns the pipeline. The 8 MP "HD" (OV8856) capture path is implemented and untested on hardware (The video pipeline, The cameras). - Cloud mode stays. The factory cloud experience is kept and maintained as a mode, never stripped (Cloud mode, Cloud mode, for the operator).
- A/B slot install. ForgeFIRM installs into the unused factory A/B rootfs
slot and archives every factory version first.
ffbootswitches slots, andfwupapplies signed.fwreleases (Install and update, Install, Back to the factory firmware, Updating).
Who owns the motion hardware¶
forgectrl, the machine-services daemon, owns the pulse device for as long
as it runs and hands the open connection to whichever controller is active.
Only one controller, GRBL or cloud, runs at a time, and switching between
them is a live operation from the web panel.
Two behaviors follow from this that you will notice:
- The 40 V motor rail stays up while the machine is on. Handing the device from one controller to another never cycles it. The stepper drivers on this board can latch into an unserviceable state on a rail glitch (the position counters keep counting while the motors produce nothing), so the rail is left alone.
- The machine proves it can move before the first job of a session. Before the first controller start, forgectrl makes a short test move (always to the right first; a cable lives at the left end of travel) and confirms it with the accelerometer in the print head. If it sees no motion it powers the rail down and retries with progressively longer off periods. If the drivers still will not wake, it reports a motion fault instead of starting a controller, and the panel offers a retry. Position counters advancing are never accepted as proof that the machine moved.
The two modes side by side¶
| GRBL mode | Cloud mode | |
|---|---|---|
| Who plans motion | grblHAL on the machine | the Glowforge service |
| Input | G-code over TCP port 23 | a downloaded pulse file |
| Ring use | live-streamed, small window | preloaded before the button; topped up as it drains when the job is longer than the ring |
| Machine tick | 28160 Hz default | 10 kHz (from the job header) |
| Job length limit | none | none (the ring buffers ~56 minutes at a time) |
| Needs internet | no | yes |
| Laser arming | button press per job | button press per job |
| Button mid-job | feed hold / cycle start | pause with backtrack / resume with lead |
| Lid or interlock open | cancel + return to job start | cancel + park at job start |
| Homing | $H (camera; limit switches planned) |
automatic, camera-based |
| Fan control | M8/M9 plus the armed window |
per-job duties from the job header |
| Underrun possible | yes (handled as a fault) | no (nothing is streamed) |
Only one mode runs at a time. Switch from the panel's Status tab; the switch is allowed only when the machine is idle (Modes).
The pages of this section¶
| Page | Contents |
|---|---|
| The kernel module | glowforge.ko: the pulse engine, the laser latch, the safety readbacks, the sensors, and the sysfs tree. |
| The pulse-feeder contract | The pulse device: the ring, append and free, end of data, underrun, the dead-man, and backtrack. |
| The grblHAL driver | The GRBL-mode controller: from G-code to pulse bytes, the laser path, the armed window, lid and button handling, faults, the cooling client. |
| forgectrl | The machine-services daemon: supervision, the pulse-device broker, the motion-liveness gate, telemetry, settings, diagnostics. |
| The cooling engine | Fans, pump, TEC, and heater; flow verification; the gates; the job-state reports and the verdict file. |
| The video pipeline | What the cameras send, the privacy gate, the encoders, lighting, and the arbitration of the single camera path. |
| Cloud mode | The factory-experience client: components, scope, jobs, the firmware-update policy, the offline service, the emulator. |
| Homing | Camera-referenced homing in both modes, running unhomed, and the planned limit-switch cycle. |
| Install and update | The A/B slot installer, the invariants and contracts of the update system, the release pipeline. |
| Logging | One transport, one writer: the emitters, the loggers, the levels, the export sanitizer. |
| The image and the BSP | The Yocto layers, the kernel, the device tree, and the reserved memory pool. |