drivers/sensors: add LSM6DS3TR-C uORB driver for the XIAO ESP32-S3 - #19997
Merged
Conversation
FelipeMdeO
requested review from
acassis,
linguini1 and
raiden00pl
as code owners
August 28, 2026 17:41
FelipeMdeO
force-pushed
the
feature/lsm6ds3trc-driver
branch
from
August 28, 2026 18:26
ad640a0 to
3bd75e6
Compare
xiaoxiang781216
previously approved these changes
Aug 28, 2026
No driver exists for this exact chip. lsm6dsl.c is the closest register-compatible match but is the deprecated legacy char-device style; lsm6dso32_uorb.c is the closest uORB-style match but is for a different chip variant. The new driver borrows lsm6dso32_uorb.c's structure (dual sensor_lowerhalf_s, raw I2C_TRANSFER helpers) and lsm6dsl.h's register map -- fixing a bug in the header it was ported from along the way: LSM6DSL_FIFO_CTRL2_SHIFT is defined as 255 instead of 0. Delivery mode is chosen the same way mpu6050 does: kthread polling by default, or interrupt-driven if the board supplies attach(). Unlike the earlier lsm6dso32-style design this went through first -- one INT pin and one activate()/interrupt path per sub-sensor -- the shipped version uses a single shared INT pin for both, mirroring mpu6050's own one-handler-one-worker design (apache#19601) instead. The two-independent- paths version worked for accel alone but was intermittently broken for gyro: activate() sometimes never actually turned CTRL2_G on even though the interrupt-enable bit was written correctly, and other times the whole console hung -- a real race, never conclusively root-caused on a serial console with no JTAG available. The LSM6DS3TR-C supports OR'ing both DRDY_XL and DRDY_G onto one pin via independent enable bits in that pin's INTn_CTRL register, so there was no need for two paths in the first place: one ISR times the burst, one HPWORK worker reads OUT_TEMP_L..OUTZ_H_A (14 contiguous bytes covering temp, gyro and accel in one I2C transaction) and pushes whichever topic(s) are currently subscribed. activate() now just flips each sub-sensor's own bit in the shared register instead of running its own attach. On the XIAO ESP32-S3 with Seeed's IMU Breakout Board, INT1/INT2 route to GPIO3/GPIO4 (confirmed from the breakout board's schematic, not guessed). Only INT1/GPIO3 is wired up, since one pin is now enough; GPIO4/INT2 is documented as available but unused. Also: CTRL1_XL's FS_XL bits were never actually written to match the driver's own software default (4g) -- registration set the in-memory value but the chip stayed at its 2g reset default until a caller issued an explicit SNIOC_SETFULLSCALE. register() now writes it. Validated on the bench, both modes, reproduced across multiple fresh reboots: WHO_AM_I reads 0x6a, sensor_accel0/sensor_gyro0 stream continuously. Interrupt mode delivers ~300 samples of each per 6s window with shared timestamps down to the microsecond between the two topics per event, confirming both come from the same burst read. Assisted-by: Claude <noreply@anthropic.com> Signed-off-by: Felipe Moura <moura.fmo@gmail.com>
FelipeMdeO
force-pushed
the
feature/lsm6ds3trc-driver
branch
from
August 28, 2026 19:21
3bd75e6 to
4df02c9
Compare
acassis
requested changes
Aug 28, 2026
acassis
left a comment
Contributor
There was a problem hiding this comment.
@FelipeMdeO please add this new driver to the Documentation page: https://nuttx.apache.org/docs/latest/components/drivers/special/sensors/sensors_uorb.html
FelipeMdeO
force-pushed
the
feature/lsm6ds3trc-driver
branch
from
August 28, 2026 19:36
1595736 to
6812081
Compare
Adds a dedicated page (matching the lsm6dso32 one, the closest register-compatible driver already documented) instead of a plain list entry: chip description, registration examples for both polling and interrupt-driven mode -- including the single-shared-INT-pin config_s/attach() shape this driver actually uses, unlike sensors that need one interrupt pin per sub-sensor -- and the two custom ioctls (SNIOC_WHO_AM_I, SNIOC_SETFULLSCALE) with their argument units. Requested in review on this PR. Signed-off-by: Felipe Moura <moura.fmo@gmail.com>
FelipeMdeO
force-pushed
the
feature/lsm6ds3trc-driver
branch
from
August 28, 2026 19:58
6812081 to
384afb5
Compare
Contributor
Author
|
Documentation added |
xiaoxiang781216
approved these changes
Aug 29, 2026
acassis
approved these changes
Aug 29, 2026
FelipeMdeO
added a commit
to FelipeMdeO/nuttx
that referenced
this pull request
Aug 29, 2026
…bringup.c Merging master (which now carries the LSM6DS3TR-C driver, PR apache#19997) into this branch left the CONFIG_MMCSD_SPI block's closing brace missing and a trailing-whitespace-only line behind, breaking the build. Restore the missing "}" and drop the stray whitespace. Assisted-by: Claude <noreply@anthropic.com> Signed-off-by: Felipe Moura <mouraf@fiteclabs.org.br>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
No driver exists for the LSM6DS3TR-C. lsm6dsl.c is the closest
register-compatible match (same WHO_AM_I, same CTRL1_XL/CTRL2_G layout)
but is the deprecated legacy char-device style; lsm6dso32_uorb.c is the
closest uORB-style match but is for a different chip variant. The new
driver borrows lsm6dso32_uorb.c's structure (dual sensor_lowerhalf_s,
raw I2C_TRANSFER helpers) and lsm6dsl.h's register map -- fixing a bug
in the header it was ported from along the way: LSM6DSL_FIFO_CTRL2_SHIFT
is defined as 255 instead of 0.
Delivery mode is chosen the same way mpu6050 does: kthread polling by
default, or interrupt-driven if the board supplies attach().
On the XIAO ESP32-S3 with Seeed's IMU Breakout Board, INT1/INT2 route to
GPIO3/GPIO4 (confirmed from the breakout board's schematic, not guessed).
Only INT1/GPIO3 is wired up, since one pin is now enough; GPIO4/INT2 is
documented as available but unused.
Also: CTRL1_XL's FS_XL bits were never actually written to match the
driver's own software default (4g) -- registration set the in-memory
value but the chip stayed at its 2g reset default until a caller issued
an explicit SNIOC_SETFULLSCALE. register() now writes it.
Impact
New optional driver (CONFIG_SENSORS_LSM6DS3TRC, default n), no impact
on boards that don't enable it.
Testing
Host: Ubuntu 24.04.4 LTS. xtensa-esp-elf-gcc (crosstool-NG
esp-14.2.0_20241119) 14.2.0. checkpatch.sh (style + -m commit message)
clean.
Compiles clean for the XIAO ESP32-S3 target, rebased onto current
master with no conflicts.
On hardware -- Seeed XIAO ESP32-S3 Sense + IMU Breakout Board
(LSM6DS3TR-C @ 0x6A, I2C0 SDA=GPIO5/SCL=GPIO6, INT1=GPIO3), native USB
Serial/JTAG console:
i2c dev 0 0x7f finds the IMU at 0x6a and the board's OLED at 0x3c,
matching the breakout board schematic.
i2c get -a 0x6a -r 0x0f reads WHO_AM_I = 0x6a.
Polling mode: sensor_accel0/sensor_gyro0 stream continuously for
minutes with no read errors, reproduced across multiple reboots.
Interrupt mode: reproduced across multiple fresh reboots, ~300 samples
of each topic per 6s window (matching the configured 52 Hz ODR), with
shared timestamps down to the microsecond between the two topics
per event -- confirming both come from the same burst read.
Console results: