mirror of
https://github.com/openglow-org/forgefirm.git
synced 2026-09-28 01:01:12 -07:00
BRINGUP/SAFETY: interlock latch drive and watchdog readback bench-validated on image 20260815150546
Loop pull sets interlock_latch_reset + interlock_latch within one 50 ms sample and both clear on reinsert; charge_pump_alive tracks the run and falls 0.45 s after the last charge-pump pulse (matches the measured R*C); estop follows it on both edges. Note that an interlock trip parks grblHAL in Door:0 until a cycle start.
This commit is contained in:
+18
-3
@@ -2386,9 +2386,24 @@ accordingly ("Automatic — AP country, else World").
|
|||||||
Ships with the next image flash (kernel changes are never hot-swapped);
|
Ships with the next image flash (kernel changes are never hot-swapped);
|
||||||
bench re-run of this exact reading then expects `interlock_latch`=1 /
|
bench re-run of this exact reading then expects `interlock_latch`=1 /
|
||||||
`interlock_circuit` b4=1 with the loop open, both clearing after it is
|
`interlock_circuit` b4=1 with the loop open, both clearing after it is
|
||||||
closed. Same batch: the charge-pump watchdog readback (`cnc/charge_pump_alive`,
|
closed. **BENCH-VALIDATED 2026-08-15 on image 20260815150546:** loop
|
||||||
|
pulled → `interlock`=1, `interlock_latch_reset`=1, `interlock_latch`=1,
|
||||||
|
`interlock_circuit` 45→61 (b4 set), all within one 50 ms sample;
|
||||||
|
reinserted → all clear the same way. Side effect to know: the pull is
|
||||||
|
a grblHAL safety-door hold — the controller sits in `Door:0` after the
|
||||||
|
loop closes until a cycle start (`~`) returns it to Idle (a client
|
||||||
|
connecting then sees Door, not a dead link). Same batch: the charge-pump
|
||||||
|
watchdog readback (`cnc/charge_pump_alive`,
|
||||||
`interlock_circuit` b5; GPIO1_08 = inverted one-shot Q, new
|
`interlock_circuit` b5; GPIO1_08 = inverted one-shot Q, new
|
||||||
`charge-pump-alive-gpio` + GPIO_8 pad in the linux-fslc DTS — kernel
|
`charge-pump-alive-gpio` + GPIO_8 pad in the linux-fslc DTS — kernel
|
||||||
module and DTB must ship together, the pin is required at probe; DTB
|
module and DTB must ship together, the pin is required at probe; DTB
|
||||||
compile-checked with cpp+dtc against the staged kernel). Full write-up
|
compile-checked with cpp+dtc against the staged kernel) — **also
|
||||||
of the chain: `docs/SAFETY.md` (+ `docs/img/safety-chain.svg`).
|
bench-validated 2026-08-15:** two X jogs sampled at 50 Hz: `state`
|
||||||
|
running → `charge_pump_alive` 1 and `estop` 0 in the same 20 ms sample;
|
||||||
|
after each run `charge_pump_alive` fell 0.325 s / 0.326 s after `idle`,
|
||||||
|
which with the 200 ms feed phase (last pulse 0.136 s / 0.118 s before
|
||||||
|
the run end) is a one-shot period of **0.46 s / 0.44 s** — matching
|
||||||
|
the measured R·C (≈500 kΩ × ≈900 nF = 0.45 s); `estop` re-asserted
|
||||||
|
with the drop both times, i.e. HV_ENABLE = DOORS_OK · WDOG_ALIVE
|
||||||
|
observed live. Full write-up of the chain: `docs/SAFETY.md`
|
||||||
|
(+ `docs/img/safety-chain.svg`).
|
||||||
|
|||||||
+19
-18
@@ -47,7 +47,7 @@ away kills emission in hardware, not in software.
|
|||||||
|
|
||||||
| Ref | Part | Role |
|
| Ref | Part | Role |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| U1 | SN74AHC123A dual retriggerable monostable, R ≈ 499 kΩ / C ≈ 1 µF (t_w ≈ 0.45–0.5 s) | Charge-pump watchdog: Q stays high only while CHG_PUMP keeps arriving; times out ~0.5 s after the last pulse |
|
| U1 | SN74AHC123A dual retriggerable monostable, R ≈ 499 kΩ / C ≈ 1 µF (t_w ≈ 0.45 s, bench-measured) | Charge-pump watchdog: Q stays high only while CHG_PUMP keeps arriving; times out ≈0.45 s after the last pulse |
|
||||||
| U5, U6 | SN74AHC14 hex Schmitt-trigger inverters | Level inversion / conditioning for every switch line and SoC readback |
|
| U5, U6 | SN74AHC14 hex Schmitt-trigger inverters | Level inversion / conditioning for every switch line and SoC readback |
|
||||||
| U17 | SN74AHC08 quad 2-input AND | The four gates: DOORS, HV_ENABLE, and the two-stage LASER_ON gate |
|
| U17 | SN74AHC08 quad 2-input AND | The four gates: DOORS, HV_ENABLE, and the two-stage LASER_ON gate |
|
||||||
| U23 | CD4043B quad R/S latch (NOR type, active-high S/R, output enable tied high) | Latch 1 = button latch, latch 2 = interlock latch |
|
| U23 | CD4043B quad R/S latch (NOR type, active-high S/R, output enable tied high) | Latch 1 = button latch, latch 2 = interlock latch |
|
||||||
@@ -75,7 +75,7 @@ away kills emission in hardware, not in software.
|
|||||||
|
|
||||||
| Net | SoC pin | Driven by | Effect |
|
| Net | SoC pin | Driven by | Effect |
|
||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
| CHG_PUMP | GPIO3_24 (F22, `charge-pump-gpio`) | `glowforge.ko`: one 0→1→0 pulse at run start, then every 200 ms from a soft hrtimer **only while `state == running`**; forced low on stop, disable, unload and kernel panic | Retriggers U1-1 (t_w ≈ 0.45–0.5 s, so a 200 ms feed holds Q solidly high). No edges → Q falls within ~0.5 s → HV_ENABLE drops |
|
| CHG_PUMP | GPIO3_24 (F22, `charge-pump-gpio`) | `glowforge.ko`: one 0→1→0 pulse at run start, then every 200 ms from a soft hrtimer **only while `state == running`**; forced low on stop, disable, unload and kernel panic | Retriggers U1-1 (t_w ≈ 0.45 s, so a 200 ms feed holds Q solidly high). No edges → Q falls ≈0.45 s after the last pulse → HV_ENABLE drops |
|
||||||
| LATCH_RESET | GPIO1_07 (R3, `latch-reset-gpio`, init HIGH) | `cnc/laser_latch` (1 = lock). Also drives the FIRE line to high impedance while locked | Into U32 with lid-open; SETs the button latch → LASER_ON blocked until the next button press |
|
| LATCH_RESET | GPIO1_07 (R3, `latch-reset-gpio`, init HIGH) | `cnc/laser_latch` (1 = lock). Also drives the FIRE line to high impedance while locked | Into U32 with lid-open; SETs the button latch → LASER_ON blocked until the next button press |
|
||||||
| INTERLOCK_RESET | GPIO4_05 (P5, `interlock-latch-reset-gpio`, init HIGH) | `glowforge.ko`: high whenever the remote-interlock loop reads open, or until a switch device reporting the loop has attached; low only while an attached device reports it closed (in-kernel input handler on the gpio-keys switch, EV_SW code 5). Read back as `interlock_latch_reset` / `interlock_circuit` bit 4 | SET input of the interlock latch → LASER_ON blocked in hardware while the loop is open |
|
| INTERLOCK_RESET | GPIO4_05 (P5, `interlock-latch-reset-gpio`, init HIGH) | `glowforge.ko`: high whenever the remote-interlock loop reads open, or until a switch device reporting the loop has attached; low only while an attached device reports it closed (in-kernel input handler on the gpio-keys switch, EV_SW code 5). Read back as `interlock_latch_reset` / `interlock_circuit` bit 4 | SET input of the interlock latch → LASER_ON blocked in hardware while the loop is open |
|
||||||
| FIRE (LASER_ENABLE) | GPIO2_30 (E22, `laser-enable-gpio`) | The SDMA script, from bit 4 of each pulse byte; Hi-Z whenever the latch is locked or no run is in flight | One input of the final LASER_ON AND gate |
|
| FIRE (LASER_ENABLE) | GPIO2_30 (E22, `laser-enable-gpio`) | The SDMA script, from bit 4 of each pulse byte; Hi-Z whenever the latch is locked or no run is in flight | One input of the final LASER_ON AND gate |
|
||||||
@@ -195,8 +195,10 @@ would not allow.
|
|||||||
from the cooling engine (flow verification, over-temperature, lid-IR
|
from the cooling engine (flow verification, over-temperature, lid-IR
|
||||||
emission witness); a stale or failed verdict relocks in-process.
|
emission witness); a stale or failed verdict relocks in-process.
|
||||||
- **Safety door.** `doors` (lid) and `interlock` (loop open) are the core's
|
- **Safety door.** `doors` (lid) and `interlock` (loop open) are the core's
|
||||||
safety-door signal: a running job parks and resumes on close. This is a
|
safety-door signal: a running job parks; once the door/loop closes the
|
||||||
motion/UX gate; the lid is *also* cut in hardware by the button latch.
|
controller reports `Door:0` and a cycle start resumes it. This is a
|
||||||
|
motion/UX gate; the lid is *also* cut in hardware by the button latch,
|
||||||
|
and the interlock by the interlock latch (§3.1).
|
||||||
- **Head/motion witnesses.** Position counters are not proof of motion (the
|
- **Head/motion witnesses.** Position counters are not proof of motion (the
|
||||||
step-stream drives are open loop); the head accelerometer is the motion
|
step-stream drives are open loop); the head accelerometer is the motion
|
||||||
witness, and `beam_detect_analog` on the head is the live emission witness.
|
witness, and `beam_detect_analog` on the head is the live emission witness.
|
||||||
@@ -241,7 +243,14 @@ kernel readbacks (the runbook `BRINGUP.md` holds the drill records):
|
|||||||
- Armed kill mid-FIRE: emission tail equals the ring in-flight only
|
- Armed kill mid-FIRE: emission tail equals the ring in-flight only
|
||||||
(15–171 ms), the latch relocks, the burn line ends abruptly.
|
(15–171 ms), the latch relocks, the burn line ends abruptly.
|
||||||
- Switch bits 0–3, 5, 6 verified against physical state; bit 4 (`estop`)
|
- Switch bits 0–3, 5, 6 verified against physical state; bit 4 (`estop`)
|
||||||
characterized live: high at idle, low through any run.
|
characterized live: high at idle, low through any run, and it flips
|
||||||
|
together with `charge_pump_alive` on both edges (HV_ENABLE = DOORS_OK ·
|
||||||
|
WDOG_ALIVE observed).
|
||||||
|
- Interlock latch drive: with the connector unjumpered, `interlock`,
|
||||||
|
`interlock_latch_reset` and `interlock_latch` all assert within one 50 ms
|
||||||
|
sample and all clear when the loop is closed again.
|
||||||
|
- Watchdog period: `charge_pump_alive` falls ≈0.45 s after the last
|
||||||
|
charge-pump pulse (two runs, 0.44/0.46 s), matching the measured R·C.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -251,17 +260,9 @@ Present gaps in the hardware picture. None of them changes the safety
|
|||||||
argument (every gap is on the readback/sense side or is a "which part" question),
|
argument (every gap is on the readback/sense side or is a "which part" question),
|
||||||
but each is worth closing:
|
but each is worth closing:
|
||||||
|
|
||||||
- **`estop` toggles seen inside motion windows.** With the one-shot's
|
- **`estop` toggles seen inside motion windows** are run boundaries: `estop`
|
||||||
measured R/C (≈ 499 kΩ, ≈ 1 µF → t_w ≈ 0.45–0.5 s against a 200 ms feed)
|
follows the watchdog exactly (low from the first pulse of a run, high
|
||||||
the one-shot cannot gap during a healthy run, so those toggles are most
|
≈0.45 s after its last), and homing and jogs are several short runs. A
|
||||||
likely run boundaries (homing and jogs are several short runs) or a feed
|
feed late by more than ~250 ms would look the same and has not been
|
||||||
late by more than ~250 ms; `charge_pump_alive` sampled through a run
|
observed.
|
||||||
settles it.
|
|
||||||
- **Interlock latch drive: bench validation pending.** The board itself has
|
|
||||||
no trip path from the loop to the latch's SET input (bench-verified with the
|
|
||||||
connector unjumpered: `interlock` open, `interlock_latch` clear while
|
|
||||||
INTERLOCK_RESET was held low). The kernel drive described in §3.1 closes
|
|
||||||
that gap; its host test is green and it ships with the next image, where the
|
|
||||||
expected reading with the loop open is `interlock_latch` set,
|
|
||||||
`interlock_circuit` bit 4 set, clearing after the loop is closed.
|
|
||||||
- **`laser_pgood` (HV_OK, J1_14) semantics** are not fully characterized.
|
- **`laser_pgood` (HV_OK, J1_14) semantics** are not fully characterized.
|
||||||
|
|||||||
Reference in New Issue
Block a user