Keep the configuration files inside /data/forgefirm; pin the three components

ForgeFIRM's own files live under /data/forgefirm; two configuration
files did not. The machine settings sat at /data/forgefirm.conf, in the
root of /data beside the factory's own files, and the cloud-mode
configuration sat at /data/etc/gfhome.conf, inside a directory the
factory owns. Both move:

  /data/forgefirm.conf   -> /data/forgefirm/forgefirm.conf
  /data/etc/gfhome.conf  -> /data/forgefirm/gfhome.conf

There is no migration: only the bench has ever run this firmware.
/data/etc now holds only the factory's wpa_supplicant.conf.

The acceptance check of the file modes reads the settings file at its
new path, and the two bench tools that read it directly follow. The
pins move to the revisions that carry the change, forgectrl also
bringing the fix that reads the module's disabled state as idle:

  forgectrl           468ee21 (0.1.12)
  grblhal-glowforge   9ee624b (0.1.10)
  forgefirm-app       56f134a (0.1.28+git)

The lock moves meta-openglow to b7ad6d9, which pins python3-gfhardware
on the same revision. The four upstream layers stay where they were:
`kas lock --update` moves every floating repository, and a release is
not the place to take poky, meta-openembedded and meta-freescale along
for the ride.
This commit is contained in:
ScottW514
2026-09-09 15:32:54 -04:00
parent 61030da69b
commit 64301d3221
10 changed files with 13 additions and 13 deletions
+1 -1
View File
@@ -236,7 +236,7 @@ def image_health(ctx):
ctx.check(not user_wd, "a userspace watchdog daemon is running: %s", user_wd) ctx.check(not user_wd, "a userspace watchdog daemon is running: %s", user_wd)
# 7. file modes and space # 7. file modes and space
for path in ("/data/forgefirm/panel.token", "/data/forgefirm.conf"): for path in ("/data/forgefirm/panel.token", "/data/forgefirm/forgefirm.conf"):
if os.path.exists(path): if os.path.exists(path):
m = stat.S_IMODE(os.stat(path).st_mode) m = stat.S_IMODE(os.stat(path).st_mode)
ev[path] = "%o" % m ev[path] = "%o" % m
+1 -1
View File
@@ -11,4 +11,4 @@ overrides:
meta-freescale-distro: meta-freescale-distro:
commit: b9d6a5d9931922558046d230c1f5f4ef6ee72345 commit: b9d6a5d9931922558046d230c1f5f4ef6ee72345
meta-openglow: meta-openglow:
commit: d655e1e58c97224236f21472b02cb19f32eab982 commit: b7ad6d9377fbb4215dc4d898837906b06b47e5e9
@@ -3,7 +3,7 @@
# rsyslog is the only log writer on the machine. Every ForgeFIRM process # rsyslog is the only log writer on the machine. Every ForgeFIRM process
# (forgectrl, grblHAL, gfcloud, gfhome), the kernel, and everything else # (forgectrl, grblHAL, gfcloud, gfhome), the kernel, and everything else
# route to their own directory under /data/log/forgefirm. The per-logger # route to their own directory under /data/log/forgefirm. The per-logger
# disk and remote levels come from /data/forgefirm.conf and are rendered # disk and remote levels come from /data/forgefirm/forgefirm.conf and are rendered
# into the included rules file at every boot by `forgectrl # into the included rules file at every boot by `forgectrl
# --render-syslog` (see the forgefirm-logging init script), so a change # --render-syslog` (see the forgefirm-logging init script), so a change
# made in the control panel applies at the next reboot. # made in the control panel applies at the next reboot.
@@ -2,5 +2,5 @@
# only SRCREV and PV here - the image manifest leaves *-pin.inc out of the # only SRCREV and PV here - the image manifest leaves *-pin.inc out of the
# layer content hash because the component entry already identifies the # layer content hash because the component entry already identifies the
# pinned source (forgefirm-image-manifest.bbclass). # pinned source (forgefirm-image-manifest.bbclass).
SRCREV = "439a8889ce0edb8ca8ab83f02bd3c3e0f09dd91a" SRCREV = "468ee215dd1148b92c979decacecc41aa6a75ccf"
PV = "0.1.11" PV = "0.1.12"
@@ -4,9 +4,9 @@
# because the component entry already identifies the pinned source # because the component entry already identifies the pinned source
# (forgefirm-image-manifest.bbclass). The python3-gfhardware recipe in # (forgefirm-image-manifest.bbclass). The python3-gfhardware recipe in
# meta-glowforge-bsp pins the same repository; move both together. # meta-glowforge-bsp pins the same repository; move both together.
SRCREV = "53d57f7c84fd314012f21bbbee883dde95353ded" SRCREV = "56f134a1e6393a2096c16e8226027fbbd38d79c7"
# Bump PV with every SRCREV move: the hash-derived package version is not # Bump PV with every SRCREV move: the hash-derived package version is not
# monotonic on its own and buildhistory QA fails the build when it sorts # monotonic on its own and buildhistory QA fails the build when it sorts
# backwards. # backwards.
PV = "0.1.27+git" PV = "0.1.28+git"
@@ -2,5 +2,5 @@
# changes; keep only SRCREV and PV here - the image manifest leaves # changes; keep only SRCREV and PV here - the image manifest leaves
# *-pin.inc out of the layer content hash because the component entry # *-pin.inc out of the layer content hash because the component entry
# already identifies the pinned source (forgefirm-image-manifest.bbclass). # already identifies the pinned source (forgefirm-image-manifest.bbclass).
SRCREV = "97be92bbc8443ff8c4a3176fa2594cd6828c1c65" SRCREV = "9ee624bbc1d1fd929f1f5587b6fc6acaa13a4561"
PV = "0.1.9" PV = "0.1.10"
@@ -28,7 +28,7 @@ IMAGE_INSTALL:remove = "python3 ${FORGEFIRM_RELEASE_TRIM}"
# broker, cooling engine, cameras, telemetry, settings, diagnostics, web # broker, cooling engine, cameras, telemetry, settings, diagnostics, web
# control panel, and A/B updates. # control panel, and A/B updates.
# gfhome: one-shot Glowforge web-service homing, invoked by the controller # gfhome: one-shot Glowforge web-service homing, invoked by the controller
# for $H when homing_mode = gfcloud (/data/forgefirm.conf). # for $H when homing_mode = gfcloud (/data/forgefirm/forgefirm.conf).
# gfcloud: full Glowforge web-service controller daemon (the factory cloud # gfcloud: full Glowforge web-service controller daemon (the factory cloud
# experience), started when controller_mode = cloud - mutually exclusive with # experience), started when controller_mode = cloud - mutually exclusive with
# grblHAL. Pulls python3-ffmachine (shared web-service machine glue). # grblHAL. Pulls python3-ffmachine (shared web-service machine glue).
+1 -1
View File
@@ -40,7 +40,7 @@ page's takeover does that; from a host, stop them first.
| `raster_dry.py` | A dry raster at top speed at each XY microstep mode (runs on the board; the controller in GRBL mode, idle, no other Grbl client): per mode given (default 8, 16, 32) it stores `xy_microsteps` through forgectrl, waits for the restarted controller, streams 60 passes of 150 mm at F12000 with the laser off, and reports the peak feed, the controller CPU, the kernel counters against the start, `cnc/underruns` and any clamped-event line. Needs 150 mm of free +X and 12 mm of free +Y travel. Ends at x8. | | `raster_dry.py` | A dry raster at top speed at each XY microstep mode (runs on the board; the controller in GRBL mode, idle, no other Grbl client): per mode given (default 8, 16, 32) it stores `xy_microsteps` through forgectrl, waits for the restarted controller, streams 60 passes of 150 mm at F12000 with the laser off, and reports the peak feed, the controller CPU, the kernel counters against the start, `cnc/underruns` and any clamped-event line. Needs 150 mm of free +X and 12 mm of free +Y travel. Ends at x8. |
| `xy_pattern_accel.py` | The XY microstep modes by the head accelerometer with the machine silent (runs on the board; the machine homed and at home, the lid closed, no other Grbl client): per mode it takes the cooling engine's quiet hold with the pump (`POST /cool/quiet?on=1&pump=1`: every fan, the pump and the TEC off), waits the fixed 10 s, samples the LIS2HH12 over `/dev/i2c-3` in one SMBus block transaction per reading at about 600 Hz, and runs the pattern from home at F12000: to (18, 9) in, to (9, 9) in, a 9 in circle from its mid-bottom back to (9, 9), to (9, 0), home. Reports the cruise-window RMS and peak-to-peak per leg and overall, the leg times, the kernel counters against home and `cnc/underruns`; JSON with the trace in the bench data directory. Ends at x8. | | `xy_pattern_accel.py` | The XY microstep modes by the head accelerometer with the machine silent (runs on the board; the machine homed and at home, the lid closed, no other Grbl client): per mode it takes the cooling engine's quiet hold with the pump (`POST /cool/quiet?on=1&pump=1`: every fan, the pump and the TEC off), waits the fixed 10 s, samples the LIS2HH12 over `/dev/i2c-3` in one SMBus block transaction per reading at about 600 Hz, and runs the pattern from home at F12000: to (18, 9) in, to (9, 9) in, a 9 in circle from its mid-bottom back to (9, 9), to (9, 0), home. Reports the cruise-window RMS and peak-to-peak per leg and overall, the leg times, the kernel counters against home and `cnc/underruns`; JSON with the trace in the bench data directory. Ends at x8. |
| `arc_tolerance_sweep.py` | How fine an arc the controller can plan (runs on the board; the machine homed and at home, the lid closed, no other Grbl client, the machine silent through the quiet hold): a `$12` ladder on the 9 in circle at F12000 at the mode given (`--mode`, default 16). Per rung: the chords and the chord boundaries a second, the circle time against the ideal, the lowest feed mid-circle and the fewest free planner blocks, the controller CPU, clamped events, underruns and the accelerometer's cruise RMS. `$12` goes back to what it was on every exit path; the head returns home. | | `arc_tolerance_sweep.py` | How fine an arc the controller can plan (runs on the board; the machine homed and at home, the lid closed, no other Grbl client, the machine silent through the quiet hold): a `$12` ladder on the 9 in circle at F12000 at the mode given (`--mode`, default 16). Per rung: the chords and the chord boundaries a second, the circle time against the ideal, the lowest feed mid-circle and the fewest free planner blocks, the controller CPU, clamped events, underruns and the accelerometer's cruise RMS. `$12` goes back to what it was on every exit path; the head returns home. |
| `gfbench.py` | Not a tool: the helper the board/host tools share - `HOST`/`LOCAL` from `GF_HOST`, `board(cmd)` (local `sh -c` or ssh), the factory coolant conversion `degc()`, `data_path()` (`FORGETEST_BENCH_DATA` or next to the tool), forgectrl's HTTP API with the panel token, `setting(key)` (from forgectrl, or from `/data/forgefirm.conf` on the board while forgectrl is stopped). | | `gfbench.py` | Not a tool: the helper the board/host tools share - `HOST`/`LOCAL` from `GF_HOST`, `board(cmd)` (local `sh -c` or ssh), the factory coolant conversion `degc()`, `data_path()` (`FORGETEST_BENCH_DATA` or next to the tool), forgectrl's HTTP API with the panel token, `setting(key)` (from forgectrl, or from `/data/forgefirm/forgefirm.conf` on the board while forgectrl is stopped). |
| `lens_travel.py` | Lens travel drill (runs on the board; stops the controller through forgectrl and restarts it; lens motion only): steps the lens over sysfs the way the focus card's lens home does and counts, per condition and round, the hall's hysteresis band (down off the rising edge until the hall leaves home, back up until it reads home), the rising edge's height above the bottom stop after a drive onto it, and the top stop's height above the edge (a drive up, down until the hall leaves home, back up; the difference). Conditions: the card's half-step drive onto the stop, a short drive, a long one, the factory's full-step home mode; `--ladder` drives a list of half-step descents below the leave-home point and counts each back (exact until the stop, short by an even number after a stall), `--current` picks the run current, the hold current, or hold down / run up, `--settle` and `--cadence` vary the timing; `--park bottom|top|edge-N|edge+N` holds the lens there for a depth-gauge reading with the controller in standby, `--park edge` returns it to the rising edge and restarts the controller. Stall drills on the bench reference machine only. The posture found is put back. | | `lens_travel.py` | Lens travel drill (runs on the board; stops the controller through forgectrl and restarts it; lens motion only): steps the lens over sysfs the way the focus card's lens home does and counts, per condition and round, the hall's hysteresis band (down off the rising edge until the hall leaves home, back up until it reads home), the rising edge's height above the bottom stop after a drive onto it, and the top stop's height above the edge (a drive up, down until the hall leaves home, back up; the difference). Conditions: the card's half-step drive onto the stop, a short drive, a long one, the factory's full-step home mode; `--ladder` drives a list of half-step descents below the leave-home point and counts each back (exact until the stop, short by an even number after a stall), `--current` picks the run current, the hold current, or hold down / run up, `--settle` and `--cadence` vary the timing; `--park bottom|top|edge-N|edge+N` holds the lens there for a depth-gauge reading with the controller in standby, `--park edge` returns it to the rising edge and restarts the controller. Stall drills on the bench reference machine only. The posture found is put back. |
| `lens_stop_accel.py` | Lens stop detection by the head accelerometer (runs on the board; stops the controller through forgectrl and restarts it; lens motion only; stall drills on the bench reference machine only): reads the LIS2HH12 straight over `/dev/i2c-3` in six-byte bursts at 800 Hz (the iio path waits a sample period per read), steps the lens one half-step at a time from the hall's rising edge toward each stop and past it, and prints per step the peak-to-peak on each axis. A free step rings strongly on every second half-step; at a stop the ring dies, and a rotor slip a few steps later is a burst three times any free ring. `--find N` runs the contact rule N times per stop (a strong-parity step ringing under `--thresh`, or a burst over four times it, calls contact; the lens backs off `--back` and the count home proves no slip). `--save` keeps the per-step sample traces as JSON. | | `lens_stop_accel.py` | Lens stop detection by the head accelerometer (runs on the board; stops the controller through forgectrl and restarts it; lens motion only; stall drills on the bench reference machine only): reads the LIS2HH12 straight over `/dev/i2c-3` in six-byte bursts at 800 Hz (the iio path waits a sample period per read), steps the lens one half-step at a time from the hall's rising edge toward each stop and past it, and prints per step the peak-to-peak on each axis. A free step rings strongly on every second half-step; at a stop the ring dies, and a rotor slip a few steps later is a burst three times any free ring. `--find N` runs the contact rule N times per stop (a strong-parity step ringing under `--thresh`, or a burst over four times it, calls contact; the lens backs off `--back` and the count home proves no slip). `--save` keeps the per-step sample traces as JSON. |
| `fan_test.py` | Fan/coolant bench (board or host; controller running): snapshots fan PWMs/tachs/temps, drives M8 → cut fans, M9 → cooldown → idle, verifying via tach readbacks. | | `fan_test.py` | Fan/coolant bench (board or host; controller running): snapshots fan PWMs/tachs/temps, drives M8 → cut fans, M9 → cooldown → idle, verifying via tach readbacks. |
+1 -1
View File
@@ -144,7 +144,7 @@ def forgectrl_post(path, **kw):
return forgectrl_request("POST", path, **kw) return forgectrl_request("POST", path, **kw)
SETTINGS_FILE = "/data/forgefirm.conf" SETTINGS_FILE = "/data/forgefirm/forgefirm.conf"
def setting(key, default=None): def setting(key, default=None):
+1 -1
View File
@@ -657,7 +657,7 @@ DLADDER_LEN = 25.0 # mm of burn per rung
DLADDER_PITCH = 3.0 # mm between rungs DLADDER_PITCH = 3.0 # mm between rungs
STREAM_RATE_HZ = 28160 # machine tick (GFSINK_RATE default) STREAM_RATE_HZ = 28160 # machine tick (GFSINK_RATE default)
PWM_PERIOD = 127 # 7-bit power byte against PWMSAR PWM_PERIOD = 127 # 7-bit power byte against PWMSAR
CONF = os.environ.get('GFHOME_CONF') or '/data/forgefirm.conf' CONF = os.environ.get('GFHOME_CONF') or '/data/forgefirm/forgefirm.conf'
PULSE_MIN_KEY = 'laser_pulse_min_ticks' PULSE_MIN_KEY = 'laser_pulse_min_ticks'
PULSE_MIN_DEFAULT = 3 # glowforge_laser.c PULSE_MIN_TICKS_DEFAULT PULSE_MIN_DEFAULT = 3 # glowforge_laser.c PULSE_MIN_TICKS_DEFAULT