Compare commits

...

3 Commits

Author SHA1 Message Date
Huang Qi
3a6865aef5 drivers/sensors: Add QST QMI8658 6-axis IMU sensor support
Some checks failed
Build Documentation / build-html (push) Has been cancelled
Add complete driver support for the QST QMI8658 6-axis IMU sensor featuring
3-axis accelerometer and 3-axis gyroscope with I2C interface and uORB
integration.

Key features implemented:
* Full I2C communication with configurable frequency (default 400kHz)
* Multiple accelerometer ranges (±2g, ±4g, ±8g, ±16g) and ODR settings
* Multiple gyroscope ranges (±16 to ±1024 dps) with high ODR support
* Low-pass filter configuration for both sensors
* Temperature sensing with 16-bit resolution
* Self-test capability for both accelerometer and gyroscope
* Calibration-on-demand support with offset registers
* FIFO buffer management (framework ready)
* Interrupt-driven and polling mode support
* Complete uORB integration with sensor_accel and sensor_gyro topics

Driver components added:
* Core driver implementation (qmi8658_uorb.c) with register operations
* Header file with register definitions and scale factors (qmi8658.h)
* Kconfig options for driver configuration and polling mode
* Build system integration (CMakeLists.txt, Make.defs)
* Comprehensive documentation with API reference and usage examples

The driver follows NuttX sensor framework conventions and provides
robust error handling, mutex protection, and comprehensive debugging
support through CONFIG_DEBUG_SENSORS.

Signed-off-by: Huang Qi <huangqi3@xiaomi.com>
2025-11-30 09:44:43 -03:00
fangxinyong
31b5ef357c libm/newlib: Include fenv sources for all ARCHs and extend x86 includes
newlib/libm/fenv/*.c are the non-functional implementation that should
be overridden by an architecture specific implementation in newlib/libm/machine/ARCH.

Make the architecture check for including shared x86 sys headers for x86 and x86_64.

Signed-off-by: fangxinyong <fangxinyong@xiaomi.com>
2025-11-30 20:43:58 +08:00
fangxinyong
d956699f75 libm/newlib: Add duplicate filename filtering for source lists
Implement filename-based filtering to exclude duplicate files
from source lists, ensuring ARCH-specific files (ARCH_CSRCS)
take precedence over files in common or other dirs

Signed-off-by: fangxinyong <fangxinyong@xiaomi.com>
2025-11-30 20:43:58 +08:00
10 changed files with 2180 additions and 7 deletions

View File

@@ -30,6 +30,7 @@ general interface.
sensors/mcp9600.rst
sensors/mpl115a.rst
sensors/nau7802.rst
sensors/qmi8658.rst
sensors/sht4x.rst
sensors/lsm6dso32.rst
sensors/lis2mdl.rst

View File

@@ -0,0 +1,232 @@
=======
QMI8658
=======
The QMI8658 is a high-performance 6-axis IMU sensor by QST featuring a 3-axis
accelerometer and 3-axis gyroscope. It supports both I2C and SPI interfaces,
although this driver currently supports I2C communication only.
This driver uses the :doc:`uorb
</components/drivers/special/sensors/sensors_uorb>` interface. It supports the
self-test capability for both the accelerometer and gyroscope.
The driver supports comprehensive features including multiple full-scale ranges,
configurable ODR settings, low-pass filters, FIFO buffer management, temperature
sensing, and device calibration.
.. note::
The QMI8658 is a feature-rich sensor with advanced capabilities like
tap detection, motion detection, and various low-power modes. This driver
implements the core functionality for accelerometer and gyroscope data
acquisition with room for future feature extensions.
Application Programming Interface
=================================
.. code-block:: c
#include <nuttx/sensors/qmi8658.h>
The QMI8658 driver provides one registration function:
- **uORB Interface**: ``qmi8658_uorb_register()``
Registration
------------
The uORB interface registers the driver and creates separate uORB topics for
accelerometer and gyroscope data under ``/dev/uorb/``: ``sensor_accel<n>`` and
``sensor_gyro<n>``, where ``n`` is the device number.
.. code-block:: c
/* Example uORB registration */
ret = qmi8658_uorb_register(0, i2c_bus, QMI8658_I2C_ADDR_DEFAULT);
if (ret < 0)
{
syslog(LOG_ERR, "Couldn't register QMI8658 uORB: %d\n", ret);
return ret;
}
The uORB interface registers the driver and creates separate uORB topics for
accelerometer and gyroscope data under ``/dev/uorb/``: ``sensor_accel<n>`` and
``sensor_gyro<n>``, where ``n`` is the device number.
.. code-block:: c
/* Example uORB registration */
ret = qmi8658_uorb_register(0, i2c_bus, QMI8658_I2C_ADDR_DEFAULT);
if (ret < 0)
{
syslog(LOG_ERR, "Couldn't register QMI8658 uORB: %d\n", ret);
return ret;
}
Configuration Options
=====================
The QMI8658 driver supports several Kconfig options:
* ``CONFIG_SENSORS_QMI8658``: Enable QMI8658 driver support (requires UORB)
* ``CONFIG_SENSORS_QMI8658_POLL``: Enable polling mode with configurable interval
* ``CONFIG_SENSORS_QMI8658_POLL_INTERVAL``: Set polling interval (default 1s)
* ``CONFIG_QMI8658_I2C_FREQUENCY``: Set I2C communication frequency (default 400kHz)
Supported Features
==================
Accelerometer
-------------
* **Full-Scale Ranges**: ±2g, ±4g, ±8g, ±16g
* **Output Data Rates**: 1000Hz, 500Hz, 250Hz, 125Hz, 62.5Hz, 31.25Hz
* **Low-Power ODR**: 128Hz, 21Hz, 11Hz, 3Hz
* **Low-Pass Filters**: 4 different modes + OFF
Gyroscope
---------
* **Full-Scale Ranges**: ±16, ±32, ±64, ±128, ±256, ±512, ±1024 dps
* **Output Data Rates**: 7174.4Hz, 3587.2Hz, 1793.6Hz, 896.8Hz, 448.4Hz, 224.2Hz, 112.1Hz, 56.05Hz, 28.025Hz
* **Low-Pass Filters**: 4 different modes + OFF
Additional Features
-----------------==
* **Temperature Sensor**: 16-bit temperature data with 256 LSB/°C scale factor
* **FIFO Buffer**: Configurable FIFO with watermark and interrupt support
* **Sampling Modes**: Synchronous and asynchronous sampling
* **Interrupt Support**: Data ready, FIFO watermark, motion detection
* **Self-Test**: Built-in self-test capability for both sensors
* **Calibration**: On-demand calibration support
IOCTL Commands
==============
uORB IOCTLs
-----------
* ``SNIOC_SETFULLSCALE``: Set full-scale range (argument in g for accel, dps for gyro)
* ``SNIOC_SET_CALIBVALUE``: Set calibration offsets
* ``SNIOC_SELFTEST``: Perform sensor self-test
* ``SNIOC_WHO_AM_I``: Read device ID (should return 0x05)
Scale Factors
=============
The driver provides predefined scale factors for converting raw sensor data
to physical units:
Accelerometer Scale Factors (LSB/g):
.. code-block:: c
#define QMI8658_ACC_SCALE_2G (16384.0f)
#define QMI8658_ACC_SCALE_4G (8192.0f)
#define QMI8658_ACC_SCALE_8G (4096.0f)
#define QMI8658_ACC_SCALE_16G (2048.0f)
Gyroscope Scale Factors (LSB/dps):
.. code-block:: c
#define QMI8658_GYRO_SCALE_16DPS (2048.0f)
#define QMI8658_GYRO_SCALE_32DPS (1024.0f)
#define QMI8658_GYRO_SCALE_64DPS (512.0f)
#define QMI8658_GYRO_SCALE_128DPS (256.0f)
#define QMI8658_GYRO_SCALE_256DPS (128.0f)
#define QMI8658_GYRO_SCALE_512DPS (64.0f)
#define QMI8658_GYRO_SCALE_1024DPS (32.0f)
Temperature Scale Factor (LSB/°C):
.. code-block:: c
#define QMI8658_TEMP_SCALE (256.0f)
Data Conversion
===============
To convert raw sensor data to physical units:
.. code-block:: c
/* Convert accelerometer raw data to g */
float accel_x_g = (float)raw_accel_x / QMI8658_ACC_SCALE_8G;
float accel_y_g = (float)raw_accel_y / QMI8658_ACC_SCALE_8G;
float accel_z_g = (float)raw_accel_z / QMI8658_ACC_SCALE_8G;
/* Convert gyroscope raw data to dps */
float gyro_x_dps = (float)raw_gyro_x / QMI8658_GYRO_SCALE_512DPS;
float gyro_y_dps = (float)raw_gyro_y / QMI8658_GYRO_SCALE_512DPS;
float gyro_z_dps = (float)raw_gyro_z / QMI8658_GYRO_SCALE_512DPS;
/* Convert temperature raw data to °C */
float temp_c = (float)raw_temp / QMI8658_TEMP_SCALE;
Debugging and Testing
=====================
To debug the QMI8658 device, you can:
1. **Enable Debug Output**: Set ``CONFIG_DEBUG_SENSORS`` and ``CONFIG_DEBUG_INFO``
2. **Use uORB Listener**: Include ``uorb_listener`` application to monitor sensor data
Performance Considerations
==========================
* **I2C Frequency**: Default 400kHz, configurable via ``CONFIG_QMI8658_I2C_FREQUENCY``
* **Polling Overhead**: Use interrupt-driven mode when possible for better efficiency
* **FIFO Usage**: Enable FIFO to reduce I2C traffic and CPU overhead
* **Power Management**: Utilize low-power ODR settings for battery-powered applications
Limitations
===========
* Currently supports I2C interface only (SPI support can be added)
* Advanced features like tap detection and motion detection not yet implemented
* FIFO interrupt handling not fully implemented
* Some low-power modes require additional configuration
Hardware Connections
====================
I2C Interface
--------------
* **VDD**: Power supply (1.71V to 3.6V)
* **GND**: Ground
* **SDA/SDI**: I2C Serial Data
* **SCL/SCLK**: I2C Serial Clock
* **CS**: Chip Select (connect to VDD for I2C mode)
* **INT1/INT2**: Interrupt pins (optional)
Typical I2C addresses:
* **Primary**: 0x6B
* **Secondary**: 0x6D (when SDO/SA0 pin is high)
.. note::
Ensure proper pull-up resistors on SDA and SCL lines (typically 4.7kΩ for 3.3V).
Troubleshooting
===============
**Device Not Responding**
* Check I2C address and connections
* Verify power supply voltage
* Ensure CS pin is properly configured for I2C mode
**Incorrect Readings**
* Verify full-scale range settings
* Check scale factor calculations
* Ensure sensor is properly calibrated
**Communication Errors**
* Reduce I2C frequency
* Check for signal integrity issues
* Verify pull-up resistor values

