laser_lifecycle_test: rule 17's abort lands in a move above the step-smoothing cutoff

Rule 17's ^X mid-move goes out during G1 X120 F3000 instead of
G1 X30 F600, and the plausibility bound on the distance the abort
kept widens to the new move's length. Every other line of the rule
stays.

At $100 = 213.333 the F600 move cruises at about 2133 steps/s. The
core's step smoothing puts a rate between 2000 and 4000 steps/s at
level 2: four interrupt callbacks per step period, and only one in
four carries an X step. The core counts a step one interrupt callback
ahead of the pulse start that outputs it, so a reset leaves a pending
step only when its idle lands on a callback that carries one, one run
in four at F600. On the null sink the shipped backlog is empty by the
time the reset runs and the residue is zero, so that pending step is
all the position check can see, and the check is the harness's only
proof of the driver's hand-over of the step at the idle and of the
read-back correction. At F3000 the move cruises at 10667 steps/s,
above the 8000 steps/s cutoff of level 0, where every callback
carries a step and every reset owes one. The ^X goes out 0.5 s after
the move reports Run and lands near 56 mm of the 120, inside the
move.

Proof: python3 -m py_compile and pyflakes 4.0.3 are clean on
scripts/bench/laser_lifecycle_test.py. Against the null-sink build of
the grblHAL-glowforge default branch head, configured as its CI
configures it (-DGFMCODE_WAIT_S=5.0), rule 17 passes 10 runs in 10
and the harness passes whole. Two scratch mutants of that tree's
driver.c, each built the same way: (a) readback_position keeps
sys.position as the core counted it, with the position_lost handling
kept; (b) stepperGoIdle hands the engine no pending step, the step
and direction bits passed to gf_stream_go_idle forced to 0. With this
change each fails rule 17 in 5 runs of 5, every time on the position
check with MPos one step past the stream (17104.0 steps against
17103 for (a), 17197.0 against 17196 for (b), in their first runs).
With the parent's F600 the same mutants pass rule 17 15 runs in 20
(a) and 14 runs in 20 (b). The harness runs in grblHAL-glowforge CI,
step "Armed-window lifecycle" (python3
forgefirm/scripts/bench/laser_lifecycle_test.py
build/grblHAL_glowforge), from the head of this repository's default
branch.

Acceptance: none. scripts/bench/ is outside every covers map.
This commit is contained in:
ScottW514
2026-10-17 18:51:58 -04:00
parent 18cba1daa2
commit c978e76b4c
+2 -2
View File
@@ -945,7 +945,7 @@ def test_cancel_and_abort():
s.send_raw("M5")
s.send_raw("G91")
s.send_raw("G1 X30 F600") # 3 s
s.send_raw("G1 X120 F3000") # 2.4 s
if not s.wait_state("Run", 5):
fail("[cancel-abort] the move never reported Run (state %s)" % s.state())
time.sleep(0.5)
@@ -957,7 +957,7 @@ def test_cancel_and_abort():
fail("[cancel-abort] ^X mid-move did not ask the kernel to stop with its ramp "
"(no cnc/stop write)")
x2 = s.mpos_x()
if x2 is None or not 0.5 < x2 - x1 < 29.5:
if x2 is None or not 0.5 < x2 - x1 < 119.5:
fail("[cancel-abort] the abort did not keep a plausible position (X %s from %.3f)" % (x2, x1))
moved = s.shipped_x_steps()
if abs(x2 * spm - moved) > 0.5: