feat(boards/px4_fmu-v6c): add support for LSM6DSV16X (#26951)

* feat(drivers): add ST LSM6DSV16X IMU driver

Add a new SPI driver for the ST LSM6DSV16X 6-axis IMU with FIFO-based
accel, gyro, and temperature acquisition.

The driver supports continuous FIFO mode with tagged sample parsing,
DRDY interrupt triggering via FIFO threshold, and dynamic watermark
configuration based on the selected sample rate. It also falls back to
scheduled polling when a GPIO interrupt is not available.

To improve robustness, the driver periodically validates critical
register settings and limits FIFO draining per cycle.

Tested on Pixhawk6C with ground testing and flight validation.

* feat(boards/px4_fmu-v6c): add LSM6DSV16X support for Pixhawk6C

Enable the ST LSM6DSV16X as an alternative probe-based IMU on
Pixhawk6C.

The sensor is configured on SPI1 with chip-select PC13 and shares the
same CS and DRDY lines as the ICM42688P across all supported hardware
revisions. Board startup first probes the ICM42688P and then the
LSM6DSV16X, so only the IMU populated on a given board is started.

This change enables the LSM6DSV16X driver in the board configuration,
registers the device type in `spi.cpp`, and adds board sensor probing
for the new IMU.

Use rotation `-R 26` (`ROTATION_PITCH_180_YAW_90`) to match the sensor
orientation on the Pixhawk6C PCB.

* fix(drivers/lsm6dsv): address review comments

- add missing #include <cstddef> for size_t
- check FIFO status transfer() return value
- fix FIFO word count to sample period conversion (DIFF_FIFO reports
  words, not sample periods; each sample period is 2 words)
- fix drv_sensor.h macro alignment (spaces to tab)

* drv_sensor: move LSM6DSV devtype into IMU range

* fmu-v6c: use quiet LSM6DSV fallback probe
This commit is contained in:
zebulon-86
2026-04-16 11:04:00 +08:00
committed by GitHub
parent e9a8bc804b
commit d439ae9e28
10 changed files with 1066 additions and 2 deletions
+1
View File
@@ -22,6 +22,7 @@ CONFIG_DRIVERS_HEATER=y
CONFIG_DRIVERS_IMU_BOSCH_BMI055=y
CONFIG_DRIVERS_IMU_BOSCH_BMI088=y
CONFIG_DRIVERS_IMU_INVENSENSE_ICM42688P=y
CONFIG_DRIVERS_IMU_ST_LSM6DSV=y
CONFIG_COMMON_LIGHT=y
CONFIG_COMMON_MAGNETOMETER=y
CONFIG_DRIVERS_POWER_MONITOR_INA226=y
+5 -2
View File
@@ -15,8 +15,11 @@ else
bmi055 -G -R 4 -s start
fi
# Internal SPI bus ICM42688p
icm42688p -R 6 -s start
# Internal SPI bus IMU (probe-based: LSM6DSV or ICM42688P on same CS)
if ! icm42688p -R 6 -s -q start
then
lsm6dsv -R 26 -s start
fi
# Internal barometer on I2C4 (The same bus is also exposed externally, and therefore marked as external)
ms5611 -X -b 4 -a 0x77 start
+5
View File
@@ -41,6 +41,7 @@ constexpr px4_spi_bus_all_hw_t px4_spi_buses_all_hw[BOARD_NUM_SPI_CFG_HW_VERSION
initSPIDevice(DRV_GYR_DEVTYPE_BMI055, SPI::CS{GPIO::PortC, GPIO::Pin14}, SPI::DRDY{GPIO::PortE, GPIO::Pin5}),
initSPIDevice(DRV_ACC_DEVTYPE_BMI055, SPI::CS{GPIO::PortC, GPIO::Pin15}, SPI::DRDY{GPIO::PortE, GPIO::Pin4}),
initSPIDevice(DRV_IMU_DEVTYPE_ICM42688P, SPI::CS{GPIO::PortC, GPIO::Pin13}, SPI::DRDY{GPIO::PortE, GPIO::Pin6}),
initSPIDevice(DRV_IMU_DEVTYPE_ST_LSM6DSV, SPI::CS{GPIO::PortC, GPIO::Pin13}, SPI::DRDY{GPIO::PortE, GPIO::Pin6}),
}, {GPIO::PortB, GPIO::Pin2}),
initSPIBus(SPI::Bus::SPI2, {
initSPIDevice(SPIDEV_FLASH(0), SPI::CS{GPIO::PortD, GPIO::Pin4})
@@ -51,6 +52,7 @@ constexpr px4_spi_bus_all_hw_t px4_spi_buses_all_hw[BOARD_NUM_SPI_CFG_HW_VERSION
initSPIDevice(DRV_GYR_DEVTYPE_BMI055, SPI::CS{GPIO::PortC, GPIO::Pin14}, SPI::DRDY{GPIO::PortE, GPIO::Pin5}),
initSPIDevice(DRV_ACC_DEVTYPE_BMI055, SPI::CS{GPIO::PortC, GPIO::Pin15}, SPI::DRDY{GPIO::PortE, GPIO::Pin4}),
initSPIDevice(DRV_IMU_DEVTYPE_ICM42688P, SPI::CS{GPIO::PortC, GPIO::Pin13}, SPI::DRDY{GPIO::PortE, GPIO::Pin6}),
initSPIDevice(DRV_IMU_DEVTYPE_ST_LSM6DSV, SPI::CS{GPIO::PortC, GPIO::Pin13}, SPI::DRDY{GPIO::PortE, GPIO::Pin6}),
}, {GPIO::PortB, GPIO::Pin2}),
initSPIBus(SPI::Bus::SPI2, {
initSPIDevice(SPIDEV_FLASH(0), SPI::CS{GPIO::PortD, GPIO::Pin4})
@@ -61,6 +63,7 @@ constexpr px4_spi_bus_all_hw_t px4_spi_buses_all_hw[BOARD_NUM_SPI_CFG_HW_VERSION
initSPIDevice(DRV_GYR_DEVTYPE_BMI088, SPI::CS{GPIO::PortC, GPIO::Pin14}, SPI::DRDY{GPIO::PortE, GPIO::Pin5}),
initSPIDevice(DRV_ACC_DEVTYPE_BMI088, SPI::CS{GPIO::PortC, GPIO::Pin15}, SPI::DRDY{GPIO::PortE, GPIO::Pin4}),
initSPIDevice(DRV_IMU_DEVTYPE_ICM42688P, SPI::CS{GPIO::PortC, GPIO::Pin13}, SPI::DRDY{GPIO::PortE, GPIO::Pin6}),
initSPIDevice(DRV_IMU_DEVTYPE_ST_LSM6DSV, SPI::CS{GPIO::PortC, GPIO::Pin13}, SPI::DRDY{GPIO::PortE, GPIO::Pin6}),
}, {GPIO::PortB, GPIO::Pin2}),
initSPIBus(SPI::Bus::SPI2, {
initSPIDevice(SPIDEV_FLASH(0), SPI::CS{GPIO::PortD, GPIO::Pin4})
@@ -71,6 +74,7 @@ constexpr px4_spi_bus_all_hw_t px4_spi_buses_all_hw[BOARD_NUM_SPI_CFG_HW_VERSION
initSPIDevice(DRV_GYR_DEVTYPE_BMI055, SPI::CS{GPIO::PortC, GPIO::Pin14}, SPI::DRDY{GPIO::PortE, GPIO::Pin5}),
initSPIDevice(DRV_ACC_DEVTYPE_BMI055, SPI::CS{GPIO::PortC, GPIO::Pin15}, SPI::DRDY{GPIO::PortE, GPIO::Pin4}),
initSPIDevice(DRV_IMU_DEVTYPE_ICM42688P, SPI::CS{GPIO::PortC, GPIO::Pin13}, SPI::DRDY{GPIO::PortE, GPIO::Pin6}),
initSPIDevice(DRV_IMU_DEVTYPE_ST_LSM6DSV, SPI::CS{GPIO::PortC, GPIO::Pin13}, SPI::DRDY{GPIO::PortE, GPIO::Pin6}),
}, {GPIO::PortB, GPIO::Pin2}),
initSPIBus(SPI::Bus::SPI2, {
initSPIDevice(SPIDEV_FLASH(0), SPI::CS{GPIO::PortD, GPIO::Pin4})
@@ -81,6 +85,7 @@ constexpr px4_spi_bus_all_hw_t px4_spi_buses_all_hw[BOARD_NUM_SPI_CFG_HW_VERSION
initSPIDevice(DRV_GYR_DEVTYPE_BMI088, SPI::CS{GPIO::PortC, GPIO::Pin14}, SPI::DRDY{GPIO::PortE, GPIO::Pin5}),
initSPIDevice(DRV_ACC_DEVTYPE_BMI088, SPI::CS{GPIO::PortC, GPIO::Pin15}, SPI::DRDY{GPIO::PortE, GPIO::Pin4}),
initSPIDevice(DRV_IMU_DEVTYPE_ICM42688P, SPI::CS{GPIO::PortC, GPIO::Pin13}, SPI::DRDY{GPIO::PortE, GPIO::Pin6}),
initSPIDevice(DRV_IMU_DEVTYPE_ST_LSM6DSV, SPI::CS{GPIO::PortC, GPIO::Pin13}, SPI::DRDY{GPIO::PortE, GPIO::Pin6}),
}, {GPIO::PortB, GPIO::Pin2}),
initSPIBus(SPI::Bus::SPI2, {
initSPIDevice(SPIDEV_FLASH(0), SPI::CS{GPIO::PortD, GPIO::Pin4})
+1
View File
@@ -68,6 +68,7 @@
#define DRV_MAG_DEVTYPE_QMC5883P 0x0F
#define DRV_IMU_DEVTYPE_LSM303D 0x11
#define DRV_IMU_DEVTYPE_ST_LSM6DSV 0x12
#define DRV_IMU_DEVTYPE_SIM 0x14
#define DRV_DIFF_PRESS_DEVTYPE_SIM 0x15
+47
View File
@@ -0,0 +1,47 @@
############################################################################
#
# Copyright (c) 2024-2026 PX4 Development Team. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# 3. Neither the name PX4 nor the names of its contributors may be
# used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
############################################################################
px4_add_module(
MODULE drivers__imu__st__lsm6dsv
MAIN lsm6dsv
COMPILE_FLAGS
SRCS
LSM6DSV.cpp
LSM6DSV.hpp
lsm6dsv_main.cpp
ST_LSM6DSV_Registers.hpp
DEPENDS
drivers_accelerometer
drivers_gyroscope
px4_work_queue
)
+5
View File
@@ -0,0 +1,5 @@
menuconfig DRIVERS_IMU_ST_LSM6DSV
bool "lsm6dsv"
default n
---help---
Enable support for lsm6dsv
File diff suppressed because it is too large Load Diff
+159
View File
@@ -0,0 +1,159 @@
/****************************************************************************
*
* Copyright (c) 2024-2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file LSM6DSV.hpp
*
* Driver for the ST LSM6DSV connected via SPI.
*
*/
#pragma once
#include "ST_LSM6DSV_Registers.hpp"
#include <drivers/drv_hrt.h>
#include <lib/drivers/accelerometer/PX4Accelerometer.hpp>
#include <lib/drivers/device/spi.h>
#include <lib/drivers/gyroscope/PX4Gyroscope.hpp>
#include <lib/geo/geo.h>
#include <lib/perf/perf_counter.h>
#include <px4_platform_common/atomic.h>
#include <px4_platform_common/i2c_spi_buses.h>
using namespace ST_LSM6DSV;
class LSM6DSV : public device::SPI, public I2CSPIDriver<LSM6DSV>
{
public:
LSM6DSV(const I2CSPIDriverConfig &config);
~LSM6DSV() override;
static void print_usage();
void RunImpl();
int init() override;
void print_status() override;
private:
void exit_and_cleanup() override;
// Sensor Configuration
static constexpr float FIFO_SAMPLE_DT{1e6f / GYRO_ODR};
static constexpr float GYRO_RATE{static_cast<float>(GYRO_ODR)};
static constexpr float ACCEL_RATE{static_cast<float>(ACCEL_ODR)};
static constexpr int32_t FIFO_MAX_SAMPLES{static_cast<int32_t>(FIFO::MAX_DRAIN_SAMPLES)};
struct register_config_t {
Register reg;
uint8_t set_bits{0};
uint8_t clear_bits{0};
};
int probe() override;
bool Reset();
bool Configure();
void ConfigureSampleRate(int sample_rate);
bool RegisterCheck(const register_config_t &reg_cfg);
uint8_t RegisterRead(Register reg);
void RegisterWrite(Register reg, uint8_t value);
void RegisterSetAndClearBits(Register reg, uint8_t setbits, uint8_t clearbits);
bool FIFORead(const hrt_abstime &timestamp_sample, uint16_t samples);
void FIFOReset();
void UpdateTemperature();
static int DataReadyInterruptCallback(int irq, void *context, void *arg);
void DataReady();
bool DataReadyInterruptConfigure();
bool DataReadyInterruptDisable();
void ConfigureFIFOWatermark(uint8_t samples);
const spi_drdy_gpio_t _drdy_gpio;
PX4Accelerometer _px4_accel;
PX4Gyroscope _px4_gyro;
perf_counter_t _bad_register_perf{perf_alloc(PC_COUNT, MODULE_NAME": bad register")};
perf_counter_t _bad_transfer_perf{perf_alloc(PC_COUNT, MODULE_NAME": bad transfer")};
perf_counter_t _fifo_empty_perf{perf_alloc(PC_COUNT, MODULE_NAME": FIFO empty")};
perf_counter_t _fifo_overflow_perf{perf_alloc(PC_COUNT, MODULE_NAME": FIFO overflow")};
perf_counter_t _fifo_reset_perf{perf_alloc(PC_COUNT, MODULE_NAME": FIFO reset")};
perf_counter_t _drdy_missed_perf{nullptr};
hrt_abstime _reset_timestamp{0};
hrt_abstime _last_config_check_timestamp{0};
hrt_abstime _temperature_update_timestamp{0};
int _failure_count{0};
px4::atomic<hrt_abstime> _drdy_timestamp_sample{0};
bool _data_ready_interrupt_enabled{false};
enum class STATE : uint8_t {
RESET,
WAIT_FOR_RESET,
CONFIGURE,
FIFO_RESET,
FIFO_READ,
} _state{STATE::RESET};
uint16_t _fifo_empty_interval_us{500}; // default 500 us / 2000 Hz
int32_t _fifo_gyro_samples{static_cast<int32_t>(_fifo_empty_interval_us / (1000000 / GYRO_ODR))};
uint8_t _checked_register{0};
static constexpr uint8_t size_register_cfg{12};
register_config_t _register_cfg[size_register_cfg] {
// Register | Set bits | Clear bits
{ Register::CTRL3, CTRL3_BIT::BDU | CTRL3_BIT::IF_INC, CTRL3_BIT::SW_RESET },
{ Register::HAODR_CFG, HAODR_CFG_BIT::HAODR_MODE1, 0 },
{ Register::CTRL1, HAODR_MODE1_ODR_2000HZ | CTRL1_BIT::CTRL1_MODE_HAODR, 0 },
{ Register::CTRL2, HAODR_MODE1_ODR_2000HZ | CTRL2_BIT::CTRL2_MODE_HAODR, 0 },
{ Register::CTRL6, CTRL6_BIT::FS_G_2000DPS, 0 },
{ Register::CTRL8, CTRL8_BIT::FS_XL_16G | CTRL8_BIT::LPF2_BW_ODR_DIV_10, 0 },
{ Register::CTRL9, CTRL9_BIT::LPF2_XL_EN, 0 },
{
Register::FIFO_CTRL3, static_cast<uint8_t>(FIFO_CTRL3_BIT::BDR_GY_HAODR) |
static_cast<uint8_t>(FIFO_CTRL3_BIT::BDR_XL_HAODR), 0
},
{ Register::FIFO_CTRL4, FIFO_CTRL4_BIT::FIFO_MODE_CONTINUOUS, 0 },
{ Register::INT1_CTRL, INT1_CTRL_BIT::INT1_FIFO_TH, 0 },
{ Register::CTRL4, CTRL4_BIT::DRDY_PULSED, 0 },
{ Register::FIFO_CTRL1, 0, 0 }, // WTM[7:0] set at runtime by ConfigureFIFOWatermark()
};
};
@@ -0,0 +1,217 @@
/****************************************************************************
*
* Copyright (c) 2024-2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file ST_LSM6DSV_Registers.hpp
*
* ST LSM6DSV registers.
*
*/
#pragma once
#include <cstddef>
#include <cstdint>
static constexpr uint8_t Bit0 = (1 << 0);
static constexpr uint8_t Bit1 = (1 << 1);
static constexpr uint8_t Bit2 = (1 << 2);
static constexpr uint8_t Bit3 = (1 << 3);
static constexpr uint8_t Bit4 = (1 << 4);
static constexpr uint8_t Bit5 = (1 << 5);
static constexpr uint8_t Bit6 = (1 << 6);
static constexpr uint8_t Bit7 = (1 << 7);
namespace ST_LSM6DSV
{
static constexpr uint32_t SPI_SPEED = 8 * 1000 * 1000; // 8 MHz SPI data clock
static constexpr uint8_t DIR_READ = 0x80;
static constexpr uint8_t WHO_AM_I_ID = 0x70; // LSM6DSV16X
// HAODR mode-1 ODR: 2000 Hz
static constexpr uint32_t GYRO_ODR = 2000;
static constexpr uint32_t ACCEL_ODR = 2000;
// HAODR mode-1 ODR codes (written to CTRL1/CTRL2 [3:0])
static constexpr uint8_t HAODR_MODE1_ODR_2000HZ = 0x0A;
enum class Register : uint8_t {
IF_CFG = 0x03, // Interrupt polarity and output mode
FIFO_CTRL1 = 0x07,
FIFO_CTRL2 = 0x08,
FIFO_CTRL3 = 0x09,
FIFO_CTRL4 = 0x0A,
INT1_CTRL = 0x0D, // INT1 pin control
WHO_AM_I = 0x0F,
CTRL1 = 0x10, // Accel ODR + FS
CTRL2 = 0x11, // Gyro ODR + FS
CTRL3 = 0x12, // BDU, IF_INC, SW_RESET
CTRL4 = 0x13,
CTRL6 = 0x15, // Gyro FS
CTRL8 = 0x17, // Accel FS + LPF2 BW
CTRL9 = 0x18, // LPF2 enable
FIFO_STATUS1 = 0x1B,
FIFO_STATUS2 = 0x1C,
STATUS_REG = 0x1E,
OUT_TEMP_L = 0x20,
OUT_TEMP_H = 0x21,
OUTX_L_G = 0x22,
OUTX_L_A = 0x28,
FIFO_DATA_OUT_TAG = 0x78,
FIFO_DATA_OUT_X_L = 0x79,
HAODR_CFG = 0x62,
};
// CTRL1 — Accelerometer control (ODR + operating mode + HAODR flag)
enum CTRL1_BIT : uint8_t {
// ODR_XL [3:0] — set via HAODR mode-1 code 0x0A for 2000 Hz
// OP_MODE_XL [2:0] in bits [6:4]: 0b000 = high-performance mode
CTRL1_MODE_HAODR = Bit4, // bit 4 must be set for HAODR selection
};
// CTRL2 — Gyroscope control (ODR + operating mode + HAODR flag)
enum CTRL2_BIT : uint8_t {
CTRL2_MODE_HAODR = Bit4,
};
// IF_CFG (0x03) — Interrupt polarity and output mode
enum IF_CFG_BIT : uint8_t {
H_LACTIVE = Bit4, // Interrupt active-low
PP_OD = Bit3, // Push-pull (0) / Open-drain (1)
};
// INT1_CTRL (0x0D) — INT1 pin control
enum INT1_CTRL_BIT : uint8_t {
INT1_FIFO_TH = Bit3, // FIFO threshold interrupt on INT1
};
// CTRL3
enum CTRL3_BIT : uint8_t {
BDU = Bit6, // Block Data Update
IF_INC = Bit2, // Register address auto-increment
SW_RESET = Bit0, // Software reset
};
// CTRL4
enum CTRL4_BIT : uint8_t {
INT2_on_INT1 = Bit4, // Route INT2 signals to INT1
DRDY_PULSED = Bit1, // Pulsed interrupt mode (~65 µs)
};
// CTRL6 — Gyroscope full-scale
enum CTRL6_BIT : uint8_t {
// FS_G [3:0]
FS_G_2000DPS = 0x04, // ±2000 dps
};
// CTRL8 — Accelerometer full-scale + LPF2 bandwidth
enum CTRL8_BIT : uint8_t {
// FS_XL [1:0] in bits [1:0]
FS_XL_16G = 0x03, // ±16 g
// HP_LPF2_XL_BW [2:0] in bits [7:5] — when LPF2 enabled via CTRL9
LPF2_BW_ODR_DIV_10 = Bit5, // 0x20 → ODR/10
};
// CTRL9
enum CTRL9_BIT : uint8_t {
LPF2_XL_EN = Bit3, // Enable accelerometer LPF2
};
// STATUS_REG
enum STATUS_REG_BIT : uint8_t {
XLDA = Bit0, // Accelerometer new data available
GDA = Bit1, // Gyroscope new data available
TDA = Bit2, // Temperature new data available
};
// FIFO_CTRL3 — Batch Data Rate for accel and gyro
enum FIFO_CTRL3_BIT : uint8_t {
// BDR_GY [3:0] in bits [7:4], BDR_XL [3:0] in bits [3:0]
// Set both to HAODR mode-1 code = 0x0A
BDR_XL_HAODR = HAODR_MODE1_ODR_2000HZ,
BDR_GY_HAODR = HAODR_MODE1_ODR_2000HZ << 4,
};
// FIFO_CTRL4 — FIFO mode
enum FIFO_CTRL4_BIT : uint8_t {
FIFO_MODE_BYPASS = 0x00,
FIFO_MODE_CONTINUOUS = 0x06, // Continuous mode
};
// FIFO_STATUS2 (bit layout: [7]WTM_IA [6]OVR_IA [5]FULL_IA [4]CNT_BDR [3]OVR_LATCHED [2:1]0 [0]DIFF8)
enum FIFO_STATUS2_BIT : uint8_t {
FIFO_OVR_LATCHED = Bit3, // FIFO overrun latched (cleared on read)
COUNTER_BDR_IA = Bit4, // Counter BDR reached
FIFO_OVR_IA = Bit6, // FIFO overrun status (non-latched)
DIFF_FIFO_8 = Bit0, // bit 8 of FIFO diff count
};
// HAODR_CFG
enum HAODR_CFG_BIT : uint8_t {
HAODR_MODE1 = 0x01, // Enable HAODR mode-1
};
// FIFO tag IDs (upper 5 bits of FIFO_DATA_OUT_TAG >> 3)
enum class FifoTag : uint8_t {
GYRO_NC = 0x01,
ACCEL_NC = 0x02,
TEMPERATURE = 0x03,
TIMESTAMP = 0x04,
};
namespace FIFO
{
// FIFO word: 1-byte tag + 6-byte data = 7 bytes
static constexpr size_t WORD_SIZE = 7;
// Max samples to drain per poll (avoid blocking scheduler)
static constexpr size_t MAX_DRAIN_SAMPLES = 32;
// FIFO depth: 512 words max on LSM6DSV
static constexpr size_t DEPTH = 512;
}
} // namespace ST_LSM6DSV
@@ -0,0 +1,87 @@
/****************************************************************************
*
* Copyright (c) 2024-2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#include "LSM6DSV.hpp"
#include <px4_platform_common/getopt.h>
#include <px4_platform_common/module.h>
void LSM6DSV::print_usage()
{
PRINT_MODULE_USAGE_NAME("lsm6dsv", "driver");
PRINT_MODULE_USAGE_SUBCATEGORY("imu");
PRINT_MODULE_USAGE_COMMAND("start");
PRINT_MODULE_USAGE_PARAMS_I2C_SPI_DRIVER(false, true);
PRINT_MODULE_USAGE_PARAM_INT('R', 0, 0, 35, "Rotation", true);
PRINT_MODULE_USAGE_DEFAULT_COMMANDS();
}
extern "C" int lsm6dsv_main(int argc, char *argv[])
{
int ch;
using ThisDriver = LSM6DSV;
BusCLIArguments cli{false, true};
cli.default_spi_frequency = SPI_SPEED;
while ((ch = cli.getOpt(argc, argv, "R:")) != EOF) {
switch (ch) {
case 'R':
cli.rotation = (enum Rotation)atoi(cli.optArg());
break;
}
}
const char *verb = cli.optArg();
if (!verb) {
ThisDriver::print_usage();
return -1;
}
BusInstanceIterator iterator(MODULE_NAME, cli, DRV_IMU_DEVTYPE_ST_LSM6DSV);
if (!strcmp(verb, "start")) {
return ThisDriver::module_start(cli, iterator);
}
if (!strcmp(verb, "stop")) {
return ThisDriver::module_stop(iterator);
}
if (!strcmp(verb, "status")) {
return ThisDriver::module_status(iterator);
}
ThisDriver::print_usage();
return -1;
}