Skip to content

sensor: Add ICM42686 Driver Support #92579

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

ubieda
Copy link
Member

@ubieda ubieda commented Jul 3, 2025

Description

This PR adds support for ICM42686 driver, by extending and refactoring existing ICM42688 driver.
The new variant contains feature parity with the original driver:

  • Fetch and Get (Sensor Model V1)
  • Sensor Model V2:
    • Read/Decode
    • Streaming mode
  • Build Time Configuration thorugh device-tree properties
  • Run Time Configuration through attribute set/get API.

Testing

This was tested on VMU RT1170, which contains both ICM42688 and ICM42686, running the sensor-shell sample to set up and obtain sensor readings:

  • Build command:
west build -b vmu_rt1170/mimxrt1176/cm7 samples/sensor/sensor_shell
  • Sensor Read/Decode:
uart:~$ sensor get icm42688p0@0 
channel type=0(accel_x) index=0 shift=8 num_samples=1 value=19162868474ns (-0.004787)
channel type=1(accel_y) index=0 shift=8 num_samples=1 value=19162868474ns (0.052671)
channel type=2(accel_z) index=0 shift=8 num_samples=1 value=19162868474ns (9.916782)
channel type=3(accel_xyz) index=0 shift=8 num_samples=1 value=19162868474ns, (-0.004787, 0.052671, 9.916782)
channel type=4(gyro_x) index=0 shift=6 num_samples=1 value=19162868474ns (-0.004255)
channel type=5(gyro_y) index=0 shift=6 num_samples=1 value=19162868474ns (-0.026604)
channel type=6(gyro_z) index=0 shift=6 num_samples=1 value=19162868474ns (0.012769)
channel type=7(gyro_xyz) index=0 shift=6 num_samples=1 value=19162868474ns, (-0.004255, -0.026604, 0.012769)
channel type=12(die_temp) index=0 shift=9 num_samples=1 value=19162868474ns (31.951991)
uart:~$ sensor get icm
  icm42688p0@0  icm42686p0@0  
uart:~$ sensor get icm42686p0@0 
channel type=0(accel_x) index=0 shift=8 num_samples=1 value=3300985903ns (0.052671)
channel type=1(accel_y) index=0 shift=8 num_samples=1 value=3300985903ns (0.076613)
channel type=2(accel_z) index=0 shift=8 num_samples=1 value=3300985903ns (-9.720457)
channel type=3(accel_xyz) index=0 shift=8 num_samples=1 value=3300985903ns, (0.052671, 0.076613, -9.720457)
channel type=4(gyro_x) index=0 shift=6 num_samples=1 value=3300985903ns (0.000000)
channel type=5(gyro_y) index=0 shift=6 num_samples=1 value=3300985903ns (-0.006384)
channel type=6(gyro_z) index=0 shift=6 num_samples=1 value=3300985903ns (0.004255)
channel type=7(gyro_xyz) index=0 shift=6 num_samples=1 value=3300985903ns, (0.000000, -0.006384, 0.004255)
channel type=12(die_temp) index=0 shift=9 num_samples=1 value=3300985903ns (35.084540)
  • Streaming Mode:
uart:~$ sensor attr_set icm42686p0@0 accel_xyz sampling_frequency 25
icm42686p0@0 channel=accel_xyz, attr=sampling_frequency set to value=25
[00:03:17.412,000] <inf> ICM4268X_LL: FIFO ENABLED
uart:~$ sensor attr_set icm42686p0@0 gyro_xyz sampling_frequency 25
icm42686p0@0 channel=gyro_xyz, attr=sampling_frequency set to value=25
[00:03:19.423,000] <inf> ICM4268X_LL: FIFO ENABLED
uart:~$ sensor attr_set icm42686p0@0 all batch_dur 10000
icm42686p0@0 channel=all, attr=batch_dur set to value=10000
[00:03:21.782,000] <inf> ICM4268X_LL: FIFO ENABLED
uart:~$ sensor attr_set icm42686p0@0 all batch_dur 10000
uart:~$ sensor stream icm
  icm42688p0@0  icm42686p0@0
