Skip to content

Bug Report: IMU Initialization Error due to interrupted DFU mode / firmware upload #64

Description

@WickWub

Bug Report: Onboard LSM6DS3 IMU Fails to Initialize After Interrupted DFU Sessions on XIAO nRF52840 Sense (Qbead Hardware) — Resolved by Full Power Cycle

Summary

The onboard LSM6DS3(TR-C) IMU on two independent Qbead units (Seeed XIAO nRF52840 Sense) stopped initializing after a period of unstable DFU mode / firmware upload activity. LSM6DS3::begin() consistently returned a non-zero (failure) status code, and a direct WHO_AM_I register read (address 0x0F) returned 0x00 instead of a valid chip identifier, with accelerometer output flat at 0.00 on all axes. The issue was reproduced identically across two separate toolchains (PlatformIO and the official Arduino IDE + Seeeduino package) and two separate physical boards, which initially pointed toward a possible hardware defect. This conclusion was incorrect. A full battery drain followed by re-flashing the exact same, previously-failing firmware resolved the issue on both affected units. This confirms the root cause was some transient MCU/peripheral state corruption requiring a true power-off cycle to clear — not a hardware defect, library bug, or toolchain issue.

Environment

Component Detail
Board Seeed Studio XIAO nRF52840 Sense
Onboard sensor LSM6DS3 / LSM6DS3TR-C, expected I2C address 0x6A
Toolchain A PlatformIO on VS Code, platform Seeed-Studio/platform-seeedboards, board id seeed-xiao-afruitnrf52-nrf52840, framework arduino
Toolchain B Arduino IDE, board package Seeeduino:nrf52 v1.1.13, FQBN Seeeduino:nrf52:xiaonRF52840
Sensor library seeed-studio/Seeed Arduino LSM6DS3, tested at both 2.0.5 and 2.0.7
Firmware under test Qbead's own Qbead.h; IMU-reader example, Dynamical Decoupling simple example, minimal standalone I2C diagnostic sketches
Host system Windows, Lenovo Legion Pro 5
Units tested 2 physically separate, previously untouched XIAO nRF52840 Sense boards

Reproducibility

Consistently reproducible prior to the fix, across:

  • Board 1/2 + PlatformIO
  • Board 1/2 + Arduino IDE
  • Library version 2.0.5 and 2.0.7 (no behavioral difference)
  • Both the full Qbead firmware, inc. some of its examples, and minimal standalone diagnostic sketches

Consistently resolved on both boards after a full battery drain + re-power + re-flash of the same firmware that had previously failed (see Resolution).

Symptoms (Prior to Fix)

  • Qbead::begin() printed [ERROR]{IMU} IMU failed to initialize.
  • Standalone diagnostic sketch: myIMU.begin() returned 1 (non-zero = failure).
  • Direct WHO_AM_I register read (0x0F) returned 0x00, not a valid chip ID.
  • readFloatAccelX/Y/Z() returned a flat 0.00 on all axes continuously, unchanged by physical movement.
  • No I2C bus hang using the intended Wire object — the transaction completed cleanly but returned invalid/zeroed data.
  • NeoPixel driver and BLE advertising (Bluefruit) continued to initialize and run correctly; only the IMU path was affected.

Impact

  • Any Qbead feature depending on IMU data was non-functional: Bloch-sphere orientation rendering, tap detection, BLE-notified accelerometer/tap characteristics.
  • Confirmed to have worked correctly earlier in the same session, on one device, (LED tracked physical rotation) before regressing during a period of repeated bootloader entry/exit and USB instability. Thus rendering the device's interactivity dead.

Root Cause

Transient corruption of MCU or IMU peripheral state, caused by an unstable/interrupted upload session, that persisted across normal resets and firmware flashes and was only cleared by a genuine full power-off cycle.

Given the board's onboard battery and, to my knowledge, no method to manually instruct a full power-cycle meant that all reset attempts (single reset, double-tap-to-DFU-mode, re-flashing, even multi-minute unplug periods) never actually achieved a true cold restart, and therefore never had the chance to clear whatever internal state was left in a bad configuration.

A likely contributing sequence, based on the debugging timeline:

  • Repeated USB port enumeration and at least one interrupted/marginal DFU session (correlated with use of an unstable side-mounted USB-A port on the host laptop; see USB Port Note below) occurred around the time the IMU stopped initializing. In general many DFU-mode / reset button instructions and firmware upload attempts were attempted in a relatively short time period.
  • This is possibly consistent with some documented nRF52-series behavior: Nordic Semiconductor's errata documentation confirms that certain peripheral register states are not cleared by watchdog, CPU lockup, soft, or pin resets on this chip family. This goes a little far into the weeds of the hardware specifics, hence I did not verify this assertion extensively or used it to resolve the issue.
  • Only forcing a full discharge of the onboard battery (via sustained maximum-brightness LED load) achieved a true power-on reset, which resolved the issue on both independently-tested units upon the first re-flashing of the same firmware after the battery had drained (LED's gone off).

This rules out a broken hardware issue. Especially given the exact same behaviour occurred on two factory new Qbeads. This is further supported by the brief correct behaviour of the IMU tracking physical rotation after a serial monitor triggered the already flashed firmware on one of the devices. This was before any successful firmware upload was performed.

Resolution

  1. Force a full battery discharge: flash a minimal sketch that sets all NeoPixels to maximum brightness/full white and leaves them on continuously, and let the board run until the LEDs went dark on their own (battery depleted below operating voltage).
  2. Allow the board to rest, fully unpowered, for a period of time.
  3. Reconnect USB power and re-flash the exact same firmware that had previously failed (no code changes).
  4. IMU initialized successfully on both affected boards; accelerometer readings responded correctly to physical movement.

No firmware, library, or configuration changes were required — the fix was exclusively a full power cycle.

USB Port Note (Related Finding)

Earlier upload/connectivity instability (frequent COM port drops, PermissionError 13, semaphore timeouts) correlated with use of a side-mounted USB-A port on the host laptop (Lenovo Legion Pro 5). Lenovo's own published specifications confirm side and rear USB-A ports on this model line are wired as distinct ports, differing in USB generation/controller rather than being interchangeable. Switching to a rear USB port resolved the connectivity instability. This is the most likely trigger for the interrupted/marginal upload session that is suspected to have caused the transient IMU state corruption described above, though the exact causal mechanism remains unconfirmed at the register/peripheral level.

Debugging Steps Performed (Condensed)

  1. Resolved PlatformIO/Windows upload tooling issues (USB COM port instability, expected COM port reassignment after upload/reset).
  2. Observed regression to [ERROR]{IMU} IMU failed to initialize following a period of repeated bootloader entry/exit and USB instability, later correlated with an unstable side USB port.
  3. Built minimal standalone I2C diagnostic sketches to isolate the IMU from BLE/NeoPixel code.
  4. Ruled out a missing IMU power-enable gate (not relevant to this board variant).
  5. Read the WHO_AM_I register directly, obtaining 0x00.
  6. Tested library version sensitivity (2.0.5 vs 2.0.7, full cache clear) — no change.
  7. Cross-validated under the official Arduino IDE + Seeeduino board package, independent of PlatformIO — identical failure.
  8. Cross-validated on a second, independent, previously untouched board — identical failure.
  9. Attempted a full power-cycle via forced battery drain (maximum-brightness LED load).
  10. Re-flashed the same, previously-failing firmware after the drain-and-rest period — IMU initialized correctly on both boards.

Suggested Follow-Up

  • Potentially document this failure mode and its resolution for other Qbead users/maintainers in a Troubleshooting addition of the installation README. Since the underlying trigger (interrupted DFU session leaving peripheral state corrupted until a true power cycle) is plausible to occur for other users; it may present itself after interrupted DFU uploads due to different root causes.
  • Consider whether a firmware-level workaround exists. Such as an explicit peripheral reset sequence at boot to make the IMU initialization path resilient to this class of corruption without requiring a full battery drain.

Status

Resolved. Root cause: transient peripheral/MCU state corruption requiring a full power cycle to clear, likely triggered by an unstable/interrupted DFU upload session. Fixed via full battery discharge and reflash, with no code changes, on both affected units.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions