mirror of
https://github.com/apache/nuttx.git
synced 2026-09-10 10:56:41 +00:00
drivers/sensors: add LSM6DS3TR-C uORB driver for the XIAO ESP32-S3
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 (#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>
This commit is contained in:
parent
bd2081aeec
commit
300c7363d7
9 changed files with 1581 additions and 0 deletions
|
|
@ -66,6 +66,10 @@ ifeq ($(CONFIG_SENSORS_BMP180),y)
|
|||
CSRCS += esp32s3_board_bmp180.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_LSM6DS3TRC),y)
|
||||
CSRCS += esp32s3_board_lsm6ds3trc.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_ESP32S3_OTG),y)
|
||||
CSRCS += esp32s3_board_usb.c
|
||||
endif
|
||||
|
|
|
|||
131
boards/xtensa/esp32s3/common/src/esp32s3_board_lsm6ds3trc.c
Normal file
131
boards/xtensa/esp32s3/common/src/esp32s3_board_lsm6ds3trc.c
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
/****************************************************************************
|
||||
* boards/xtensa/esp32s3/common/src/esp32s3_board_lsm6ds3trc.c
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <nuttx/i2c/i2c_master.h>
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/sensors/lsm6ds3trc.h>
|
||||
|
||||
#include "espressif/esp_gpio.h"
|
||||
#include "esp32s3_i2c.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* INT1/INT2 routing on Seeed's "IMU Breakout Board for XIAO" (XIAOML Kit),
|
||||
* confirmed from the board's schematic (IMU_Breakout_Board_for_XIAO_SCH,
|
||||
* rev V1.0): LSM6DS3TR-C INT1 -> XIAO GPIO3 (D2), INT2 -> XIAO GPIO4 (D3),
|
||||
* each through a 33ohm series resistor, both populated. The chip can OR
|
||||
* both DRDY_XL and DRDY_G onto either pin, so only one is used -- INT1 is
|
||||
* an arbitrary but fixed choice. GPIO4/INT2 stays unused by the driver.
|
||||
*/
|
||||
|
||||
#define LSM6DS3TRC_IRQ_PIN 3 /* INT1 */
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: board_lsm6ds3trc_attach
|
||||
*
|
||||
* Description:
|
||||
* Attach (or detach, if handler is NULL) the shared data-ready
|
||||
* interrupt handler to INT1 (XIAO GPIO3).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int board_lsm6ds3trc_attach(xcpt_t handler, FAR void *arg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
esp_gpioirqdisable(LSM6DS3TRC_IRQ_PIN);
|
||||
|
||||
ret = esp_gpio_irq(LSM6DS3TRC_IRQ_PIN, handler, arg);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_gpioirqenable(LSM6DS3TRC_IRQ_PIN);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: board_lsm6ds3trc_initialize
|
||||
*
|
||||
* Description:
|
||||
* Initialize and register the LSM6DS3TR-C 6-axis IMU driver, exposing
|
||||
* it through uORB as /dev/uorb/sensor_accelN and /dev/uorb/sensor_gyroN.
|
||||
* Data is delivered from the shared INT1 data-ready interrupt rather
|
||||
* than kthread polling.
|
||||
*
|
||||
* Input Parameters:
|
||||
* devno - The device number, used to build the uORB device paths
|
||||
* busno - The I2C bus number
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int board_lsm6ds3trc_initialize(int devno, int busno)
|
||||
{
|
||||
struct i2c_master_s *i2c;
|
||||
|
||||
static const struct lsm6ds3trc_config_s config =
|
||||
{
|
||||
.int_pin = LSM6DS3TRC_INT1,
|
||||
.attach = board_lsm6ds3trc_attach,
|
||||
};
|
||||
|
||||
/* The IMU drives INT1 push-pull, active high by default (CTRL3_C
|
||||
* H_LACTIVE reset value) -- rising edge signals data ready. No pull
|
||||
* needed once the sensor drives the line, but PULLDOWN gives a defined
|
||||
* idle state before CTRL registers are written during registration.
|
||||
*/
|
||||
|
||||
esp_configgpio(LSM6DS3TRC_IRQ_PIN, INPUT_FUNCTION_2 | PULLDOWN | RISING);
|
||||
|
||||
i2c = esp32s3_i2cbus_initialize(busno);
|
||||
if (i2c == NULL)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* SA0 tied low on this board -> 0x6a. Use 0x6b if SA0 is pulled high. */
|
||||
|
||||
return lsm6ds3trc_register(i2c, 0x6a, devno,
|
||||
(FAR struct lsm6ds3trc_config_s *)&config);
|
||||
}
|
||||
|
|
@ -70,5 +70,33 @@ int esp32s3_bringup(void);
|
|||
int esp32s3_gpio_init(void);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: board_i2c_init
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_I2C_DRIVER
|
||||
int board_i2c_init(void);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: board_lsm6ds3trc_initialize
|
||||
*
|
||||
* Description:
|
||||
* Initialize and register the LSM6DS3TR-C 6-axis IMU driver, exposing
|
||||
* it through uORB as /dev/uorb/sensor_accelN and /dev/uorb/sensor_gyroN.
|
||||
*
|
||||
* Input Parameters:
|
||||
* devno - The device number, used to build the uORB device paths
|
||||
* busno - The I2C bus number
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_SENSORS_LSM6DS3TRC
|
||||
int board_lsm6ds3trc_initialize(int devno, int busno);
|
||||
#endif
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* __BOARDS_XTENSA_ESP32S3_ESP32S3_XIAO_SRC_ESP32S3_XIAO_H */
|
||||
|
|
|
|||
|
|
@ -47,6 +47,10 @@
|
|||
# include "espressif/esp_hr_timer.h"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ESP32S3_I2C
|
||||
# include "esp32s3_i2c.h"
|
||||
#endif
|
||||
|
||||
#include "esp32s3-xiao.h"
|
||||
|
||||
#ifdef CONFIG_USERLED
|
||||
|
|
@ -119,6 +123,28 @@ int esp32s3_bringup(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_I2C_DRIVER
|
||||
/* Configure I2C peripheral interfaces */
|
||||
|
||||
ret = board_i2c_init();
|
||||
if (ret < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "Failed to initialize I2C driver: %d\n", ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SENSORS_LSM6DS3TRC
|
||||
/* Try to register the LSM6DS3TR-C device on I2C0 (D4/D5 = SDA/SCL) */
|
||||
|
||||
ret = board_lsm6ds3trc_initialize(0, ESP32S3_I2C0);
|
||||
if (ret < 0)
|
||||
{
|
||||
syslog(LOG_ERR,
|
||||
"Failed to initialize LSM6DS3TR-C driver for I2C0: %d\n",
|
||||
ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If we got here then perhaps not all initialization was successful, but
|
||||
* at least enough succeeded to bring-up NSH with perhaps reduced
|
||||
* capabilities.
|
||||
|
|
|
|||
|
|
@ -151,6 +151,10 @@ if(CONFIG_SENSORS)
|
|||
list(APPEND SRCS lsm6dso32_uorb.c)
|
||||
endif()
|
||||
|
||||
if(CONFIG_SENSORS_LSM6DS3TRC)
|
||||
list(APPEND SRCS lsm6ds3trc_uorb.c)
|
||||
endif()
|
||||
|
||||
if(CONFIG_SENSORS_LSM9DS1)
|
||||
list(APPEND SRCS lsm9ds1_base.c)
|
||||
if(CONFIG_SENSORS_LSM9DS1_UORB)
|
||||
|
|
|
|||
|
|
@ -1074,6 +1074,49 @@ config SENSORS_LSM6DSO32_GYRO_ORB_BUFSIZE
|
|||
|
||||
endif # SENSORS_LSM6DSO32
|
||||
|
||||
config SENSORS_LSM6DS3TRC
|
||||
bool "STM LSM6DS3TR-C support"
|
||||
default n
|
||||
select I2C
|
||||
select SCHED_HPWORK
|
||||
---help---
|
||||
Enable uORB driver support for the STM LSM6DS3TR-C 6-axis IMU
|
||||
over I2C. Needs the high-priority work queue even in kthread
|
||||
polling mode: the driver's interrupt handlers reference it
|
||||
unconditionally (they're only dead code until a future phase wires
|
||||
up INT1/INT2).
|
||||
|
||||
if SENSORS_LSM6DS3TRC
|
||||
|
||||
config SENSORS_LSM6DS3TRC_I2C_FREQUENCY
|
||||
int "LSM6DS3TR-C I2C frequency"
|
||||
default 400000
|
||||
range 1 400000
|
||||
---help---
|
||||
The I2C frequency used to communicate with the LSM6DS3TR-C.
|
||||
|
||||
config SENSORS_LSM6DS3TRC_THREAD_STACKSIZE
|
||||
int "LSM6DS3TR-C worker thread stack size"
|
||||
default 1024
|
||||
---help---
|
||||
The stack size for the worker threads that perform measurements.
|
||||
|
||||
config SENSORS_LSM6DS3TRC_ACCEL_ORB_BUFSIZE
|
||||
int "LSM6DS3TR-C accelerometer uORB buffer size"
|
||||
default 10
|
||||
range 0 500
|
||||
---help---
|
||||
The circular buffer size for the accelerometer uORB measurements
|
||||
|
||||
config SENSORS_LSM6DS3TRC_GYRO_ORB_BUFSIZE
|
||||
int "LSM6DS3TR-C gyroscope uORB buffer size"
|
||||
default 10
|
||||
range 0 500
|
||||
---help---
|
||||
The circular buffer size for the gyroscope uORB measurements
|
||||
|
||||
endif # SENSORS_LSM6DS3TRC
|
||||
|
||||
config SENSORS_LSM9DS1
|
||||
bool "STMicro LSM9DS1 support"
|
||||
default n
|
||||
|
|
|
|||
|
|
@ -163,6 +163,10 @@ ifeq ($(CONFIG_SENSORS_LSM6DSO32),y)
|
|||
CSRCS += lsm6dso32_uorb.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_LSM6DS3TRC),y)
|
||||
CSRCS += lsm6ds3trc_uorb.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_LSM9DS1),y)
|
||||
CSRCS += lsm9ds1_base.c
|
||||
ifeq ($(CONFIG_SENSORS_LSM9DS1_UORB),y)
|
||||
|
|
|
|||
1242
drivers/sensors/lsm6ds3trc_uorb.c
Normal file
1242
drivers/sensors/lsm6ds3trc_uorb.c
Normal file
File diff suppressed because it is too large
Load diff
99
include/nuttx/sensors/lsm6ds3trc.h
Normal file
99
include/nuttx/sensors/lsm6ds3trc.h
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
/****************************************************************************
|
||||
* include/nuttx/sensors/lsm6ds3trc.h
|
||||
*
|
||||
* 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_LSM6DS3TRC_H
|
||||
#define __INCLUDE_NUTTX_SENSORS_LSM6DS3TRC_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/i2c/i2c_master.h>
|
||||
#include <nuttx/sensors/ioctl.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
/* LSM6DS3TR-C interrupt pins */
|
||||
|
||||
enum lsm6ds3trc_int_e
|
||||
{
|
||||
LSM6DS3TRC_INT1 = 0, /* Interrupt pin 1 */
|
||||
LSM6DS3TRC_INT2 = 1, /* Interrupt pin 2 */
|
||||
};
|
||||
|
||||
typedef int (*lsm6ds3trc_attach)(xcpt_t handler, FAR void *arg);
|
||||
|
||||
/* Configuration for the LSM6DS3TR-C driver.
|
||||
*
|
||||
* The chip can OR both the accelerometer and gyroscope data-ready flags
|
||||
* onto a single INT pin (each has its own enable bit in that pin's
|
||||
* INT<n>_CTRL register), so one interrupt line is enough for both
|
||||
* sub-sensors -- there's no need for the two independent INT1/INT2 paths
|
||||
* a chip with a single combined DRDY bit would require two pins for.
|
||||
* Mirrors mpu6050_config_s: one shared handler, one shared HPWORK worker
|
||||
* that bursts accel+gyro+temp from one contiguous I2C read and pushes
|
||||
* whichever topic(s) are currently subscribed.
|
||||
*
|
||||
* Leave `attach` NULL to use kthread polling instead (each sub-sensor
|
||||
* polls independently at its own rate, same as always).
|
||||
*/
|
||||
|
||||
struct lsm6ds3trc_config_s
|
||||
{
|
||||
enum lsm6ds3trc_int_e int_pin; /* INT pin both DRDY_XL and DRDY_G use */
|
||||
lsm6ds3trc_attach attach; /* Attach the interrupt (NULL for kthread) */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: lsm6ds3trc_register
|
||||
*
|
||||
* Description:
|
||||
* Register the LSM6DS3TR-C as a UORB sensor with accel and gyro topics.
|
||||
* If used with interrupts and device registration fails, it is the
|
||||
* caller's responsibility to detach the interrupt handler.
|
||||
*
|
||||
* Input Parameters:
|
||||
* i2c - An instance of the I2C interface to use to communicate with
|
||||
* the LSM6DS3TR-C
|
||||
* addr - The I2C address of the LSM6DS3TR-C (0x6a with SA0 low, 0x6b
|
||||
* with SA0 high).
|
||||
* devno - The device number for the UORB topics registered (i.e.
|
||||
* sensor_accel<n>)
|
||||
* config - Configuration setup for interrupt-driven or polling driven
|
||||
* data fetching. Leave `*_attach` function NULL to use kthread
|
||||
* polling instead of interrupt handling. Must not be NULL.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int lsm6ds3trc_register(FAR struct i2c_master_s *i2c, uint8_t addr,
|
||||
uint8_t devno,
|
||||
FAR struct lsm6ds3trc_config_s *config);
|
||||
|
||||
#endif /* __INCLUDE_NUTTX_SENSORS_LSM6DS3TRC_H */
|
||||
Loading…
Add table
Add a link
Reference in a new issue