This is an automated email from the ASF dual-hosted git repository.
xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new a5dcd6afafd sensors/lps22hb: Add a uORB barometer driver.
a5dcd6afafd is described below
commit a5dcd6afafd1a652fd6a5055f49327415126e2f0
Author: raiden00pl <[email protected]>
AuthorDate: Wed May 31 19:36:40 2023 +0200
sensors/lps22hb: Add a uORB barometer driver.
Add a uORB barometer driver for the STMicro LPS22HB, reporting pressure
in hPa and temperature on sensor_baro<n>. NuttX had no driver for this
part before.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: raiden00pl <[email protected]>
---
Documentation/os/drivers/special/sensors.rst | 1 +
.../os/drivers/special/sensors/lps22hb.rst | 24 ++
.../os/drivers/special/sensors/sensors_uorb.rst | 1 +
drivers/sensors/CMakeLists.txt | 4 +
drivers/sensors/Kconfig | 16 +
drivers/sensors/Make.defs | 4 +
drivers/sensors/lps22hb_uorb.c | 446 +++++++++++++++++++++
include/nuttx/sensors/lps22hb.h | 63 +++
8 files changed, 559 insertions(+)
diff --git a/Documentation/os/drivers/special/sensors.rst
b/Documentation/os/drivers/special/sensors.rst
index 7202a0b8e0c..a2a695fd0d7 100644
--- a/Documentation/os/drivers/special/sensors.rst
+++ b/Documentation/os/drivers/special/sensors.rst
@@ -48,3 +48,4 @@ tool for monitoring sensor activity at runtime.
sensors/l86xxx.rst
sensors/gnss_lowerhalf.rst
sensors/bh1745nuc.rst
+ sensors/lps22hb.rst
diff --git a/Documentation/os/drivers/special/sensors/lps22hb.rst
b/Documentation/os/drivers/special/sensors/lps22hb.rst
new file mode 100644
index 00000000000..71e9ba3a5b4
--- /dev/null
+++ b/Documentation/os/drivers/special/sensors/lps22hb.rst
@@ -0,0 +1,24 @@
+=======
+LPS22HB
+=======
+
+STMicroelectronics LPS22HB pressure sensor on I2C,
+:doc:`uORB </os/drivers/special/sensors/sensors_uorb>` interface.
+
+Configuration
+=============
+
+- ``CONFIG_SENSORS_LPS22HB``
+- ``CONFIG_LPS22HB_I2C_FREQUENCY``
+
+Usage
+=====
+
+.. code-block:: c
+
+ #include <nuttx/sensors/lps22hb.h>
+
+ int lps22hb_register_uorb(int devno, FAR struct i2c_master_s *i2c,
+ uint8_t addr);
+
+Registers ``sensor_baro<devno>`` (hPa, °C).
diff --git a/Documentation/os/drivers/special/sensors/sensors_uorb.rst
b/Documentation/os/drivers/special/sensors/sensors_uorb.rst
index aac5f02ba59..446302ff216 100644
--- a/Documentation/os/drivers/special/sensors/sensors_uorb.rst
+++ b/Documentation/os/drivers/special/sensors/sensors_uorb.rst
@@ -563,6 +563,7 @@ Implemented Drivers
- l3gd20
- :doc:`lis2mdl`
- lis3dsh
+- :doc:`lps22hb`
- lsm9ds1
- ltr308
- :doc:`mpu6050`
diff --git a/drivers/sensors/CMakeLists.txt b/drivers/sensors/CMakeLists.txt
index 98c60c073ce..e062a53e9d7 100644
--- a/drivers/sensors/CMakeLists.txt
+++ b/drivers/sensors/CMakeLists.txt
@@ -172,6 +172,10 @@ if(CONFIG_SENSORS)
list(APPEND SRCS lps25h.c)
endif()
+ if(CONFIG_SENSORS_LPS22HB)
+ list(APPEND SRCS lps22hb_uorb.c)
+ endif()
+
if(CONFIG_SENSORS_CCS811)
list(APPEND SRCS ccs811_uorb.c)
endif()
diff --git a/drivers/sensors/Kconfig b/drivers/sensors/Kconfig
index 2214e296b93..786ea1e0a06 100644
--- a/drivers/sensors/Kconfig
+++ b/drivers/sensors/Kconfig
@@ -1234,6 +1234,22 @@ config LSM9DS1_I2C_FREQUENCY
range 1 400000
depends on SENSORS_LSM9DS1 || SENSORS_LSM9DS1_UORB
+config SENSORS_LPS22HB
+ bool "STMicro LPS22HB pressure sensor"
+ default n
+ select I2C
+ ---help---
+ Enable driver support for the STMicro LPS22HB barometer sensor.
+
+if SENSORS_LPS22HB
+
+config LPS22HB_I2C_FREQUENCY
+ int "LPS22HB I2C frequency"
+ default 400000
+ range 1 400000
+
+endif # SENSORS_LPS22HB
+
config SENSORS_LPS25H
bool "STMicro LPS25H pressure sensor"
default n
diff --git a/drivers/sensors/Make.defs b/drivers/sensors/Make.defs
index 02cbdbdf6f6..e643938382e 100644
--- a/drivers/sensors/Make.defs
+++ b/drivers/sensors/Make.defs
@@ -180,6 +180,10 @@ ifeq ($(CONFIG_SENSORS_MSA301),y)
CSRCS += msa301.c
endif
+ifeq ($(CONFIG_SENSORS_LPS22HB),y)
+ CSRCS += lps22hb_uorb.c
+endif
+
ifeq ($(CONFIG_SENSORS_LPS25H),y)
CSRCS += lps25h.c
endif
diff --git a/drivers/sensors/lps22hb_uorb.c b/drivers/sensors/lps22hb_uorb.c
new file mode 100644
index 00000000000..e0b0819e78a
--- /dev/null
+++ b/drivers/sensors/lps22hb_uorb.c
@@ -0,0 +1,446 @@
+/****************************************************************************
+ * drivers/sensors/lps22hb_uorb.c
+ *
+ * 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 <debug.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <nuttx/nuttx.h>
+#include <nuttx/kmalloc.h>
+#include <nuttx/random.h>
+#include <nuttx/signal.h>
+#include <nuttx/i2c/i2c_master.h>
+#include <nuttx/sensors/sensor.h>
+#include <nuttx/sensors/lps22hb.h>
+
+/****************************************************************************
+ * Pre-Processor Definitions
+ ****************************************************************************/
+
+/* Registers */
+
+#define LPS22HB_INTERRUPT_CFG (0x0b)
+#define LPS22HB_THS_P_L (0x0c)
+#define LPS22HB_THS_P_H (0x0d)
+#define LPS22HB_WHO_AM_I (0x0f)
+#define LPS22HB_CTRL_REG1 (0x10)
+#define LPS22HB_CTRL_REG2 (0x11)
+#define LPS22HB_CTRL_REG3 (0x12)
+#define LPS22HB_FIFO_CTRL (0x14)
+#define LPS22HB_REF_P_XL (0x15)
+#define LPS22HB_REF_P_L (0x16)
+#define LPS22HB_REF_P_H (0x17)
+#define LPS22HB_RPDS_L (0x18)
+#define LPS22HB_RPDS_H (0x19)
+#define LPS22HB_RES_CONF (0x1a)
+#define LPS22HB_INT_SOURCE (0x25)
+#define LPS22HB_FIFO_STATUS (0x26)
+#define LPS22HB_STATUS (0x27)
+#define LPS22HB_PRESS_OUT_XL (0x28)
+#define LPS22HB_PRESS_OUT_L (0x29)
+#define LPS22HB_PRESS_OUT_H (0x2a)
+#define LPS22HB_TEMP_OUT_L (0x2b)
+#define LPS22HB_TEMP_OUT_H (0x2c)
+#define LPS22HB_LPFP_RES (0x33)
+
+/* WHO_AM_I value */
+
+#define LPS22HB_DEVID (0xb1)
+
+/* CTRL_REG1 bits */
+
+#define LPS22HB_CTRL_REG1_BDU (1 << 1)
+
+/* CTRL_REG2 bits */
+
+#define LPS22HB_CTRL_REG2_ONE_SHOT (1 << 0)
+#define LPS22HB_CTRL_REG2_IF_ADD_INC (1 << 4)
+
+/* STATUS bits */
+
+#define LPS22HB_STATUS_P_DA (1 << 0)
+#define LPS22HB_STATUS_T_DA (1 << 1)
+
+/* Sensitivity: pressure 4096 LSB/hPa, temperature 100 LSB/degC */
+
+#define LPS22HB_PRESS_DIVIDER (4096)
+#define LPS22HB_TEMP_DIVIDER (100)
+
+/* One-shot conversion timeout */
+
+#define LPS22HB_ONE_SHOT_RETRIES 10
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct lps22hb_dev_s
+{
+ FAR struct sensor_lowerhalf_s lower; /* Lower-half sensor driver */
+ FAR struct i2c_master_s *i2c; /* I2C interface */
+ uint8_t addr; /* I2C address */
+ bool enabled; /* Sensor activated */
+ unsigned long interval; /* Polling interval in us */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int lps22hb_read_reg(FAR struct lps22hb_dev_s *priv, uint8_t regaddr,
+ FAR uint8_t *regval);
+static int lps22hb_write_reg(FAR struct lps22hb_dev_s *priv, uint8_t regaddr,
+ uint8_t regval);
+static int lps22hb_read_regs(FAR struct lps22hb_dev_s *priv, uint8_t regaddr,
+ FAR uint8_t *regvals, int len);
+static int lps22hb_checkid(FAR struct lps22hb_dev_s *priv);
+static int lps22hb_measure(FAR struct lps22hb_dev_s *priv,
+ FAR struct sensor_baro *baro);
+
+/* Sensor lower-half operations */
+
+static int lps22hb_activate(FAR struct sensor_lowerhalf_s *lower,
+ FAR struct file *filep, bool enable);
+static int lps22hb_set_interval(FAR struct sensor_lowerhalf_s *lower,
+ FAR struct file *filep,
+ FAR uint32_t *period_us);
+static int lps22hb_fetch(FAR struct sensor_lowerhalf_s *lower,
+ FAR struct file *filep, FAR char *buffer,
+ size_t buflen);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct sensor_ops_s g_lps22hb_ops =
+{
+ .activate = lps22hb_activate,
+ .set_interval = lps22hb_set_interval,
+ .fetch = lps22hb_fetch,
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: lps22hb_read_reg
+ ****************************************************************************/
+
+static int lps22hb_read_reg(FAR struct lps22hb_dev_s *priv, uint8_t regaddr,
+ FAR uint8_t *regval)
+{
+ return lps22hb_read_regs(priv, regaddr, regval, 1);
+}
+
+/****************************************************************************
+ * Name: lps22hb_read_regs
+ *
+ * Description:
+ * Read a block of registers. The LPS22HB auto-increments the register
+ * address on multi-byte reads (IF_ADD_INC is set by default).
+ *
+ ****************************************************************************/
+
+static int lps22hb_read_regs(FAR struct lps22hb_dev_s *priv, uint8_t regaddr,
+ FAR uint8_t *regvals, int len)
+{
+ struct i2c_config_s config;
+
+ config.frequency = CONFIG_LPS22HB_I2C_FREQUENCY;
+ config.address = priv->addr;
+ config.addrlen = 7;
+
+ return i2c_writeread(priv->i2c, &config, ®addr, 1, regvals, len);
+}
+
+/****************************************************************************
+ * Name: lps22hb_write_reg
+ ****************************************************************************/
+
+static int lps22hb_write_reg(FAR struct lps22hb_dev_s *priv, uint8_t regaddr,
+ uint8_t regval)
+{
+ struct i2c_config_s config;
+ uint8_t buf[2];
+
+ config.frequency = CONFIG_LPS22HB_I2C_FREQUENCY;
+ config.address = priv->addr;
+ config.addrlen = 7;
+
+ buf[0] = regaddr;
+ buf[1] = regval;
+
+ return i2c_write(priv->i2c, &config, buf, 2);
+}
+
+/****************************************************************************
+ * Name: lps22hb_checkid
+ *
+ * Description:
+ * Read and verify the LPS22HB chip ID
+ *
+ ****************************************************************************/
+
+static int lps22hb_checkid(FAR struct lps22hb_dev_s *priv)
+{
+ uint8_t devid = 0;
+ int ret;
+
+ ret = lps22hb_read_reg(priv, LPS22HB_WHO_AM_I, &devid);
+ if (ret < 0)
+ {
+ return ret;
+ }
+
+ if (devid != LPS22HB_DEVID)
+ {
+ snerr("ERROR: Wrong device ID: 0x%02x\n", devid);
+ return -ENODEV;
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: lps22hb_measure
+ *
+ * Description:
+ * Trigger a one-shot measurement and read pressure and temperature.
+ *
+ ****************************************************************************/
+
+static int lps22hb_measure(FAR struct lps22hb_dev_s *priv,
+ FAR struct sensor_baro *baro)
+{
+ uint8_t data[5];
+ uint8_t regval;
+ int32_t press_raw;
+ int16_t temp_raw;
+ int retries = LPS22HB_ONE_SHOT_RETRIES;
+ int whole;
+ int frac;
+ int ret;
+
+ /* Enable block data update and set one-shot (ODR = 0) mode */
+
+ ret = lps22hb_write_reg(priv, LPS22HB_CTRL_REG1, LPS22HB_CTRL_REG1_BDU);
+ if (ret < 0)
+ {
+ return ret;
+ }
+
+ /* Trigger a one-shot conversion. Keep IF_ADD_INC set so that the burst
+ * read below auto-increments the register address.
+ */
+
+ ret = lps22hb_write_reg(priv, LPS22HB_CTRL_REG2,
+ LPS22HB_CTRL_REG2_IF_ADD_INC |
+ LPS22HB_CTRL_REG2_ONE_SHOT);
+ if (ret < 0)
+ {
+ return ret;
+ }
+
+ /* Wait for pressure and temperature data to be available */
+
+ do
+ {
+ nxsig_usleep(5000);
+ ret = lps22hb_read_reg(priv, LPS22HB_STATUS, ®val);
+ if (ret < 0)
+ {
+ return ret;
+ }
+ }
+ while (((regval & (LPS22HB_STATUS_P_DA | LPS22HB_STATUS_T_DA)) !=
+ (LPS22HB_STATUS_P_DA | LPS22HB_STATUS_T_DA)) && --retries);
+
+ if (retries == 0)
+ {
+ snerr("ERROR: LPS22HB conversion timeout\n");
+ return -ETIMEDOUT;
+ }
+
+ /* Burst read pressure (3 bytes) and temperature (2 bytes) */
+
+ ret = lps22hb_read_regs(priv, LPS22HB_PRESS_OUT_XL, data, 5);
+ if (ret < 0)
+ {
+ return ret;
+ }
+
+ press_raw = data[2] << 16 | data[1] << 8 | data[0];
+
+ /* Sign-extend the 24-bit pressure value */
+
+ if (press_raw & 0x00800000)
+ {
+ press_raw |= 0xff000000;
+ }
+
+ temp_raw = data[4] << 8 | data[3];
+
+ add_sensor_randomness(press_raw ^ temp_raw);
+
+ /* Pressure is a 24-bit count in 1/4096 hPa. Split the integer and
+ * fractional hPa so that the operands stay within the b16 range.
+ */
+
+ whole = press_raw / LPS22HB_PRESS_DIVIDER;
+ frac = press_raw % LPS22HB_PRESS_DIVIDER;
+
+ baro->timestamp = sensor_get_timestamp();
+ baro->pressure =
+ sensor_data_add(sensor_data_itof(whole),
+ sensor_data_divi(sensor_data_itof(frac),
+ LPS22HB_PRESS_DIVIDER));
+ baro->temperature = sensor_data_divi(sensor_data_itof(temp_raw),
+ LPS22HB_TEMP_DIVIDER);
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: lps22hb_activate
+ ****************************************************************************/
+
+static int lps22hb_activate(FAR struct sensor_lowerhalf_s *lower,
+ FAR struct file *filep, bool enable)
+{
+ FAR struct lps22hb_dev_s *priv =
+ container_of(lower, FAR struct lps22hb_dev_s, lower);
+
+ priv->enabled = enable;
+ return OK;
+}
+
+/****************************************************************************
+ * Name: lps22hb_set_interval
+ ****************************************************************************/
+
+static int lps22hb_set_interval(FAR struct sensor_lowerhalf_s *lower,
+ FAR struct file *filep,
+ FAR uint32_t *period_us)
+{
+ FAR struct lps22hb_dev_s *priv =
+ container_of(lower, FAR struct lps22hb_dev_s, lower);
+
+ priv->interval = *period_us;
+ return OK;
+}
+
+/****************************************************************************
+ * Name: lps22hb_fetch
+ ****************************************************************************/
+
+static int lps22hb_fetch(FAR struct sensor_lowerhalf_s *lower,
+ FAR struct file *filep, FAR char *buffer,
+ size_t buflen)
+{
+ FAR struct lps22hb_dev_s *priv =
+ container_of(lower, FAR struct lps22hb_dev_s, lower);
+ struct sensor_baro baro;
+ int ret;
+
+ if (buflen != sizeof(baro))
+ {
+ return -EINVAL;
+ }
+
+ ret = lps22hb_measure(priv, &baro);
+ if (ret < 0)
+ {
+ return ret;
+ }
+
+ memcpy(buffer, &baro, sizeof(baro));
+ return sizeof(baro);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: lps22hb_register_uorb
+ *
+ * Description:
+ * Register the LPS22HB barometer sensor as a UORB device.
+ *
+ * Input Parameters:
+ * devno - The device number, used to build the device path.
+ * i2c - The I2C bus driver instance.
+ * addr - The I2C address of the LPS22HB.
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+int lps22hb_register_uorb(int devno, FAR struct i2c_master_s *i2c,
+ uint8_t addr)
+{
+ FAR struct lps22hb_dev_s *priv;
+ int ret;
+
+ DEBUGASSERT(i2c != NULL);
+
+ priv = kmm_zalloc(sizeof(struct lps22hb_dev_s));
+ if (priv == NULL)
+ {
+ snerr("ERROR: Failed to allocate LPS22HB instance\n");
+ return -ENOMEM;
+ }
+
+ priv->i2c = i2c;
+ priv->addr = addr;
+ priv->interval = 1000000;
+ priv->lower.ops = &g_lps22hb_ops;
+ priv->lower.type = SENSOR_TYPE_BAROMETER;
+
+ /* Probe the device */
+
+ ret = lps22hb_checkid(priv);
+ if (ret < 0)
+ {
+ snerr("ERROR: Failed to identify LPS22HB: %d\n", ret);
+ kmm_free(priv);
+ return ret;
+ }
+
+ ret = sensor_register(&priv->lower, devno);
+ if (ret < 0)
+ {
+ snerr("ERROR: Failed to register LPS22HB driver: %d\n", ret);
+ kmm_free(priv);
+ return ret;
+ }
+
+ sninfo("LPS22HB registered\n");
+ return OK;
+}
diff --git a/include/nuttx/sensors/lps22hb.h b/include/nuttx/sensors/lps22hb.h
new file mode 100644
index 00000000000..1d0d6f9ab30
--- /dev/null
+++ b/include/nuttx/sensors/lps22hb.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+ * include/nuttx/sensors/lps22hb.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_LPS22HB_H
+#define __INCLUDE_NUTTX_SENSORS_LPS22HB_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/i2c/i2c_master.h>
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/****************************************************************************
+ * Name: lps22hb_register_uorb
+ *
+ * Description:
+ * Register the LPS22HB barometer sensor as a UORB device.
+ *
+ * Input Parameters:
+ * devno - The device number, used to build the device path.
+ * i2c - The I2C bus driver instance.
+ * addr - The I2C address of the LPS22HB.
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+int lps22hb_register_uorb(int devno, FAR struct i2c_master_s *i2c,
+ uint8_t addr);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INCLUDE_NUTTX_SENSORS_LPS22HB_H */