uart:~$ sensor stream icm42686p0@0 on fifo_wm incl
Disabling existing stream
Enabling stream...
Trigger (1 / data_ready) detected
Trigger (10 / fifo_wm) detected
Trigger (11 / fifo_full) detected
channel type=0(accel_x) index=0 shift=9 num_samples=100 value=2940457166ns (0.081131)
channel type=1(accel_y) index=0 shift=9 num_samples=100 value=2940457166ns (0.081131)
channel type=2(accel_z) index=0 shift=9 num_samples=100 value=2940457166ns (0.081131)
channel type=3(accel_xyz) index=0 shift=9 num_samples=100 value=2940457166ns, (0.081131, 0.046600, -9.702820)
channel type=4(gyro_x) index=0 shift=7 num_samples=100 value=2940457166ns (-0.005792)
channel type=5(gyro_y) index=0 shift=7 num_samples=100 value=2940457166ns (-0.005792)
channel type=6(gyro_z) index=0 shift=7 num_samples=100 value=2940457166ns (-0.005792)
channel type=7(gyro_xyz) index=0 shift=7 num_samples=100 value=2940457166ns, (-0.005792, 0.000636, 0.004793)
channel type=12(die_temp) index=0 shift=9 num_samples=100 value=2940457166ns (35.059555)
Trigger (1 / data_ready) detected
Trigger (10 / fifo_wm) detected
channel type=0(accel_x) index=0 shift=9 num_samples=25 value=2430948229ns (0.082568)
channel type=1(accel_y) index=0 shift=9 num_samples=25 value=2430948229ns (0.082568)
channel type=2(accel_z) index=0 shift=9 num_samples=25 value=2430948229ns (0.082568)
channel type=3(accel_xyz) index=0 shift=9 num_samples=25 value=2430948229ns, (0.082568, 0.047605, -9.702461)
channel type=4(gyro_x) index=0 shift=7 num_samples=25 value=2430948229ns (-0.005712)
channel type=5(gyro_y) index=0 shift=7 num_samples=25 value=2430948229ns (-0.005712)
channel type=6(gyro_z) index=0 shift=7 num_samples=25 value=2430948229ns (-0.005712)
channel type=7(gyro_xyz) index=0 shift=7 num_samples=25 value=2430948229ns, (-0.005712, 0.000575, 0.004859)
channel type=12(die_temp) index=0 shift=9 num_samples=25 value=2430948229ns (35.067028)
Trigger (1 / data_ready) detected
Trigger (10 / fifo_wm) detected
channel type=0(accel_x) index=0 shift=9 num_samples=25 value=3421436652ns (0.083047)
channel type=1(accel_y) index=0 shift=9 num_samples=25 value=3421436652ns (0.083047)
channel type=2(accel_z) index=0 shift=9 num_samples=25 value=3421436652ns (0.083047)
channel type=3(accel_xyz) index=0 shift=9 num_samples=25 value=3421436652ns, (0.083047, 0.045403, -9.703323)
channel type=4(gyro_x) index=0 shift=7 num_samples=25 value=3421436652ns (-0.005541)
channel type=5(gyro_y) index=0 shift=7 num_samples=25 value=3421436652ns (-0.005541)
channel type=6(gyro_z) index=0 shift=7 num_samples=25 value=3421436652ns (-0.005541)
channel type=7(gyro_xyz) index=0 shift=7 num_samples=25 value=3421436652ns, (-0.005541, 0.000500, 0.004923)
channel type=12(die_temp) index=0 shift=9 num_samples=25 value=3421436652ns (35.065820)
Trigger (1 / data_ready) detected
Trigger (10 / fifo_wm) detected
channel type=0(accel_x) index=0 shift=9 num_samples=25 value=4411926607ns (0.079407)
channel type=1(accel_y) index=0 shift=9 num_samples=25 value=4411926607ns (0.079407)
channel type=2(accel_z) index=0 shift=9 num_samples=25 value=4411926607ns (0.079407)
channel type=3(accel_xyz) index=0 shift=9 num_samples=25 value=4411926607ns, (0.079407, 0.047989, -9.701982)
channel type=4(gyro_x) index=0 shift=7 num_samples=25 value=4411926607ns (-0.005882)
channel type=5(gyro_y) index=0 shift=7 num_samples=25 value=4411926607ns (-0.005882)
channel type=6(gyro_z) index=0 shift=7 num_samples=25 value=4411926607ns (-0.005882)
channel type=7(gyro_xyz) index=0 shift=7 num_samples=25 value=4411926607ns, (-0.005882, 0.000564, 0.004699)
channel type=12(die_temp) index=0 shift=9 num_samples=25 value=4411926607ns (35.072161)
Trigger (1 / data_ready) detected
Trigger (10 / fifo_wm) detected
channel type=0(accel_x) index=0 shift=9 num_samples=25 value=5402416407ns (0.080269)
channel type=1(accel_y) index=0 shift=9 num_samples=25 value=5402416407ns (0.080269)
channel type=2(accel_z) index=0 shift=9 num_samples=25 value=5402416407ns (0.080269)
channel type=3(accel_xyz) index=0 shift=9 num_samples=25 value=5402416407ns, (0.080269, 0.046935, -9.703132)
channel type=4(gyro_x) index=0 shift=7 num_samples=25 value=5402416407ns (-0.005978)
channel type=5(gyro_y) index=0 shift=7 num_samples=25 value=5402416407ns (-0.005978)
channel type=6(gyro_z) index=0 shift=7 num_samples=25 value=5402416407ns (-0.005978)
channel type=7(gyro_xyz) index=0 shift=7 num_samples=25 value=5402416407ns, (-0.005978, 0.000660, 0.004849)
channel type=12(die_temp) index=0 shift=9 num_samples=25 value=5402416407ns (35.067934)
Trigger (1 / data_ready) detected
Trigger (10 / fifo_wm) detected
channel type=0(accel_x) index=0 shift=9 num_samples=25 value=6392905612ns (0.079886)
channel type=1(accel_y) index=0 shift=9 num_samples=25 value=6392905612ns (0.079886)
channel type=2(accel_z) index=0 shift=9 num_samples=25 value=6392905612ns (0.079886)
channel type=3(accel_xyz) index=0 shift=9 num_samples=25 value=6392905612ns, (0.079886, 0.044349, -9.701791)
channel type=4(gyro_x) index=0 shift=7 num_samples=25 value=6392905612ns (-0.005850)
channel type=5(gyro_y) index=0 shift=7 num_samples=25 value=6392905612ns (-0.005850)
channel type=6(gyro_z) index=0 shift=7 num_samples=25 value=6392905612ns (-0.005850)
channel type=7(gyro_xyz) index=0 shift=7 num_samples=25 value=6392905612ns, (-0.005850, 0.000532, 0.004955)
channel type=12(die_temp) index=0 shift=9 num_samples=25 value=6392905612ns (35.068537)
uart:~$ sensor stream icm42686p0@0 off
Disabling existing stream
uart:~$ 

