From c4c9eab46f294aac82bb628396a2c1bfa4cd80ee Mon Sep 17 00:00:00 2001 From: Felipe Moura Date: Sat, 19 Sep 2026 17:58:44 -0300 Subject: [PATCH] sensors/lsm6ds3trc: recover from a failed FIFO drain instead of wedging A single failed burst read of FIFO_DATA_OUT was enough to take the board down. The drain path gave up on error, unlocked and returned, leaving the FIFO above its watermark. INT1 is level triggered on exactly that condition, so the line stayed asserted, the worker was re-entered the instant the IRQ was re-enabled, failed again, and that hot loop starved every other task until the board wedged -- console cut off mid-line, no crash dump. Observed killing a board within seconds of the first failure. Fix: if the read fails, empty the FIFO through Bypass and restore the previous mode bits, which deasserts INT1. That costs one batch of samples and acquisition resumes on the next watermark. Restoring the saved bits rather than recomputing them preserves the FIFO-only ODR set by fifo_configure(). Losing a batch is a far better outcome than losing the board. The underlying cause of these timeouts on esp32s3 was light sleep cutting the transfer in half; that is fixed separately in esp32s3_i2c.c. This commit is the driver recovering gracefully from a failed read whatever its cause, which it was not before. Assisted-by: Claude:claude-opus-5 Signed-off-by: Felipe Moura --- drivers/sensors/lsm6ds3trc_uorb.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/drivers/sensors/lsm6ds3trc_uorb.c b/drivers/sensors/lsm6ds3trc_uorb.c index 322bda97a4f..f61c658a6b1 100644 --- a/drivers/sensors/lsm6ds3trc_uorb.c +++ b/drivers/sensors/lsm6ds3trc_uorb.c @@ -933,8 +933,23 @@ static void lsm6ds3trc_fifo_worker_body(FAR struct lsm6ds3trc_dev_s *dev) nwords * sizeof(int16_t)); if (err < 0) { - nxmutex_unlock(&dev->devlock); + uint8_t ctrl5; + snerr("ERROR: Failed to read FIFO data: %d\n", err); + + /* Recover instead of wedging: a FIFO left above watermark holds + * level-triggered INT1 asserted, re-entering this worker forever. + * Emptying it through Bypass costs one batch but deasserts the line; + * restore the previous mode bits to keep fifo_configure()'s ODR. + */ + + if (lsm6ds3trc_read_bytes(dev, FIFO_CTRL5, &ctrl5, 1) >= 0) + { + lsm6ds3trc_set_bits(dev, FIFO_CTRL5, FIFO_MODE_BYPASS, 0x07); + lsm6ds3trc_set_bits(dev, FIFO_CTRL5, ctrl5 & 0x07, 0x07); + } + + nxmutex_unlock(&dev->devlock); return; } @@ -1726,8 +1741,8 @@ int lsm6ds3trc_register(FAR struct i2c_master_s *i2c, uint8_t addr, * the device at all: an unregistered sensor leaves the application * with no /dev/uorb/sensor_accel0 to open, which is fatal to it. * Losing the whole sensor to protect against a maybe-storm is the - * wrong trade -- and it is exactly what happened on 2026-09-19, when - * a single -EIO here took the collar down completely. + * wrong trade -- a single -EIO here has taken a board down completely + * before. */ if (!reset_done)