View File

@@ -496,6 +496,7 @@ Implemented Drivers
- mpu9250
- ms56xx
- :doc:`nau7802`
- :doc:`qmi8658`
- :doc:`sht4x`
- :doc:`lsm6dso32`
- wtgahrs2

View File

@@ -344,6 +344,12 @@ if(CONFIG_SENSORS)
list(APPEND SRCS tmp112.c)
endif()
# QMI8658 6-axis IMU
if(CONFIG_SENSORS_QMI8658)
list(APPEND SRCS qmi8658_uorb.c)
endif()
endif() # CONFIG_I2C
# These drivers depend on SPI support

View File

@@ -2152,4 +2152,35 @@ config TMP112_I2C_FREQUENCY
endif #SENSORS_TMP112
config SENSORS_QMI8658
bool "QST QMI8658 6-Axis IMU Sensor support"
default n
depends on I2C && UORB
---help---
Enable driver support for the QST QMI8658 6-axis IMU sensor.
if SENSORS_QMI8658
config SENSORS_QMI8658_POLL
bool "Enables polling sensor data"
default n
---help---
Enables polling of sensor data.
config SENSORS_QMI8658_POLL_INTERVAL
int "Polling interval in microseconds, default 1s"
depends on SENSORS_QMI8658_POLL
default 1000000
range 0 4294967295
---help---
The interval until a new sensor measurement will be triggered.
config QMI8658_I2C_FREQUENCY
int "QMI8658 I2C frequency"
default 400000
---help---
I2C frequency used to communicate with QMI8658.
endif # SENSORS_QMI8658
endif # SENSORS

