The GRBL settings store lives in /data/forgefirm

BRINGUP names the new path in the standalone start line and the
stored-settings note. forgectrl.panel-serves checks, in GRBL mode, that
the store is /data/forgefirm/EEPROM-glowforge.DAT and that nothing of it
remains at the top of /data. super.c is already in its covers map.
This commit is contained in:
ScottW514
2026-09-06 22:22:33 -04:00
parent a86d66049f
commit 9f715f08de
2 changed files with 18 additions and 9 deletions
+7 -7
View File
@@ -151,12 +151,12 @@ core mutex stands in for interrupt masking. `GFSINK` unset = null-sink mode
second. second.
3. Standalone start (bench/debug only - requires forgectrl stopped, since the 3. Standalone start (bench/debug only - requires forgectrl stopped, since the
broker's exclusive hold on `/dev/glowforge` makes any self-open fail EBUSY): broker's exclusive hold on `/dev/glowforge` makes any self-open fail EBUSY):
`cd /data && GFSINK=/dev/glowforge grblHAL_glowforge -p 23 -e `cd /data/forgefirm && GFSINK=/dev/glowforge grblHAL_glowforge -p 23 -e
/data/EEPROM-glowforge.DAT`. Env knobs: `GFSINK_RATE` (machine tick, default /data/forgefirm/EEPROM-glowforge.DAT`. Env knobs: `GFSINK_RATE` (machine
28160 Hz = factory travel tick), `GFSINK_DEPTH_MS` (queue depth = feed-hold tick, default 28160 Hz = factory travel tick), `GFSINK_DEPTH_MS` (queue
latency, default 200). Standalone, the driver opens the device itself and depth = feed-hold latency, default 200). Standalone, the driver opens the
every takeover runs the `rail_settle_s` off-period; under the broker it device itself and every takeover runs the `rail_settle_s` off-period; under
inherits the fd and skips the settle (the rail never dropped). The driver the broker it inherits the fd and skips the settle (the rail never dropped). The driver
applies the full analog machine config at init either way (×8 modes, decay 1, applies the full analog machine config at init either way (×8 modes, decay 1,
motor_lock 0 with every axis in the pulse path and the Z soft limit always motor_lock 0 with every axis in the pulse path and the Z soft limit always
on, laser latched, PIC hold currents) and swaps PIC run/hold on, laser latched, PIC hold currents) and swaps PIC run/hold
@@ -184,7 +184,7 @@ runtime `$35=0` the shipped duties stay floored.
**Stored `$`-settings beat freshly baked defaults** - after changing **Stored `$`-settings beat freshly baked defaults** - after changing
`GLOWFORGE_DEFAULTS` values, run `$RST=$` once on the board (settings persist `GLOWFORGE_DEFAULTS` values, run `$RST=$` once on the board (settings persist
in the eeprom file in `/data`). in `/data/forgefirm/EEPROM-glowforge.DAT`).
**Protocol-loop pacing is fd-blocking.** `serial_wait()` drains TX then **Protocol-loop pacing is fd-blocking.** `serial_wait()` drains TX then
`ppoll()`s the listen/client fds with a state-dependent timeout: idle and alarm `ppoll()`s the listen/client fds with a state-dependent timeout: idle and alarm
+11 -2
View File
@@ -1,5 +1,6 @@
"""forgectrl.* - the machine-services daemon's API, access control, and panel.""" """forgectrl.* - the machine-services daemon's API, access control, and panel."""
import json import json
import os
import socket import socket
import time import time
@@ -283,8 +284,10 @@ def settings_bounds(ctx):
"interval since the previous read, memory used percent), and /cam/status " "interval since the previous read, memory used percent), and /cam/status "
"answers. In GRBL mode with a live controller, /status also echoes the " "answers. In GRBL mode with a live controller, /status also echoes the "
"controller's published state file as the grbl block (fresh age, machine " "controller's published state file as the grbl block (fresh age, machine "
"state, sender session, laser window and dose model, modal report) and " "state, sender session, laser window and dose model, modal report), "
"GET /grbl/settings serves the published $$ view.") "GET /grbl/settings serves the published $$ view, and the controller's "
"settings store is /data/forgefirm/EEPROM-glowforge.DAT with nothing of "
"it at the top of /data.")
def panel_serves(ctx): def panel_serves(ctx):
fc = ctx.forgectrl fc = ctx.forgectrl
ev = ctx.evidence ev = ctx.evidence
@@ -350,6 +353,12 @@ def panel_serves(ctx):
ev["grbl_settings_status"] = st ev["grbl_settings_status"] = st
ctx.check(st == 200 and b"$35=" in (text or b""), ctx.check(st == 200 and b"$35=" in (text or b""),
"GET /grbl/settings -> %s without the $$ view", st) "GET /grbl/settings -> %s without the $$ view", st)
# The $-settings persist in the data directory, never loose in /data.
nvs = "/data/forgefirm/EEPROM-glowforge.DAT"
ev["grbl_nvs"] = os.path.isfile(nvs)
ctx.check(os.path.isfile(nvs), "the controller's settings store is not at %s", nvs)
ctx.check(not os.path.exists("/data/EEPROM-glowforge.DAT"),
"a settings store remains at the top of /data")
else: else:
ctx.log("no live GRBL controller (%s); grbl block checks skipped", mode) ctx.log("no live GRBL controller (%s); grbl block checks skipped", mode)