From bc066af50abe1cf38554aedc34e69f885652ce4e Mon Sep 17 00:00:00 2001 From: likun17 Date: Mon, 14 Aug 2023 20:58:40 +0800 Subject: [PATCH] sensor/bmi160.c:provides work in character device mode and UORB communication mode. create a new bmi160.h file. Signed-off-by: likun17 --- drivers/sensors/Kconfig | 8 + drivers/sensors/Make.defs | 4 + drivers/sensors/bmi160.c | 714 ++++++++++++--------------------- drivers/sensors/bmi160.h | 263 ++++++++++++ include/nuttx/sensors/bmi160.h | 24 +- 5 files changed, 544 insertions(+), 469 deletions(-) create mode 100644 drivers/sensors/bmi160.h diff --git a/drivers/sensors/Kconfig b/drivers/sensors/Kconfig index 027fc2c4a72..800c9a24013 100644 --- a/drivers/sensors/Kconfig +++ b/drivers/sensors/Kconfig @@ -161,6 +161,14 @@ config SENSORS_BMI160 if SENSORS_BMI160 +config SENSORS_BMI160_UORB + bool "BMI160 UORB Interface" + default n + select UORB + ---help--- + Enables Work with the UORB or Character Device interface. + If not set, the Character Device is used by default. + choice prompt "BMI160 Interface" default SENSORS_BMI160_SPI diff --git a/drivers/sensors/Make.defs b/drivers/sensors/Make.defs index 048e93d4e69..dd5d03b4315 100644 --- a/drivers/sensors/Make.defs +++ b/drivers/sensors/Make.defs @@ -137,8 +137,12 @@ ifeq ($(CONFIG_SENSORS_BMG160),y) endif ifeq ($(CONFIG_SENSORS_BMI160),y) +ifeq ($(CONFIG_SENSORS_BMI160_UORB),y) + CSRCS += bmi160_uorb.c +else CSRCS += bmi160.c endif +endif ifeq ($(CONFIG_SENSORS_BMI270),y) CSRCS += bmi270.c diff --git a/drivers/sensors/bmi160.c b/drivers/sensors/bmi160.c index 3afcb0d2c6a..081fc329459 100644 --- a/drivers/sensors/bmi160.c +++ b/drivers/sensors/bmi160.c @@ -22,19 +22,7 @@ * Included Files ****************************************************************************/ -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include +#include "bmi160.h" #if defined(CONFIG_SENSORS_BMI160) @@ -42,203 +30,14 @@ * Pre-processor Definitions ****************************************************************************/ -#define DEVID 0xd1 - -/* I2C Address - * - * NOTE: If SDO pin is pulled to VDDIO, use 0x69 - */ - -#ifdef CONFIG_BMI160_I2C_ADDR_68 -#define BMI160_I2C_ADDR 0x68 -#else -#define BMI160_I2C_ADDR 0x69 -#endif - -#define BMI160_I2C_FREQ 400000 - -#define BMI160_CHIP_ID (0x00) /* Chip ID */ -#define BMI160_ERROR (0x02) /* Error register */ -#define BMI160_PMU_STAT (0x03) /* Current power mode */ -#define BMI160_DATA_0 (0x04) /* MAG X 7:0 (LSB) */ -#define BMI160_DATA_1 (0x05) /* MAG X 15:8 (MSB) */ -#define BMI160_DATA_2 (0x06) /* MAG Y 7:0 (LSB) */ -#define BMI160_DATA_3 (0x07) /* MAG Y 15:8 (MSB) */ -#define BMI160_DATA_4 (0x08) /* MAG Z 7:0 (LSB) */ -#define BMI160_DATA_5 (0x09) /* MAG Z 15:8 (MSB) */ -#define BMI160_DATA_6 (0x0A) /* RHALL 7:0 (LSB) */ -#define BMI160_DATA_7 (0x0B) /* RHALL 15:8 (MSB) */ -#define BMI160_DATA_8 (0x0C) /* GYR X 7:0 (LSB) */ -#define BMI160_DATA_9 (0x0D) /* GYR X 15:8 (MSB) */ -#define BMI160_DATA_10 (0x0E) /* GYR Y 7:0 (LSB) */ -#define BMI160_DATA_11 (0x0F) /* GYR Y 15:8 (MSB) */ -#define BMI160_DATA_12 (0x10) /* GYR Z 7:0 (LSB) */ -#define BMI160_DATA_13 (0x11) /* GYR Z 15:8 (MSB) */ -#define BMI160_DATA_14 (0x12) /* ACC X 7:0 (LSB) */ -#define BMI160_DATA_15 (0x13) /* ACC X 15:8 (MSB) */ -#define BMI160_DATA_16 (0x14) /* ACC Y 7:0 (LSB) */ -#define BMI160_DATA_17 (0x15) /* ACC Y 15:8 (MSB) */ -#define BMI160_DATA_18 (0x16) /* ACC Z 7:0 (LSB) */ -#define BMI160_DATA_19 (0x17) /* ACC Z 15:8 (MSB) */ -#define BMI160_SENSORTIME_0 (0x18) /* Sensor time 0 */ -#define BMI160_SENSORTIME_1 (0x19) /* Sensor time 1 */ -#define BMI160_SENSORTIME_2 (0x1A) /* Sensor time 2 */ -#define BMI160_STAT (0x1B) /* Status register */ -#define BMI160_INTR_STAT_0 (0x1C) /* Interrupt status */ -#define BMI160_INTR_STAT_1 (0x1D) -#define BMI160_INTR_STAT_2 (0x1E) -#define BMI160_INTR_STAT_3 (0x1F) -#define BMI160_TEMPERATURE_0 (0x20) /* Temperature */ -#define BMI160_TEMPERATURE_1 (0x21) -#define BMI160_FIFO_LENGTH_0 (0x22) /* FIFO length */ -#define BMI160_FIFO_LENGTH_1 (0x23) -#define BMI160_FIFO_DATA (0x24) -#define BMI160_ACCEL_CONFIG (0x40) /* ACCEL config for ODR, bandwidth and undersampling */ -#define BMI160_ACCEL_RANGE (0x41) /* ACCEL range */ -#define BMI160_GYRO_CONFIG (0x42) /* GYRO config for ODR and bandwidth */ -#define BMI160_GYRO_RANGE (0x43) /* GYRO range */ -#define BMI160_MAG_CONFIG (0x44) /* MAG config for ODR */ -#define BMI160_FIFO_DOWN (0x45) /* GYRO and ACCEL downsampling rates for FIFO */ -#define BMI160_FIFO_CONFIG_0 (0x46) /* FIFO config */ -#define BMI160_FIFO_CONFIG_1 (0x47) -#define BMI160_MAG_IF_0 (0x4B) /* MAG interface */ -#define BMI160_MAG_IF_1 (0x4C) -#define BMI160_MAG_IF_2 (0x4D) -#define BMI160_MAG_IF_3 (0x4E) -#define BMI160_MAG_IF_4 (0x4F) -#define BMI160_INTR_ENABLE_0 (0x50) /* Interrupt enable */ -#define BMI160_INTR_ENABLE_1 (0x51) -#define BMI160_INTR_ENABLE_2 (0x52) -#define BMI160_INTR_OUT_CTRL (0x53) -#define BMI160_INTR_LATCH (0x54) /* Latch duration */ -#define BMI160_INTR_MAP_0 (0x55) /* Map interrupt */ -#define BMI160_INTR_MAP_1 (0x56) -#define BMI160_INTR_MAP_2 (0x57) -#define BMI160_INTR_DATA_0 (0x58) /* Data source */ -#define BMI160_INTR_DATA_1 (0x59) -#define BMI160_INTR_LOWHIGH_0 (0x5A) /* Threshold interrupt */ -#define BMI160_INTR_LOWHIGH_1 (0x5B) -#define BMI160_INTR_LOWHIGH_2 (0x5C) -#define BMI160_INTR_LOWHIGH_3 (0x5D) -#define BMI160_INTR_LOWHIGH_4 (0x5E) -#define BMI160_INTR_MOTION_0 (0x5F) -#define BMI160_INTR_MOTION_1 (0x60) -#define BMI160_INTR_MOTION_2 (0x61) -#define BMI160_INTR_MOTION_3 (0x62) -#define BMI160_INTR_TAP_0 (0x63) -#define BMI160_INTR_TAP_1 (0x64) -#define BMI160_INTR_ORIENT_0 (0x65) -#define BMI160_INTR_ORIENT_1 (0x66) -#define BMI160_INTR_FLAT_0 (0x67) -#define BMI160_INTR_FLAT_1 (0x68) -#define BMI160_FOC_CONFIG (0x69) /* Fast offset configuration */ -#define BMI160_CONFIG (0x6A) /* Miscellaneous configuration */ -#define BMI160_IF_CONFIG (0x6B) /* Serial interface configuration */ -#define BMI160_PMU_TRIGGER (0x6C) /* GYRO power mode trigger */ -#define BMI160_SELF_TEST (0x6D) /* Self test */ -#define BMI160_NV_CONFIG (0x70) /* SPI/I2C selection */ -#define BMI160_OFFSET_0 (0x71) /* ACCEL and GYRO offset */ -#define BMI160_OFFSET_1 (0x72) -#define BMI160_OFFSET_2 (0x73) -#define BMI160_OFFSET_3 (0x74) -#define BMI160_OFFSET_4 (0x75) -#define BMI160_OFFSET_5 (0x76) -#define BMI160_OFFSET_6 (0x77) -#define BMI160_STEP_COUNT_0 (0x78) /* Step counter interrupt */ -#define BMI160_STEP_COUNT_1 (0x79) -#define BMI160_STEP_CONFIG_0 (0x7A) /* Step counter configuration */ -#define BMI160_STEP_CONFIG_1 (0x7B) -#define BMI160_CMD (0x7e) /* Command register */ - -/* Register 0x40 - ACCEL_CONFIG accel bandwidth */ - -#define ACCEL_OSR4_AVG1 (0 << 4) -#define ACCEL_OSR2_AVG2 (1 << 4) -#define ACCEL_NORMAL_AVG4 (2 << 4) -#define ACCEL_CIC_AVG8 (3 << 4) -#define ACCEL_RES_AVG2 (4 << 4) -#define ACCEL_RES_AVG4 (5 << 4) -#define ACCEL_RES_AVG8 (6 << 4) -#define ACCEL_RES_AVG16 (7 << 4) -#define ACCEL_RES_AVG32 (8 << 4) -#define ACCEL_RES_AVG64 (9 << 4) -#define ACCEL_RES_AVG128 (10 << 4) - -#define ACCEL_ODR_0_78HZ (0x01) -#define ACCEL_ODR_1_56HZ (0x02) -#define ACCEL_ODR_3_12HZ (0x03) -#define ACCEL_ODR_6_25HZ (0x04) -#define ACCEL_ODR_12_5HZ (0x05) -#define ACCEL_ODR_25HZ (0x06) -#define ACCEL_ODR_50HZ (0x07) -#define ACCEL_ODR_100HZ (0x08) -#define ACCEL_ODR_200HZ (0x09) -#define ACCEL_ODR_400HZ (0x0A) -#define ACCEL_ODR_800HZ (0x0B) -#define ACCEL_ODR_1600HZ (0x0C) - -/* Register 0x42 - GYRO_CONFIG accel bandwidth */ - -#define GYRO_OSR4_MODE (0x00 << 4) -#define GYRO_OSR2_MODE (0x01 << 4) -#define GYRO_NORMAL_MODE (0x02 << 4) -#define GYRO_CIC_MODE (0x03 << 4) - -#define GYRO_ODR_25HZ (0x06) -#define GYRO_ODR_50HZ (0x07) -#define GYRO_ODR_100HZ (0x08) -#define GYRO_ODR_200HZ (0x09) -#define GYRO_ODR_400HZ (0x0A) -#define GYRO_ODR_800HZ (0x0B) -#define GYRO_ODR_1600HZ (0x0C) -#define GYRO_ODR_3200HZ (0x0D) - -/* Register 0x7b STEP_CONFIG_1 */ - -#define STEP_CNT_EN (1 << 3) - -/* Register 0x7e - CMD */ - -#define ACCEL_PM_SUSPEND (0X10) -#define ACCEL_PM_NORMAL (0x11) -#define ACCEL_PM_LOWPOWER (0X12) -#define GYRO_PM_SUSPEND (0x14) -#define GYRO_PM_NORMAL (0x15) -#define GYRO_PM_FASTSTARTUP (0x17) -#define MAG_PM_SUSPEND (0x18) -#define MAG_PM_NORMAL (0x19) -#define MAG_PM_LOWPOWER (0x1A) - /**************************************************************************** * Private Types ****************************************************************************/ -struct bmi160_dev_s -{ -#ifdef CONFIG_SENSORS_BMI160_I2C - FAR struct i2c_master_s *i2c; /* I2C interface */ - uint8_t addr; /* I2C address */ - int freq; /* Frequency <= 3.4MHz */ - -#else /* CONFIG_SENSORS_BMI160_SPI */ - FAR struct spi_dev_s *spi; /* SPI interface */ - -#endif -}; - /**************************************************************************** * Private Functions ****************************************************************************/ -static uint8_t bmi160_getreg8(FAR struct bmi160_dev_s *priv, - uint8_t regaddr); -static void bmi160_putreg8(FAR struct bmi160_dev_s *priv, uint8_t regaddr, - uint8_t regval); -static uint16_t bmi160_getreg16(FAR struct bmi160_dev_s *priv, - uint8_t regaddr); -static void bmi160_getregs(FAR struct bmi160_dev_s *priv, uint8_t regaddr, - uint8_t *regval, int len); - /* Character driver methods */ static int bmi160_open(FAR struct file *filep); @@ -248,8 +47,6 @@ static ssize_t bmi160_read(FAR struct file *filep, FAR char *buffer, static int bmi160_ioctl(FAR struct file *filep, int cmd, unsigned long arg); -static int bmi160_checkid(FAR struct bmi160_dev_s *priv); - /**************************************************************************** * Private Data ****************************************************************************/ @@ -266,264 +63,6 @@ static const struct file_operations g_bmi160fops = bmi160_ioctl, /* ioctl */ }; -/**************************************************************************** - * Name: bmi160_configspi - * - * Description: - * - ****************************************************************************/ - -#ifdef CONFIG_SENSORS_BMI160_SPI -static inline void bmi160_configspi(FAR struct spi_dev_s *spi) -{ - /* Configure SPI for the BMI160 */ - - SPI_SETMODE(spi, SPIDEV_MODE0); - SPI_SETBITS(spi, 8); - SPI_HWFEATURES(spi, 0); - SPI_SETFREQUENCY(spi, BMI160_SPI_MAXFREQUENCY); -} -#endif - -/**************************************************************************** - * Name: bmi160_getreg8 - * - * Description: - * Read from an 8-bit BMI160 register - * - ****************************************************************************/ - -static uint8_t bmi160_getreg8(FAR struct bmi160_dev_s *priv, uint8_t regaddr) -{ - uint8_t regval = 0; - -#ifdef CONFIG_SENSORS_BMI160_I2C - struct i2c_msg_s msg[2]; - int ret; - - msg[0].frequency = priv->freq; - msg[0].addr = priv->addr; - msg[0].flags = I2C_M_NOSTOP; - msg[0].buffer = ®addr; - msg[0].length = 1; - - msg[1].frequency = priv->freq; - msg[1].addr = priv->addr; - msg[1].flags = I2C_M_READ; - msg[1].buffer = ®val; - msg[1].length = 1; - - ret = I2C_TRANSFER(priv->i2c, msg, 2); - if (ret < 0) - { - snerr("I2C_TRANSFER failed: %d\n", ret); - } - -#else /* CONFIG_SENSORS_BMI160_SPI */ - /* If SPI bus is shared then lock and configure it */ - - SPI_LOCK(priv->spi, true); - bmi160_configspi(priv->spi); - - /* Select the BMI160 */ - - SPI_SELECT(priv->spi, SPIDEV_ACCELEROMETER(0), true); - - /* Send register to read and get the next byte */ - - SPI_SEND(priv->spi, regaddr | 0x80); - SPI_RECVBLOCK(priv->spi, ®val, 1); - - /* Deselect the BMI160 */ - - SPI_SELECT(priv->spi, SPIDEV_ACCELEROMETER(0), false); - - /* Unlock bus */ - - SPI_LOCK(priv->spi, false); -#endif - - return regval; -} - -/**************************************************************************** - * Name: bmi160_putreg8 - * - * Description: - * Write a value to an 8-bit BMI160 register - * - ****************************************************************************/ - -static void bmi160_putreg8(FAR struct bmi160_dev_s *priv, uint8_t regaddr, - uint8_t regval) -{ -#ifdef CONFIG_SENSORS_BMI160_I2C - struct i2c_msg_s msg[2]; - int ret; - uint8_t txbuffer[2]; - - txbuffer[0] = regaddr; - txbuffer[1] = regval; - - msg[0].frequency = priv->freq; - msg[0].addr = priv->addr; - msg[0].flags = 0; - msg[0].buffer = txbuffer; - msg[0].length = 2; - - ret = I2C_TRANSFER(priv->i2c, msg, 1); - if (ret < 0) - { - snerr("I2C_TRANSFER failed: %d\n", ret); - } - -#else /* CONFIG_SENSORS_BMI160_SPI */ - /* If SPI bus is shared then lock and configure it */ - - SPI_LOCK(priv->spi, true); - bmi160_configspi(priv->spi); - - /* Select the BMI160 */ - - SPI_SELECT(priv->spi, SPIDEV_ACCELEROMETER(0), true); - - /* Send register address and set the value */ - - SPI_SEND(priv->spi, regaddr); - SPI_SEND(priv->spi, regval); - - /* Deselect the BMI160 */ - - SPI_SELECT(priv->spi, SPIDEV_ACCELEROMETER(0), false); - - /* Unlock bus */ - - SPI_LOCK(priv->spi, false); - -#endif -} - -/**************************************************************************** - * Name: bmi160_getreg16 - * - * Description: - * Read 16-bits of data from an BMI160 register - * - ****************************************************************************/ - -static uint16_t bmi160_getreg16(FAR struct bmi160_dev_s *priv, - uint8_t regaddr) -{ - uint16_t regval = 0; - -#ifdef CONFIG_SENSORS_BMI160_I2C - struct i2c_msg_s msg[2]; - int ret; - - msg[0].frequency = priv->freq; - msg[0].addr = priv->addr; - msg[0].flags = I2C_M_NOSTOP; - msg[0].buffer = ®addr; - msg[0].length = 1; - - msg[1].frequency = priv->freq; - msg[1].addr = priv->addr; - msg[1].flags = I2C_M_READ; - msg[1].buffer = (uint8_t *)®val; - msg[1].length = 2; - - ret = I2C_TRANSFER(priv->i2c, msg, 2); - if (ret < 0) - { - snerr("I2C_TRANSFER failed: %d\n", ret); - } - -#else /* CONFIG_SENSORS_BMI160_SPI */ - /* If SPI bus is shared then lock and configure it */ - - SPI_LOCK(priv->spi, true); - bmi160_configspi(priv->spi); - - /* Select the BMI160 */ - - SPI_SELECT(priv->spi, SPIDEV_ACCELEROMETER(0), true); - - /* Send register to read and get the next 2 bytes */ - - SPI_SEND(priv->spi, regaddr | 0x80); - SPI_RECVBLOCK(priv->spi, ®val, 2); - - /* Deselect the BMI160 */ - - SPI_SELECT(priv->spi, SPIDEV_ACCELEROMETER(0), false); - - /* Unlock bus */ - - SPI_LOCK(priv->spi, false); -#endif - - return regval; -} - -/**************************************************************************** - * Name: bmi160_getregs - * - * Description: - * Read cnt bytes from specified dev_addr and reg_addr - * - ****************************************************************************/ - -static void bmi160_getregs(FAR struct bmi160_dev_s *priv, uint8_t regaddr, - uint8_t *regval, int len) -{ -#ifdef CONFIG_SENSORS_BMI160_I2C - struct i2c_msg_s msg[2]; - int ret; - - msg[0].frequency = priv->freq; - msg[0].addr = priv->addr; - msg[0].flags = I2C_M_NOSTOP; - msg[0].buffer = ®addr; - msg[0].length = 1; - - msg[1].frequency = priv->freq; - msg[1].addr = priv->addr; - msg[1].flags = I2C_M_READ; - msg[1].buffer = regval; - msg[1].length = len; - - ret = I2C_TRANSFER(priv->i2c, msg, 2); - if (ret < 0) - { - snerr("I2C_TRANSFER failed: %d\n", ret); - } - -#else /* CONFIG_SENSORS_BMI160_SPI */ - /* If SPI bus is shared then lock and configure it */ - - SPI_LOCK(priv->spi, true); - bmi160_configspi(priv->spi); - - /* Select the BMI160 */ - - SPI_SELECT(priv->spi, SPIDEV_ACCELEROMETER(0), true); - - /* Send register to read and get the next 2 bytes */ - - SPI_SEND(priv->spi, regaddr | 0x80); - SPI_RECVBLOCK(priv->spi, regval, len); - - /* Deselect the BMI160 */ - - SPI_SELECT(priv->spi, SPIDEV_ACCELEROMETER(0), false); - - /* Unlock bus */ - - SPI_LOCK(priv->spi, false); - -#endif -} - /**************************************************************************** * Name: bmi160_set_normal_imu * @@ -608,7 +147,7 @@ static ssize_t bmi160_read(FAR struct file *filep, FAR char *buffer, if (len < sizeof(struct accel_gyro_st_s)) { - snerr("Expected buffer size is %d\n", sizeof(struct accel_gyro_st_s)); + snerr("Expected buffer size is %lu\n", sizeof(struct accel_gyro_st_s)); return 0; } @@ -686,6 +225,10 @@ static int bmi160_ioctl(FAR struct file *filep, int cmd, unsigned long arg) return ret; } +/**************************************************************************** + * Public Functions + ****************************************************************************/ + /**************************************************************************** * Name: bmi160_checkid * @@ -694,7 +237,7 @@ static int bmi160_ioctl(FAR struct file *filep, int cmd, unsigned long arg) * ****************************************************************************/ -static int bmi160_checkid(FAR struct bmi160_dev_s *priv) +int bmi160_checkid(FAR struct bmi160_dev_s *priv) { uint8_t devid = 0; @@ -713,6 +256,244 @@ static int bmi160_checkid(FAR struct bmi160_dev_s *priv) return OK; } +/**************************************************************************** + * Name: bmi160_getreg8 + * + * Description: + * Read from an 8-bit BMI160 register + * + ****************************************************************************/ + +uint8_t bmi160_getreg8(FAR struct bmi160_dev_s *priv, uint8_t regaddr) +{ + uint8_t regval = 0; + +#ifdef CONFIG_SENSORS_BMI160_I2C + struct i2c_msg_s msg[2]; + int ret; + + msg[0].frequency = priv->freq; + msg[0].addr = priv->addr; + msg[0].flags = I2C_M_NOSTOP; + msg[0].buffer = ®addr; + msg[0].length = 1; + + msg[1].frequency = priv->freq; + msg[1].addr = priv->addr; + msg[1].flags = I2C_M_READ; + msg[1].buffer = ®val; + msg[1].length = 1; + + ret = I2C_TRANSFER(priv->i2c, msg, 2); + if (ret < 0) + { + snerr("I2C_TRANSFER failed: %d\n", ret); + } + +#else /* CONFIG_SENSORS_BMI160_SPI */ + /* If SPI bus is shared then lock and configure it */ + + SPI_LOCK(priv->spi, true); + bmi160_configspi(priv->spi); + + /* Select the BMI160 */ + + SPI_SELECT(priv->spi, SPIDEV_ACCELEROMETER(0), true); + + /* Send register to read and get the next byte */ + + SPI_SEND(priv->spi, regaddr | 0x80); + SPI_RECVBLOCK(priv->spi, ®val, 1); + + /* Deselect the BMI160 */ + + SPI_SELECT(priv->spi, SPIDEV_ACCELEROMETER(0), false); + + /* Unlock bus */ + + SPI_LOCK(priv->spi, false); +#endif + + return regval; +} + +/**************************************************************************** + * Name: bmi160_putreg8 + * + * Description: + * Write a value to an 8-bit BMI160 register + * + ****************************************************************************/ + +void bmi160_putreg8(FAR struct bmi160_dev_s *priv, uint8_t regaddr, + uint8_t regval) +{ +#ifdef CONFIG_SENSORS_BMI160_I2C + struct i2c_msg_s msg[2]; + int ret; + uint8_t txbuffer[2]; + + txbuffer[0] = regaddr; + txbuffer[1] = regval; + + msg[0].frequency = priv->freq; + msg[0].addr = priv->addr; + msg[0].flags = 0; + msg[0].buffer = txbuffer; + msg[0].length = 2; + + ret = I2C_TRANSFER(priv->i2c, msg, 1); + if (ret < 0) + { + snerr("I2C_TRANSFER failed: %d\n", ret); + } + +#else /* CONFIG_SENSORS_BMI160_SPI */ + /* If SPI bus is shared then lock and configure it */ + + SPI_LOCK(priv->spi, true); + bmi160_configspi(priv->spi); + + /* Select the BMI160 */ + + SPI_SELECT(priv->spi, SPIDEV_ACCELEROMETER(0), true); + + /* Send register address and set the value */ + + SPI_SEND(priv->spi, regaddr); + SPI_SEND(priv->spi, regval); + + /* Deselect the BMI160 */ + + SPI_SELECT(priv->spi, SPIDEV_ACCELEROMETER(0), false); + + /* Unlock bus */ + + SPI_LOCK(priv->spi, false); + +#endif +} + +/**************************************************************************** + * Name: bmi160_getreg16 + * + * Description: + * Read 16-bits of data from an BMI160 register + * + ****************************************************************************/ + +uint16_t bmi160_getreg16(FAR struct bmi160_dev_s *priv, uint8_t regaddr) +{ + uint16_t regval = 0; + +#ifdef CONFIG_SENSORS_BMI160_I2C + struct i2c_msg_s msg[2]; + int ret; + + msg[0].frequency = priv->freq; + msg[0].addr = priv->addr; + msg[0].flags = I2C_M_NOSTOP; + msg[0].buffer = ®addr; + msg[0].length = 1; + + msg[1].frequency = priv->freq; + msg[1].addr = priv->addr; + msg[1].flags = I2C_M_READ; + msg[1].buffer = (uint8_t *)®val; + msg[1].length = 2; + + ret = I2C_TRANSFER(priv->i2c, msg, 2); + if (ret < 0) + { + snerr("I2C_TRANSFER failed: %d\n", ret); + } + +#else /* CONFIG_SENSORS_BMI160_SPI */ + /* If SPI bus is shared then lock and configure it */ + + SPI_LOCK(priv->spi, true); + bmi160_configspi(priv->spi); + + /* Select the BMI160 */ + + SPI_SELECT(priv->spi, SPIDEV_ACCELEROMETER(0), true); + + /* Send register to read and get the next 2 bytes */ + + SPI_SEND(priv->spi, regaddr | 0x80); + SPI_RECVBLOCK(priv->spi, ®val, 2); + + /* Deselect the BMI160 */ + + SPI_SELECT(priv->spi, SPIDEV_ACCELEROMETER(0), false); + + /* Unlock bus */ + + SPI_LOCK(priv->spi, false); +#endif + + return regval; +} + +/**************************************************************************** + * Name: bmi160_getregs + * + * Description: + * Read cnt bytes from specified dev_addr and reg_addr + * + ****************************************************************************/ + +void bmi160_getregs(FAR struct bmi160_dev_s *priv, uint8_t regaddr, + uint8_t *regval, int len) +{ +#ifdef CONFIG_SENSORS_BMI160_I2C + struct i2c_msg_s msg[2]; + int ret; + + msg[0].frequency = priv->freq; + msg[0].addr = priv->addr; + msg[0].flags = I2C_M_NOSTOP; + msg[0].buffer = ®addr; + msg[0].length = 1; + + msg[1].frequency = priv->freq; + msg[1].addr = priv->addr; + msg[1].flags = I2C_M_READ; + msg[1].buffer = regval; + msg[1].length = len; + + ret = I2C_TRANSFER(priv->i2c, msg, 2); + if (ret < 0) + { + snerr("I2C_TRANSFER failed: %d\n", ret); + } + +#else /* CONFIG_SENSORS_BMI160_SPI */ + /* If SPI bus is shared then lock and configure it */ + + SPI_LOCK(priv->spi, true); + bmi160_configspi(priv->spi); + + /* Select the BMI160 */ + + SPI_SELECT(priv->spi, SPIDEV_ACCELEROMETER(0), true); + + /* Send register to read and get the next 2 bytes */ + + SPI_SEND(priv->spi, regaddr | 0x80); + SPI_RECVBLOCK(priv->spi, regval, len); + + /* Deselect the BMI160 */ + + SPI_SELECT(priv->spi, SPIDEV_ACCELEROMETER(0), false); + + /* Unlock bus */ + + SPI_LOCK(priv->spi, false); + +#endif +} + /**************************************************************************** * Name: bmi160_register * @@ -735,10 +516,9 @@ int bmi160_register(FAR const char *devpath, FAR struct i2c_master_s *dev) int bmi160_register(FAR const char *devpath, FAR struct spi_dev_s *dev) #endif { - FAR struct bmi160_dev_s *priv; - int ret; + uint8_t devid = 0; - priv = kmm_malloc(sizeof(struct bmi160_dev_s)); + priv = (FAR struct bmi160_dev_s *)kmm_malloc(sizeof(struct bmi160_dev_s)); if (!priv) { snerr("Failed to allocate instance\n"); diff --git a/drivers/sensors/bmi160.h b/drivers/sensors/bmi160.h new file mode 100644 index 00000000000..a3f59c2abd5 --- /dev/null +++ b/drivers/sensors/bmi160.h @@ -0,0 +1,263 @@ +/**************************************************************************** + * include/nuttx/sensors/bmi160.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_BMI160_COMMOM_H +#define __INCLUDE_NUTTX_SENSORS_BMI160_COMMOM_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define DEVID 0xd1 + +/* I2C Address + * + * NOTE: If SDO pin is pulled to VDDIO, use 0x69 + */ + +#ifdef CONFIG_BMI160_I2C_ADDR_68 +#define BMI160_I2C_ADDR 0x68 +#else +#define BMI160_I2C_ADDR 0x69 +#endif + +#define BMI160_I2C_FREQ 400000 + +#define BMI160_CHIP_ID (0x00) /* Chip ID */ +#define BMI160_ERROR (0x02) /* Error register */ +#define BMI160_PMU_STAT (0x03) /* Current power mode */ +#define BMI160_DATA_0 (0x04) /* MAG X 7:0 (LSB) */ +#define BMI160_DATA_1 (0x05) /* MAG X 15:8 (MSB) */ +#define BMI160_DATA_2 (0x06) /* MAG Y 7:0 (LSB) */ +#define BMI160_DATA_3 (0x07) /* MAG Y 15:8 (MSB) */ +#define BMI160_DATA_4 (0x08) /* MAG Z 7:0 (LSB) */ +#define BMI160_DATA_5 (0x09) /* MAG Z 15:8 (MSB) */ +#define BMI160_DATA_6 (0x0A) /* RHALL 7:0 (LSB) */ +#define BMI160_DATA_7 (0x0B) /* RHALL 15:8 (MSB) */ +#define BMI160_DATA_8 (0x0C) /* GYR X 7:0 (LSB) */ +#define BMI160_DATA_9 (0x0D) /* GYR X 15:8 (MSB) */ +#define BMI160_DATA_10 (0x0E) /* GYR Y 7:0 (LSB) */ +#define BMI160_DATA_11 (0x0F) /* GYR Y 15:8 (MSB) */ +#define BMI160_DATA_12 (0x10) /* GYR Z 7:0 (LSB) */ +#define BMI160_DATA_13 (0x11) /* GYR Z 15:8 (MSB) */ +#define BMI160_DATA_14 (0x12) /* ACC X 7:0 (LSB) */ +#define BMI160_DATA_15 (0x13) /* ACC X 15:8 (MSB) */ +#define BMI160_DATA_16 (0x14) /* ACC Y 7:0 (LSB) */ +#define BMI160_DATA_17 (0x15) /* ACC Y 15:8 (MSB) */ +#define BMI160_DATA_18 (0x16) /* ACC Z 7:0 (LSB) */ +#define BMI160_DATA_19 (0x17) /* ACC Z 15:8 (MSB) */ +#define BMI160_SENSORTIME_0 (0x18) /* Sensor time 0 */ +#define BMI160_SENSORTIME_1 (0x19) /* Sensor time 1 */ +#define BMI160_SENSORTIME_2 (0x1A) /* Sensor time 2 */ +#define BMI160_STAT (0x1B) /* Status register */ +#define BMI160_INTR_STAT_0 (0x1C) /* Interrupt status */ +#define BMI160_INTR_STAT_1 (0x1D) +#define BMI160_INTR_STAT_2 (0x1E) +#define BMI160_INTR_STAT_3 (0x1F) +#define BMI160_TEMPERATURE_0 (0x20) /* Temperature */ +#define BMI160_TEMPERATURE_1 (0x21) +#define BMI160_FIFO_LENGTH_0 (0x22) /* FIFO length */ +#define BMI160_FIFO_LENGTH_1 (0x23) +#define BMI160_FIFO_DATA (0x24) +#define BMI160_ACCEL_CONFIG (0x40) /* ACCEL config for ODR, bandwidth and undersampling */ +#define BMI160_ACCEL_RANGE (0x41) /* ACCEL range */ +#define BMI160_GYRO_CONFIG (0x42) /* GYRO config for ODR and bandwidth */ +#define BMI160_GYRO_RANGE (0x43) /* GYRO range */ +#define BMI160_MAG_CONFIG (0x44) /* MAG config for ODR */ +#define BMI160_FIFO_DOWN (0x45) /* GYRO and ACCEL downsampling rates for FIFO */ +#define BMI160_FIFO_CONFIG_0 (0x46) /* FIFO config */ +#define BMI160_FIFO_CONFIG_1 (0x47) +#define BMI160_MAG_IF_0 (0x4B) /* MAG interface */ +#define BMI160_MAG_IF_1 (0x4C) +#define BMI160_MAG_IF_2 (0x4D) +#define BMI160_MAG_IF_3 (0x4E) +#define BMI160_MAG_IF_4 (0x4F) +#define BMI160_INTR_ENABLE_0 (0x50) /* Interrupt enable */ +#define BMI160_INTR_ENABLE_1 (0x51) +#define BMI160_INTR_ENABLE_2 (0x52) +#define BMI160_INTR_OUT_CTRL (0x53) +#define BMI160_INTR_LATCH (0x54) /* Latch duration */ +#define BMI160_INTR_MAP_0 (0x55) /* Map interrupt */ +#define BMI160_INTR_MAP_1 (0x56) +#define BMI160_INTR_MAP_2 (0x57) +#define BMI160_INTR_DATA_0 (0x58) /* Data source */ +#define BMI160_INTR_DATA_1 (0x59) +#define BMI160_INTR_LOWHIGH_0 (0x5A) /* Threshold interrupt */ +#define BMI160_INTR_LOWHIGH_1 (0x5B) +#define BMI160_INTR_LOWHIGH_2 (0x5C) +#define BMI160_INTR_LOWHIGH_3 (0x5D) +#define BMI160_INTR_LOWHIGH_4 (0x5E) +#define BMI160_INTR_MOTION_0 (0x5F) +#define BMI160_INTR_MOTION_1 (0x60) +#define BMI160_INTR_MOTION_2 (0x61) +#define BMI160_INTR_MOTION_3 (0x62) +#define BMI160_INTR_TAP_0 (0x63) +#define BMI160_INTR_TAP_1 (0x64) +#define BMI160_INTR_ORIENT_0 (0x65) +#define BMI160_INTR_ORIENT_1 (0x66) +#define BMI160_INTR_FLAT_0 (0x67) +#define BMI160_INTR_FLAT_1 (0x68) +#define BMI160_FOC_CONFIG (0x69) /* Fast offset configuration */ +#define BMI160_CONFIG (0x6A) /* Miscellaneous configuration */ +#define BMI160_IF_CONFIG (0x6B) /* Serial interface configuration */ +#define BMI160_PMU_TRIGGER (0x6C) /* GYRO power mode trigger */ +#define BMI160_SELF_TEST (0x6D) /* Self test */ +#define BMI160_NV_CONFIG (0x70) /* SPI/I2C selection */ +#define BMI160_OFFSET_0 (0x71) /* ACCEL and GYRO offset */ +#define BMI160_OFFSET_1 (0x72) +#define BMI160_OFFSET_2 (0x73) +#define BMI160_OFFSET_3 (0x74) +#define BMI160_OFFSET_4 (0x75) +#define BMI160_OFFSET_5 (0x76) +#define BMI160_OFFSET_6 (0x77) +#define BMI160_STEP_COUNT_0 (0x78) /* Step counter interrupt */ +#define BMI160_STEP_COUNT_1 (0x79) +#define BMI160_STEP_CONFIG_0 (0x7A) /* Step counter configuration */ +#define BMI160_STEP_CONFIG_1 (0x7B) +#define BMI160_CMD (0x7e) /* Command register */ + +/* Register 0x40 - ACCEL_CONFIG accel bandwidth */ + +#define ACCEL_OSR4_AVG1 (0 << 4) +#define ACCEL_OSR2_AVG2 (1 << 4) +#define ACCEL_NORMAL_AVG4 (2 << 4) +#define ACCEL_CIC_AVG8 (3 << 4) +#define ACCEL_RES_AVG2 (4 << 4) +#define ACCEL_RES_AVG4 (5 << 4) +#define ACCEL_RES_AVG8 (6 << 4) +#define ACCEL_RES_AVG16 (7 << 4) +#define ACCEL_RES_AVG32 (8 << 4) +#define ACCEL_RES_AVG64 (9 << 4) +#define ACCEL_RES_AVG128 (10 << 4) + +#define ACCEL_ODR_0_78HZ (0x01) +#define ACCEL_ODR_1_56HZ (0x02) +#define ACCEL_ODR_3_12HZ (0x03) +#define ACCEL_ODR_6_25HZ (0x04) +#define ACCEL_ODR_12_5HZ (0x05) +#define ACCEL_ODR_25HZ (0x06) +#define ACCEL_ODR_50HZ (0x07) +#define ACCEL_ODR_100HZ (0x08) +#define ACCEL_ODR_200HZ (0x09) +#define ACCEL_ODR_400HZ (0x0A) +#define ACCEL_ODR_800HZ (0x0B) +#define ACCEL_ODR_1600HZ (0x0C) + +/* Register 0x42 - GYRO_CONFIG accel bandwidth */ + +#define GYRO_OSR4_MODE (0x00 << 4) +#define GYRO_OSR2_MODE (0x01 << 4) +#define GYRO_NORMAL_MODE (0x02 << 4) +#define GYRO_CIC_MODE (0x03 << 4) + +#define GYRO_ODR_25HZ (0x06) +#define GYRO_ODR_50HZ (0x07) +#define GYRO_ODR_100HZ (0x08) +#define GYRO_ODR_200HZ (0x09) +#define GYRO_ODR_400HZ (0x0A) +#define GYRO_ODR_800HZ (0x0B) +#define GYRO_ODR_1600HZ (0x0C) +#define GYRO_ODR_3200HZ (0x0D) + +/* Register 0x7b STEP_CONFIG_1 */ + +#define STEP_CNT_EN (1 << 3) + +/* Register 0x7e - CMD */ + +#define ACCEL_PM_SUSPEND (0X10) +#define ACCEL_PM_NORMAL (0x11) +#define ACCEL_PM_LOWPOWER (0X12) +#define GYRO_PM_SUSPEND (0x14) +#define GYRO_PM_NORMAL (0x15) +#define GYRO_PM_FASTSTARTUP (0x17) +#define MAG_PM_SUSPEND (0x18) +#define MAG_PM_NORMAL (0x19) +#define MAG_PM_LOWPOWER (0x1A) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* Device struct */ + +struct bmi160_dev_s +{ +#ifdef CONFIG_SENSORS_BMI160_I2C + FAR struct i2c_master_s *i2c; /* I2C interface */ + uint8_t addr; /* I2C address */ + int freq; /* Frequency <= 3.4MHz */ + +#else /* CONFIG_SENSORS_BMI160_SPI */ + FAR struct spi_dev_s *spi; /* SPI interface */ + +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +uint8_t bmi160_getreg8(FAR struct bmi160_dev_s *priv, uint8_t regaddr); +void bmi160_putreg8(FAR struct bmi160_dev_s *priv, uint8_t regaddr, + uint8_t regval); +uint16_t bmi160_getreg16(FAR struct bmi160_dev_s *priv, uint8_t regaddr); +void bmi160_getregs(FAR struct bmi160_dev_s *priv, uint8_t regaddr, + uint8_t *regval, int len); + +int bmi160_checkid(FAR struct bmi160_dev_s *priv); + +/**************************************************************************** + * Name: bmi160_configspi + * + * Description: + * + ****************************************************************************/ + +#ifdef CONFIG_SENSORS_BMI160_SPI +inline void bmi160_configspi(FAR struct spi_dev_s *spi) +{ + /* Configure SPI for the BMI160 */ + + SPI_SETMODE(spi, SPIDEV_MODE0); + SPI_SETBITS(spi, 8); + SPI_HWFEATURES(spi, 0); + SPI_SETFREQUENCY(spi, BMI160_SPI_MAXFREQUENCY); +} +#endif +#endif /* __INCLUDE_NUTTX_SENSORS_BMI160_COMMOM_H */ diff --git a/include/nuttx/sensors/bmi160.h b/include/nuttx/sensors/bmi160.h index 5fd08566fa8..ce7c4ac0b3f 100644 --- a/include/nuttx/sensors/bmi160.h +++ b/include/nuttx/sensors/bmi160.h @@ -131,10 +131,30 @@ extern "C" * ****************************************************************************/ -#ifdef CONFIG_SENSORS_BMI160_I2C +#ifndef CONFIG_SENSORS_BMI160_SCU + +# ifdef CONFIG_SENSORS_BMI160_I2C int bmi160_register(FAR const char *devpath, FAR struct i2c_master_s *dev); -#else /* CONFIG_BMI160_SPI */ +# else /* CONFIG_BMI160_SPI */ int bmi160_register(FAR const char *devpath, FAR struct spi_dev_s *dev); +# endif + +#else /* CONFIG_SENSORS_BMI160_SCU */ + +# ifdef CONFIG_SENSORS_BMI160_I2C +int bmi160_init(FAR struct i2c_master_s *dev, int port); +int bmi160gyro_register(FAR const char *devpath, int minor, + FAR struct i2c_master_s *dev, int port); +int bmi160accel_register(FAR const char *devpath, int minor, + FAR struct i2c_master_s *dev, int port); +# else /* CONFIG_SENSORS_BMI160_SPI */ +int bmi160_init(FAR struct spi_dev_s *dev); +int bmi160gyro_register(FAR const char *devpath, int minor, + FAR struct spi_dev_s *dev); +int bmi160accel_register(FAR const char *devpath, int minor, + FAR struct spi_dev_s *dev); +# endif + #endif #undef EXTERN