View File

@@ -418,6 +418,12 @@ ifeq ($(CONFIG_SENSORS_MPU9250),y)
CSRCS += mpu9250_uorb.c
endif
# QMI8658 6-axis IMU
ifeq ($(CONFIG_SENSORS_QMI8658),y)
CSRCS += qmi8658_uorb.c
endif
# Quadrature encoder upper half
ifeq ($(CONFIG_SENSORS_QENCODER),y)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,132 @@
/****************************************************************************
* include/nuttx/sensors/qmi8658.h
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __INCLUDE_NUTTX_SENSORS_QMI8658_H
#define __INCLUDE_NUTTX_SENSORS_QMI8658_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/sensors/sensor.h>
#include <nuttx/i2c/i2c_master.h>
#include <stdint.h>
#include <sys/ioctl.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Accelerometer Full Scale Ranges */
#define QMI8658_ACC_FS_2G (0x00)
#define QMI8658_ACC_FS_4G (0x01)
#define QMI8658_ACC_FS_8G (0x02)
#define QMI8658_ACC_FS_16G (0x03)
/* Gyroscope Full Scale Ranges */
#define QMI8658_GYRO_FS_16DPS (0x00)
#define QMI8658_GYRO_FS_32DPS (0x01)
#define QMI8658_GYRO_FS_64DPS (0x02)
#define QMI8658_GYRO_FS_128DPS (0x03)
#define QMI8658_GYRO_FS_256DPS (0x04)
#define QMI8658_GYRO_FS_512DPS (0x05)
#define QMI8658_GYRO_FS_1024DPS (0x06)
/* ODR (Output Data Rate) Definitions */
/* Accelerometer ODR */
#define QMI8658_ACC_ODR_1000Hz (0x03)
#define QMI8658_ACC_ODR_500Hz (0x04)
#define QMI8658_ACC_ODR_250Hz (0x05)
#define QMI8658_ACC_ODR_125Hz (0x06)
#define QMI8658_ACC_ODR_62_5Hz (0x07)
#define QMI8658_ACC_ODR_31_25Hz (0x08)
#define QMI8658_ACC_ODR_LOWPOWER_128Hz (0x0C)
#define QMI8658_ACC_ODR_LOWPOWER_21Hz (0x0D)
#define QMI8658_ACC_ODR_LOWPOWER_11Hz (0x0E)
#define QMI8658_ACC_ODR_LOWPOWER_3Hz (0x0F)
/* Gyroscope ODR */
#define QMI8658_GYRO_ODR_7174_4Hz (0x00)
#define QMI8658_GYRO_ODR_3587_2Hz (0x01)
#define QMI8658_GYRO_ODR_1793_6Hz (0x02)
#define QMI8658_GYRO_ODR_896_8Hz (0x03)
#define QMI8658_GYRO_ODR_448_4Hz (0x04)
#define QMI8658_GYRO_ODR_224_2Hz (0x05)
#define QMI8658_GYRO_ODR_112_1Hz (0x06)
#define QMI8658_GYRO_ODR_56_05Hz (0x07)
#define QMI8658_GYRO_ODR_28_025Hz (0x08)
/* Scale Factors */
/* Accelerometer scale factors (LSB/g) */
#define QMI8658_ACC_SCALE_2G (16384.0f)
#define QMI8658_ACC_SCALE_4G (8192.0f)
#define QMI8658_ACC_SCALE_8G (4096.0f)
#define QMI8658_ACC_SCALE_16G (2048.0f)
/* Gyroscope scale factors (LSB/dps) */
#define QMI8658_GYRO_SCALE_16DPS (2048.0f)
#define QMI8658_GYRO_SCALE_32DPS (1024.0f)
#define QMI8658_GYRO_SCALE_64DPS (512.0f)
#define QMI8658_GYRO_SCALE_128DPS (256.0f)
#define QMI8658_GYRO_SCALE_256DPS (128.0f)
#define QMI8658_GYRO_SCALE_512DPS (64.0f)
#define QMI8658_GYRO_SCALE_1024DPS (32.0f)
/* Temperature Scale Factor (LSB/°C) */
#define QMI8658_TEMP_SCALE (256.0f)
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
#ifdef __cplusplus
extern "C"
{
#endif
/****************************************************************************
* Name: qmi8658_uorb_register
*
* Description:
* Register the QMI8658 uORB sensor device
*
* Input Parameters:
* devno - Device number to use
* i2c - Pointer to the I2C master device
* addr - I2C address (use QMI8658_I2C_ADDR for default)
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
****************************************************************************/
int qmi8658_uorb_register(int devno, FAR struct i2c_master_s *i2c,
uint8_t addr);
#ifdef __cplusplus
}
#endif
#endif /* __INCLUDE_NUTTX_SENSORS_QMI8658_H */

