This is an automated email from the ASF dual-hosted git repository.

xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 159ef8105bb88215e88c3812bd19c96975cf2b75
Author: Felipe Moura <[email protected]>
AuthorDate: Sat Sep 19 17:58:14 2026 -0300

    sensors/lsm6ds3trc: reset the sensor before arming its interrupt
    
    lsm6ds3trc_register() attached the INT1 handler without ever putting the
    sensor into a known state, which made every reboot a coin toss.
    
    The LSM6DS3TR-C has its own supply and its own reset.  An MCU reset --
    watchdog, RTS pin, esptool, a plain "reboot" -- does not reset it, so it
    comes back still holding whatever the previous session configured: for
    this driver, INT1_CTRL.INT1_FTH still set and a FIFO still over its
    watermark, i.e. INT1 already asserted at registration time.
    
    With the (correct) ONHIGH level trigger, arming an already-active line
    storms immediately.  The board then wedges during bring-up with no
    console output and no crash dump -- it looked like a boot that stopped
    right after Wi-Fi init and never reached NSH.  That symptom cost a long
    detour: it was blamed in turn on a stuck I2C bus, on corrupted NVS/Wi-Fi
    calibration, and finally on a failing USB-serial adapter, because the one
    thing that reliably cleared it was unplugging the board -- which is
    simply the only way to power-cycle the *sensor*.
    
    SW_RESET (CTRL3_C bit 0) clears INT1_CTRL and FIFO_CTRL back to 0, which
    deasserts INT1.  It self-clears in ~50 us; poll for it rather than
    assume, and retry the write a few times, since the bus has been seen to
    return -EIO on the very first transaction after a cold boot.
    
    Carry on if the reset never takes.  An unreset sensor risks the storm
    this exists to prevent, but refusing to register leaves the application
    with no /dev/uorb/sensor_accel0 at all, which is fatal to it -- a single
    -EIO here took the whole collar down once.  Losing the sensor to guard
    against a maybe-storm is the wrong trade.
    
    Assisted-by: Claude:claude-opus-5
    Signed-off-by: Felipe Moura <[email protected]>
---
 drivers/sensors/lsm6ds3trc_uorb.c | 82 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 82 insertions(+)

diff --git a/drivers/sensors/lsm6ds3trc_uorb.c 
b/drivers/sensors/lsm6ds3trc_uorb.c
index 93703e8231e..2e0f9ad34d2 100644
--- a/drivers/sensors/lsm6ds3trc_uorb.c
+++ b/drivers/sensors/lsm6ds3trc_uorb.c
@@ -1630,6 +1630,88 @@ int lsm6ds3trc_register(FAR struct i2c_master_s *i2c, 
uint8_t addr,
       goto unreg_gyro;
     }
 
+  /* Put the sensor into its power-on register state before anything else
+   * touches it, and in particular before the interrupt is attached.
+   *
+   * The LSM6DS3TR-C has its own supply and its own reset: an MCU reset
+   * (watchdog, RTS pin, esptool, `reboot`) does not reset the sensor, so
+   * it comes up still holding whatever the previous session configured.
+   * For this driver that means INT1_CTRL.INT1_FTH still set and a FIFO
+   * still over its watermark -- i.e. INT1 asserted high, immediately, at
+   * registration time.
+   *
+   * INT1 is level-triggered (ONHIGH; see the comment in
+   * boards/xtensa/esp32s3/common/src/esp32s3_board_lsm6ds3trc.c for why
+   * edge triggering is wrong here).  A level-triggered line that is
+   * already active when esp_gpioirqenable() runs re-fires forever, and
+   * the board then wedges during bring-up with no console output and no
+   * crash dump -- observed as a boot that stops right after Wi-Fi init
+   * and never reaches NSH, recoverable only by physically removing power
+   * from the sensor.
+   *
+   * SW_RESET (CTRL3_C bit 0) clears INT1_CTRL and FIFO_CTRL back to 0,
+   * which deasserts INT1.  It self-clears in ~50us; poll rather than
+   * assume, and carry on if the sensor does not answer -- a sensor that
+   * cannot be reset is a problem for the caller to report, not a reason
+   * to arm an interrupt line we know may be stuck high.
+   */
+
+  {
+    uint8_t ctrl3_c;
+    int attempt;
+    int tries;
+    bool reset_done = false;
+
+    /* The I2C bus is not always ready the instant we get here -- a write
+     * at this point has been seen to fail with -EIO on a cold boot.  Give
+     * it a few attempts with a short pause between them.
+     */
+
+    for (attempt = 0; attempt < 3 && !reset_done; attempt++)
+      {
+        ctrl3_c = 0x01;                 /* SW_RESET */
+
+        err = lsm6ds3trc_write_bytes(priv, CTRL3_C, &ctrl3_c, 1);
+        if (err < 0)
+          {
+            snwarn("Software reset write failed (attempt %d): %d\n",
+                   attempt + 1, err);
+            nxsig_usleep(10000);
+            continue;
+          }
+
+        for (tries = 0; tries < 20; tries++)
+          {
+            nxsig_usleep(1000);
+
+            if (lsm6ds3trc_read_bytes(priv, CTRL3_C, &ctrl3_c, 1) >= 0 &&
+                (ctrl3_c & 0x01) == 0)
+              {
+                reset_done = true;
+                break;
+              }
+          }
+      }
+
+    /* Carry on even if it never took.  Not resetting the sensor risks the
+     * interrupt storm this reset exists to prevent (see the comment
+     * above), but that is a far better failure than refusing to register
+     * 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.
+     */
+
+    if (!reset_done)
+      {
+        snerr("Software reset did not complete; continuing unreset. "
+              "INT1 may already be asserted -- watch for an IRQ storm.\n");
+      }
+
+    err = OK;
+  }
+
   /* Write CTRL1_XL's FS_XL bits to match the software default above --
    * ODR is set later by activate(), but FSR needs to be right from the
    * first sample instead of only after an explicit SNIOC_SETFULLSCALE.

Reply via email to