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, &regaddr, 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, &regval);
+      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 */

Reply via email to