bdp_guard: one lock for all I2C transfers of the bd_pressure
The guard's timer read the sensor while G28 ran; bdpressure.py writes the
probe mode at every homing move, and Klipper allows only one I2C request
at a time per device: KeyError ('i2c_response', 1), Klipper shut down
during HOME. The guard now wraps the sensor's i2c in a reactor mutex at
connect; bdpressure and bdpressure_check (now looks up sensor.i2c at
every use) go through it too.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
61fa8acb05
commit
8eef0ee298
3 files changed
+47
-6
No files matched your search
+39
-1
@@ -46,6 +46,38 @@ EXT_MAGIC = 0xBD
|
||||
MODES = ('log', 'stop')
|
||||
|
||||
|
||||
# Klipper allows only one I2C request at a time per device: a second one
|
||||
# while the first waits for its answer raises KeyError ('i2c_response', oid)
|
||||
# and shuts Klipper down. The guard reads from a timer while G-code runs,
|
||||
# and bdpressure.py writes the probe mode at every homing move (seen: G28
|
||||
# during an armed guard), so all transfers of the sensor take this lock.
|
||||
# The guard puts it on the sensor object at connect; bdpressure and
|
||||
# bdpressure_check use sensor.i2c and so get it too.
|
||||
class LockedI2C:
|
||||
def __init__(self, i2c, mutex):
|
||||
self._i2c = i2c
|
||||
self._mutex = mutex
|
||||
|
||||
def i2c_read(self, *args, **kwargs):
|
||||
with self._mutex:
|
||||
return self._i2c.i2c_read(*args, **kwargs)
|
||||
|
||||
def i2c_write(self, *args, **kwargs):
|
||||
with self._mutex:
|
||||
return self._i2c.i2c_write(*args, **kwargs)
|
||||
|
||||
def i2c_write_wait_ack(self, *args, **kwargs):
|
||||
with self._mutex:
|
||||
return self._i2c.i2c_write_wait_ack(*args, **kwargs)
|
||||
|
||||
def i2c_transfer(self, *args, **kwargs):
|
||||
with self._mutex:
|
||||
return self._i2c.i2c_transfer(*args, **kwargs)
|
||||
|
||||
def __getattr__(self, name):
|
||||
return getattr(self._i2c, name)
|
||||
|
||||
|
||||
class BDPGuard:
|
||||
def __init__(self, config):
|
||||
self.printer = config.get_printer()
|
||||
@@ -76,7 +108,13 @@ class BDPGuard:
|
||||
|
||||
def _handle_connect(self):
|
||||
self.sensor = self.printer.lookup_object(self.sensor_name, None)
|
||||
self.i2c = getattr(self.sensor, 'i2c', None)
|
||||
i2c = getattr(self.sensor, 'i2c', None)
|
||||
if i2c is not None and not isinstance(i2c, LockedI2C):
|
||||
# Every user of the sensor (bdpressure, bdpressure_check, this
|
||||
# guard) now goes through one lock, see LockedI2C
|
||||
i2c = LockedI2C(i2c, self.reactor.mutex())
|
||||
self.sensor.i2c = i2c
|
||||
self.i2c = i2c
|
||||
|
||||
def _handle_shutdown(self):
|
||||
self._stop_timer()
|
||||
|
||||
Reference in new issue
Block a user