View File

@@ -93,11 +93,9 @@ if(CONFIG_LIBM_NEWLIB)
file(GLOB_RECURSE COMMON_CSRCS ${NEWLIB_DIR}/newlib/libm/common/*.c)
file(GLOB_RECURSE COMPLEX_CSRCS ${NEWLIB_DIR}/newlib/libm/complex/*.c)
if(CONFIG_ARCH_X86_64)
file(GLOB_RECURSE ARCH_CSRCS ${NEWLIB_DIR}/newlib/libm/fenv/*.c)
endif()
file(GLOB_RECURSE FENV_CSRCS ${NEWLIB_DIR}/newlib/libm/fenv/*.c)
set(CSRCS ${COMMON_CSRCS} ${COMPLEX_CSRCS} ${ARCH_CSRCS})
set(CSRCS ${COMMON_CSRCS} ${COMPLEX_CSRCS} ${FENV_CSRCS})
# aggressive optimisation can replace occurrences of sinl() and cosl() with
# sincosl(), but sincosl() is missing in newlib which causes error. So let's
@@ -123,13 +121,30 @@ if(CONFIG_LIBM_NEWLIB)
list(APPEND CSRCS ${MATH_CSRCS})
endif()
set(ARCH_FILENAMES "")
foreach(arch_file ${ARCH_CSRCS})
get_filename_component(arch_filename ${arch_file} NAME)
list(APPEND ARCH_FILENAMES ${arch_filename})
endforeach()
set(FILTERED_CSRCS "")
foreach(file ${CSRCS})
get_filename_component(filename ${file} NAME)
list(FIND ARCH_FILENAMES ${filename} index)
if(index EQUAL -1)
list(APPEND FILTERED_CSRCS ${file})
endif()
endforeach()
set(CSRCS ${FILTERED_CSRCS} ${ARCH_CSRCS})
# ############################################################################
# Include Directory
# ############################################################################
set(INCDIR ${CMAKE_CURRENT_LIST_DIR}/include ${NEWLIB_DIR}/newlib/libm/common)
if(CONFIG_ARCH_X86_64)
if(CONFIG_ARCH_X86_64 OR CONFIG_ARCH_X86)
list(APPEND INCDIR ${NEWLIB_DIR}/newlib/libc/machine/shared_x86/sys)
endif()

View File

@@ -88,12 +88,11 @@ VPATH += :newlib/newlib/newlib/libm/complex
DEPPATH += --dep-path newlib/newlib/newlib/libm/common
DEPPATH += --dep-path newlib/newlib/newlib/libm/complex
ifeq ($(CONFIG_ARCH_X86_64),y)
CSRCS += $(wildcard newlib/newlib/newlib/libm/fenv/*.c)
VPATH += :newlib/newlib/newlib/libm/fenv
DEPPATH += --dep-path newlib/newlib/newlib/libm/fenv
ifneq ($(CONFIG_ARCH_X86_64)$(CONFIG_ARCH_X86),)
CFLAGS += ${INCDIR_PREFIX}newlib/newlib/newlib/libc/machine/shared_x86/sys
endif