mirror of
https://github.com/openglow-org/forgefirm.git
synced 2026-09-27 16:51:12 -07:00
forgetest: the latch-unlock gate waits for the safety chain to release
The gate that refuses a latch unlock while the chain may hold HV_ENABLE up (charge_pump_alive or a pulse engine not idle) ran at the start of phases B, U and K3 of kernel.fire-line, within a second of the previous phase's run. A run feeds the charge-pump watchdog every 200 ms and the one-shot holds ALIVE for 0.45 s after the last feed, so the gate read alive=1 and refused: the first bench run of the gate (forgefirm 64f552fc; the laser_pgood gate before it was vacuous) failed phase B on image 20260902144848. wait_hv_off() polls the chain for up to 3 s before it refuses, logs the release when it was not immediate and records every wait in the evidence (hv_release_s). require_hv_off and check_hv_off use it. The bench scripts that copy the gate (fire_test.py per phase, gate_a_kernel_drills.py K3 after K2) get the same wait. Bench: kernel.fire-line PASS on 20260902144848 with the chain released after 0.41 s at each of the three phase boundaries. Host: tests/test_kernel_suite.py covers release inside the window, a chain held past it, and a chain already off. Catalog consequence: the kernel.* implementation hashes move (the suite file changed); the kernel set re-ran and passed.
This commit is contained in:
@@ -45,6 +45,18 @@ def hv_off_reason():
|
||||
return 'charge_pump_alive=%s state=%s' % (alive, state)
|
||||
return None
|
||||
|
||||
|
||||
def wait_hv_off(timeout_s=3.0):
|
||||
# A run feeds the charge-pump watchdog every 200 ms and the one-shot
|
||||
# holds ALIVE for 0.45 s after the last feed, so a phase that follows a
|
||||
# run finds the chain still up for under a second: wait for the release.
|
||||
t0 = time.time()
|
||||
why = hv_off_reason()
|
||||
while why is not None and time.time() - t0 < timeout_s:
|
||||
time.sleep(0.05)
|
||||
why = hv_off_reason()
|
||||
return why
|
||||
|
||||
def rd_pos():
|
||||
with open('/sys/glowforge/cnc/position', 'rb') as f:
|
||||
raw = f.read(32)
|
||||
@@ -72,7 +84,7 @@ stream = (
|
||||
print('phase %s: stream %d bytes = %.3f s' % (mode, len(stream), len(stream) / TICK_HZ))
|
||||
|
||||
if unlock:
|
||||
why = hv_off_reason()
|
||||
why = wait_hv_off()
|
||||
if why is not None:
|
||||
print('ABORT: the safety chain is not holding HV off (%s) - refusing latch unlock' % why)
|
||||
sys.exit(1)
|
||||
|
||||
@@ -65,6 +65,18 @@ def hv_off_reason():
|
||||
return 'charge_pump_alive=%s state=%s' % (alive, state)
|
||||
return None
|
||||
|
||||
|
||||
def wait_hv_off(timeout_s=3.0):
|
||||
# A run feeds the charge-pump watchdog every 200 ms and the one-shot
|
||||
# holds ALIVE for 0.45 s after the last feed, so a phase that follows a
|
||||
# run finds the chain still up for under a second: wait for the release.
|
||||
t0 = time.time()
|
||||
why = hv_off_reason()
|
||||
while why is not None and time.time() - t0 < timeout_s:
|
||||
time.sleep(0.05)
|
||||
why = hv_off_reason()
|
||||
return why
|
||||
|
||||
def rd_pos():
|
||||
with open('/sys/glowforge/cnc/position', 'rb') as f:
|
||||
raw = f.read(32)
|
||||
@@ -220,7 +232,7 @@ def drill_k2():
|
||||
|
||||
|
||||
def drill_k3():
|
||||
why = hv_off_reason()
|
||||
why = wait_hv_off()
|
||||
if why is not None:
|
||||
print('ABORT: the safety chain is not holding HV off (%s) - refusing latch unlock' % why)
|
||||
return 1
|
||||
|
||||
Reference in New Issue
Block a user