mirror of
https://github.com/openglow-org/forgefirm.git
synced 2026-09-29 09:31:17 -07:00
cp_watchdog_timing: do not starve the controller (no nice, sleep per pass), two jogs 4 s apart
This commit is contained in:
@@ -11,11 +11,13 @@ SoC's own pins, with no kernel change and no scope:
|
|||||||
|
|
||||||
The sampler arms rising-edge detection for GPIO3 pin 24 only (ICR2 bits
|
The sampler arms rising-edge detection for GPIO3 pin 24 only (ICR2 bits
|
||||||
17:16), clears that pin's sticky ISR flag, then polls ISR bit 24 and the two
|
17:16), clears that pin's sticky ISR flag, then polls ISR bit 24 and the two
|
||||||
readback pads in a tight loop, restoring ICR2 on exit. GPIO3 IMR bit 24 must
|
readback pads in a loop with a ~100 us sleep per pass, restoring ICR2 on
|
||||||
be clear (nothing has an interrupt on that pin; the run refuses otherwise),
|
exit. GPIO3 IMR bit 24 must be clear (nothing has an interrupt on that pin;
|
||||||
so the kernel never sees the flag. Reads and writes go through /dev/mem;
|
the run refuses otherwise), so the kernel never sees the flag. Reads and
|
||||||
the CHG_PUMP pad has SION set in the device tree, so its pad state is
|
writes go through /dev/mem; the CHG_PUMP pad has SION set in the device
|
||||||
visible.
|
tree, so its pad state is visible. The loop must not hog the CPU: only the
|
||||||
|
controller's shipper thread is SCHED_FIFO, its protocol/producer thread is
|
||||||
|
SCHED_OTHER, and a busy loop starves it so a run never ends.
|
||||||
|
|
||||||
Every run of the pulse engine (a jog is enough) primes the pump once and
|
Every run of the pulse engine (a jog is enough) primes the pump once and
|
||||||
then feeds it every 200 ms while `state == running`; when the run ends the
|
then feeds it every 200 ms while `state == running`; when the run ends the
|
||||||
@@ -26,9 +28,9 @@ count and period. Resolution = the loop period (tens of microseconds; the
|
|||||||
worst gap is printed).
|
worst gap is printed).
|
||||||
|
|
||||||
Usage: cp_watchdog_timing.py [seconds] [jog ...]
|
Usage: cp_watchdog_timing.py [seconds] [jog ...]
|
||||||
default: 16 s, jogs "$J=G91 X5 F300" "$J=G91 X-5 F300" x2 (out and back
|
default: 14 s, jogs "$J=G91 X5 F300" "$J=G91 X-5 F300" (out and back,
|
||||||
twice, 5 mm, head ends where it started), sent to the local grblHAL on
|
5 mm, head ends where it started), sent to the local grblHAL on
|
||||||
127.0.0.1:23 at t = 2, 4.6, 7.2, 9.8 s. Pass "-" as the only jog to sample
|
127.0.0.1:23 at t = 2 s and 6 s. Pass "-" as the only jog to sample
|
||||||
without commanding motion (drive the runs yourself).
|
without commanding motion (drive the runs yourself).
|
||||||
Motion only, laser locked; needs the GRBL controller idle with no other
|
Motion only, laser locked; needs the GRBL controller idle with no other
|
||||||
Grbl client attached (a connection here displaces the sender).
|
Grbl client attached (a connection here displaces the sender).
|
||||||
@@ -39,13 +41,14 @@ GPIO1, GPIO3, GPIO4 = 0x0209C000, 0x020A4000, 0x020A8000
|
|||||||
PSR, ICR2, IMR, ISR = 0x08, 0x10, 0x14, 0x18
|
PSR, ICR2, IMR, ISR = 0x08, 0x10, 0x14, 0x18
|
||||||
PULSE_PIN = 24 # GPIO3_24 CHG_PUMP
|
PULSE_PIN = 24 # GPIO3_24 CHG_PUMP
|
||||||
NQ_BIT, NHV_BIT = 8, 6 # GPIO1_08 !Q, GPIO4_06 !HV_ENABLE
|
NQ_BIT, NHV_BIT = 8, 6 # GPIO1_08 !Q, GPIO4_06 !HV_ENABLE
|
||||||
JOG_T0, JOG_DT = 2.0, 2.6
|
JOG_T0, JOG_DT = 2.0, 4.0
|
||||||
|
SLEEP_S = 0.0001
|
||||||
|
|
||||||
DEFAULT_JOGS = ['$J=G91 X5 F300', '$J=G91 X-5 F300'] * 2
|
DEFAULT_JOGS = ['$J=G91 X5 F300', '$J=G91 X-5 F300']
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
dur = float(sys.argv[1]) if len(sys.argv) > 1 else 16.0
|
dur = float(sys.argv[1]) if len(sys.argv) > 1 else 14.0
|
||||||
jogs = sys.argv[2:] if len(sys.argv) > 2 else DEFAULT_JOGS
|
jogs = sys.argv[2:] if len(sys.argv) > 2 else DEFAULT_JOGS
|
||||||
if jogs == ['-']:
|
if jogs == ['-']:
|
||||||
jogs = []
|
jogs = []
|
||||||
@@ -66,10 +69,13 @@ def main():
|
|||||||
if rd(g3, IMR) & (1 << PULSE_PIN):
|
if rd(g3, IMR) & (1 << PULSE_PIN):
|
||||||
print('ABORT: GPIO3 IMR bit %d is set - something has an interrupt on the pump pin' % PULSE_PIN)
|
print('ABORT: GPIO3 IMR bit %d is set - something has an interrupt on the pump pin' % PULSE_PIN)
|
||||||
return 2
|
return 2
|
||||||
try:
|
|
||||||
os.nice(-20)
|
def cnc_state():
|
||||||
except OSError:
|
try:
|
||||||
pass
|
with open('/sys/glowforge/cnc/state') as f:
|
||||||
|
return f.read().strip()
|
||||||
|
except OSError:
|
||||||
|
return '?'
|
||||||
|
|
||||||
sock = None
|
sock = None
|
||||||
if jogs:
|
if jogs:
|
||||||
@@ -109,6 +115,7 @@ def main():
|
|||||||
if nq != nq_prev:
|
if nq != nq_prev:
|
||||||
events.append((t, '!Q->%d' % nq))
|
events.append((t, '!Q->%d' % nq))
|
||||||
nq_prev = nq
|
nq_prev = nq
|
||||||
|
events.append((time.monotonic_ns(), 'cnc/state=' + cnc_state()))
|
||||||
if nhv != nhv_prev:
|
if nhv != nhv_prev:
|
||||||
events.append((t, '!HV->%d' % nhv))
|
events.append((t, '!HV->%d' % nhv))
|
||||||
nhv_prev = nhv
|
nhv_prev = nhv
|
||||||
@@ -123,6 +130,7 @@ def main():
|
|||||||
sent += 1
|
sent += 1
|
||||||
if t > tend:
|
if t > tend:
|
||||||
break
|
break
|
||||||
|
time.sleep(SLEEP_S)
|
||||||
finally:
|
finally:
|
||||||
wr(g3, ICR2, icr2_orig)
|
wr(g3, ICR2, icr2_orig)
|
||||||
wr(g3, ISR, 1 << PULSE_PIN)
|
wr(g3, ISR, 1 << PULSE_PIN)
|
||||||
|
|||||||
Reference in New Issue
Block a user