@ubieda ubieda force-pushed the feature/icm42686-driver-support branch 5 times, most recently from 0f64e78 to 7477da4 Compare July 3, 2025 19:16
@ubieda ubieda added this to the v4.3.0 milestone Jul 3, 2025
@ubieda
Copy link
Member Author

ubieda commented Jul 3, 2025

Looks like the issues flagged by SonarQube are due to moving existing in-tree files. I wonder if we're good with addressing them on follow-up PRs instead of blocking this one.

bperseghetti
bperseghetti previously approved these changes Jul 4, 2025
Copy link
Member

@bperseghetti bperseghetti left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great addition! I also tested this on real hardware, both targets (42688 and 42686) work perfectly.

teburd
teburd previously approved these changes Jul 4, 2025
PetervdPerk-NXP
PetervdPerk-NXP previously approved these changes Jul 7, 2025
afontaine-invn
afontaine-invn previously approved these changes Jul 8, 2025
ubieda added 6 commits July 23, 2025 14:06
As a first step to enable the similar variants (e.g: ICM42686),
refactor common functionality into icm4268x files. As a result,
applications using the icm42688 will need to have both compatible
properties: "invensense,icm42688" and "invensense,icm4268x" defined.
In-tree boards have been modified to comply with this pattern.

This patch does not contain functional changes. The driver should
work the same as before.

Signed-off-by: Luis Ubieda <[email protected]>
Addressing low-hanging fruits.

Put in a separate commit in order to make it easier to keep track of
changes.

Signed-off-by: Luis Ubieda <[email protected]>
Now this driver supports both ICM42688 and ICM42686.
Tested with read-decode as well as streaming mode.

Signed-off-by: Luis Ubieda <[email protected]>
Additionally, remove overlay from sensor-shell sample, which is
redundant.

Signed-off-by: Luis Ubieda <[email protected]>
For build-time validation.

Signed-off-by: Luis Ubieda <[email protected]>
Users now requiring to define both dt compatibles: both icm4268x and
icm42688 to work.

Signed-off-by: Luis Ubieda <[email protected]>
@ubieda ubieda force-pushed the feature/icm42686-driver-support branch from 7477da4 to f135b0c Compare July 23, 2025 18:10
Copy link

@ubieda
Copy link
Member Author

ubieda commented Jul 23, 2025

I just rebased to resolve the conflicts and move the migration guide to 4.3.0.

WRT SonarQube issues: I gave another pass at the issues pointed out, and they're now reduced to two types:

  1. Refactor this function to reduce its Cognitive Complexity, which are flagged due to the renaming of existing driver and are part of the technical debt the driver had before I touched it.
  2. cast from 'const struct device *' to 'void *' drops const qualifier, which can be addressed here (and other driver instances) once rtio: More useful callback OPs #93227 lands.

After this round, I've repeated the test-verification listed in the PR description and I've got the same results.

I'll stick around to see all CI checks pass, then I'll stand by for another round of reviews.

zephyr_library_sources_ifdef(CONFIG_SENSOR_ASYNC_API icm4268x_rtio.c)
zephyr_library_sources_ifdef(CONFIG_ICM4268X_DECODER icm4268x_decoder.c)
zephyr_library_sources_ifdef(CONFIG_ICM4268X_STREAM icm4268x_rtio_stream.c)
zephyr_library_sources_ifdef(CONFIG_ICM4268X_TRIGGER icm4268x_trigger.c)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Of all the APIs the Sensor API has currently, I believe the trigger API is the least usable among them and conflicts the most with the stream API. I'm wondering if perhaps this API is one we really should aim to deprecate.

Supporting the polling read and stream is fairly easy I think. Supporting trigger and stream seems conflict ridden.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: Samples Samples area: Sensors Sensors platform: NXP Robotics NXP Robotics Module Platform Products Release Notes To be mentioned in the release notes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants