This is an automated email from the ASF dual-hosted git repository.
acassis 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 9199e5aa286 sensors/adxl367: add I2C accelerometer support
9199e5aa286 is described below
commit 9199e5aa28641993bf012d8b006afea53f7b670f
Author: raiden00pl <[email protected]>
AuthorDate: Mon Sep 21 12:36:34 2026 +0200
sensors/adxl367: add I2C accelerometer support
add adxl367 support
Assisted-by: Codex:GPT-6
Signed-off-by: raiden00pl <[email protected]>
---
.../components/drivers/special/sensors.rst | 1 +
.../components/drivers/special/sensors/adxl367.rst | 12 +
.../drivers/special/sensors/sensors_uorb.rst | 1 +
drivers/sensors/CMakeLists.txt | 4 +
drivers/sensors/Kconfig | 9 +
drivers/sensors/Make.defs | 4 +
drivers/sensors/adxl367.c | 420 +++++++++++++++++++++
include/nuttx/sensors/adxl367.h | 68 ++++
8 files changed, 519 insertions(+)
diff --git a/Documentation/components/drivers/special/sensors.rst
b/Documentation/components/drivers/special/sensors.rst
index 9cd4ee931fc..439acdfde86 100644
--- a/Documentation/components/drivers/special/sensors.rst
+++ b/Documentation/components/drivers/special/sensors.rst
@@ -27,6 +27,7 @@ tool for monitoring sensor activity at runtime.
sensors/adt7320.rst
sensors/adxl345.rst
sensors/adxl362.rst
+ sensors/adxl367.rst
sensors/adxl372.rst
sensors/aht10.rst
sensors/ak09912.rst
diff --git a/Documentation/components/drivers/special/sensors/adxl367.rst
b/Documentation/components/drivers/special/sensors/adxl367.rst
new file mode 100644
index 00000000000..431a5d8866f
--- /dev/null
+++ b/Documentation/components/drivers/special/sensors/adxl367.rst
@@ -0,0 +1,12 @@
+ADXL367 Accelerometer
+=====================
+
+The ADXL367 driver provides I2C accelerometer support through the sensor
+framework (uORB). It reports three-axis acceleration at a fixed range of
++/-2 g and die temperature, with output data rates from 12.5 to 400 Hz.
+
+Enable ``CONFIG_SENSORS_ADXL367`` and register an instance with
+``adxl367_register()`` from ``<nuttx/sensors/adxl367.h>``. The function accepts
+a device number, an I2C interface, and the sensor address (``0x1d`` or
``0x53``).
+Samples are read on demand through ``/dev/uorb/sensor_accelN``, where ``N`` is
+the device number.
diff --git a/Documentation/components/drivers/special/sensors/sensors_uorb.rst
b/Documentation/components/drivers/special/sensors/sensors_uorb.rst
index fbccd910baf..e2dc8a40639 100644
--- a/Documentation/components/drivers/special/sensors/sensors_uorb.rst
+++ b/Documentation/components/drivers/special/sensors/sensors_uorb.rst
@@ -530,6 +530,7 @@ Implemented Drivers
===================
- :doc:`adxl362`
+- :doc:`adxl367`
- :doc:`adxl372`
- bh1749nuc
- bme680
diff --git a/drivers/sensors/CMakeLists.txt b/drivers/sensors/CMakeLists.txt
index 53f8d38b581..58fc93c6d54 100644
--- a/drivers/sensors/CMakeLists.txt
+++ b/drivers/sensors/CMakeLists.txt
@@ -384,6 +384,10 @@ if(CONFIG_SENSORS)
list(APPEND SRCS adxl362_uorb.c)
endif()
+ if(CONFIG_SENSORS_ADXL367)
+ list(APPEND SRCS adxl367.c)
+ endif()
+
if(CONFIG_SENSORS_ADXL372)
if(CONFIG_SENSORS_ADXL372_UORB)
list(APPEND SRCS adxl372_uorb.c)
diff --git a/drivers/sensors/Kconfig b/drivers/sensors/Kconfig
index 8e08788fe7f..0335bfd7bc0 100644
--- a/drivers/sensors/Kconfig
+++ b/drivers/sensors/Kconfig
@@ -1507,6 +1507,15 @@ config SENSORS_ADXL362_THREAD_STACKSIZE
endif # SENSORS_ADXL362
+config SENSORS_ADXL367
+ bool "Analog Devices ADXL367 accelerometer"
+ default n
+ select I2C
+ ---help---
+ Enable the ADXL367 I2C accelerometer driver using the sensor
+ framework. Supports +/-2 g acceleration and die temperature,
+ with output data rates from 12.5 to 400 Hz.
+
config SENSORS_ADXL372
bool "Analog Devices ADXL372 Sensor support"
default n
diff --git a/drivers/sensors/Make.defs b/drivers/sensors/Make.defs
index 9ad42cb74ee..c3627e43be2 100644
--- a/drivers/sensors/Make.defs
+++ b/drivers/sensors/Make.defs
@@ -372,6 +372,10 @@ ifeq ($(CONFIG_SENSORS_ADXL362),y)
CSRCS += adxl362_uorb.c
endif
+ifeq ($(CONFIG_SENSORS_ADXL367),y)
+ CSRCS += adxl367.c
+endif
+
ifeq ($(CONFIG_SENSORS_ADXL372),y)
ifeq ($(CONFIG_SENSORS_ADXL372_UORB),y)
CSRCS += adxl372_uorb.c
diff --git a/drivers/sensors/adxl367.c b/drivers/sensors/adxl367.c
new file mode 100644
index 00000000000..b519b7552ed
--- /dev/null
+++ b/drivers/sensors/adxl367.c
@@ -0,0 +1,420 @@
+/****************************************************************************
+ * drivers/sensors/adxl367.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 <string.h>
+#include <sys/param.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/mutex.h>
+#include <nuttx/signal.h>
+#include <nuttx/sensors/adxl367.h>
+#include <nuttx/sensors/sensor.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define ADXL367_I2C_FREQUENCY 100000
+#define ADXL367_DEVID_AD 0x00
+#define ADXL367_DEVID_AD_VALUE 0xad
+#define ADXL367_DEVID_MST_VALUE 0x1d
+#define ADXL367_PARTID_VALUE 0xf7
+#define ADXL367_STATUS 0x0b
+#define ADXL367_STATUS_DATA_READY (1 << 0)
+#define ADXL367_XDATA_H 0x0e
+#define ADXL367_SOFT_RESET 0x1f
+#define ADXL367_SOFT_RESET_VALUE 0x52
+#define ADXL367_FILTER_CTL 0x2c
+#define ADXL367_POWER_CTL 0x2d
+#define ADXL367_POWER_MEASURE 2
+#define ADXL367_TEMP_CTL 0x3d
+#define ADXL367_TEMP_ENABLE (1 << 0)
+#define ADXL367_DEFAULT_ODR 3
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct adxl367_dev_s
+{
+ struct sensor_lowerhalf_s lower;
+ FAR struct i2c_master_s *i2c;
+ mutex_t lock;
+ uint8_t addr;
+ uint8_t odr;
+ bool enabled;
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int adxl367_activate(FAR struct sensor_lowerhalf_s *lower,
+ FAR struct file *filep, bool enable);
+static int adxl367_set_interval(FAR struct sensor_lowerhalf_s *lower,
+ FAR struct file *filep,
+ FAR uint32_t *period_us);
+static int adxl367_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_adxl367_ops =
+{
+ .activate = adxl367_activate,
+ .set_interval = adxl367_set_interval,
+ .fetch = adxl367_fetch,
+};
+
+static const uint32_t g_adxl367_periods[] =
+{
+ 80000, 40000, 20000, 10000, 5000, 2500
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: adxl367_getregs
+ ****************************************************************************/
+
+static int adxl367_getregs(FAR struct adxl367_dev_s *priv, uint8_t reg,
+ FAR uint8_t *buffer, int len)
+{
+ struct i2c_msg_s msg[2] =
+ {
+ {
+ .frequency = ADXL367_I2C_FREQUENCY,
+ .addr = priv->addr,
+ .flags = I2C_M_NOSTOP,
+ .buffer = ®,
+ .length = 1,
+ },
+ {
+ .frequency = ADXL367_I2C_FREQUENCY,
+ .addr = priv->addr,
+ .flags = I2C_M_READ,
+ .buffer = buffer,
+ .length = len,
+ }
+ };
+
+ int ret = I2C_TRANSFER(priv->i2c, msg, 2);
+
+ return ret < 0 ? ret : OK;
+}
+
+/****************************************************************************
+ * Name: adxl367_putreg
+ ****************************************************************************/
+
+static int adxl367_putreg(FAR struct adxl367_dev_s *priv, uint8_t reg,
+ uint8_t value)
+{
+ uint8_t buffer[2];
+ struct i2c_config_s config =
+ {
+ .frequency = ADXL367_I2C_FREQUENCY,
+ .address = priv->addr,
+ .addrlen = 7,
+ };
+
+ int ret;
+
+ buffer[0] = reg;
+ buffer[1] = value;
+ ret = i2c_write(priv->i2c, &config, buffer, sizeof(buffer));
+
+ return ret < 0 ? ret : OK;
+}
+
+/****************************************************************************
+ * Name: adxl367_set_power
+ ****************************************************************************/
+
+static int adxl367_set_power(FAR struct adxl367_dev_s *priv, bool enable)
+{
+ int ret;
+
+ ret = adxl367_putreg(priv, ADXL367_POWER_CTL,
+ enable ? ADXL367_POWER_MEASURE : 0);
+ if (ret == OK)
+ {
+ priv->enabled = enable;
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: adxl367_activate
+ ****************************************************************************/
+
+static int adxl367_activate(FAR struct sensor_lowerhalf_s *lower,
+ FAR struct file *filep, bool enable)
+{
+ FAR struct adxl367_dev_s *priv = (FAR struct adxl367_dev_s *)lower;
+ int ret;
+
+ ret = nxmutex_lock(&priv->lock);
+ if (ret < 0)
+ {
+ return ret;
+ }
+
+ ret = adxl367_set_power(priv, enable);
+ nxmutex_unlock(&priv->lock);
+ return ret;
+}
+
+/****************************************************************************
+ * Name: adxl367_set_interval
+ ****************************************************************************/
+
+static int adxl367_set_interval(FAR struct sensor_lowerhalf_s *lower,
+ FAR struct file *filep,
+ FAR uint32_t *period_us)
+{
+ FAR struct adxl367_dev_s *priv = (FAR struct adxl367_dev_s *)lower;
+ bool enabled;
+ uint8_t odr = 0;
+ int ret;
+ int restore;
+
+ ret = nxmutex_lock(&priv->lock);
+ if (ret < 0)
+ {
+ return ret;
+ }
+
+ enabled = priv->enabled;
+
+ while (odr < nitems(g_adxl367_periods) - 1 &&
+ *period_us < g_adxl367_periods[odr])
+ {
+ odr++;
+ }
+
+ if (odr == priv->odr)
+ {
+ *period_us = g_adxl367_periods[odr];
+ goto out;
+ }
+
+ /* FILTER_CTL must only be changed in standby. Keep the range at +/-2 g
+ * and disable the nonstandard high speed I2C mode.
+ */
+
+ ret = adxl367_set_power(priv, false);
+ if (ret < 0)
+ {
+ goto out;
+ }
+
+ ret = adxl367_putreg(priv, ADXL367_FILTER_CTL, odr);
+ if (ret == OK)
+ {
+ priv->odr = odr;
+ *period_us = g_adxl367_periods[odr];
+ }
+
+ if (enabled)
+ {
+ restore = adxl367_set_power(priv, true);
+ if (ret == OK)
+ {
+ ret = restore;
+ }
+ }
+
+out:
+ nxmutex_unlock(&priv->lock);
+ return ret;
+}
+
+/****************************************************************************
+ * Name: adxl367_data
+ ****************************************************************************/
+
+static int16_t adxl367_data(FAR const uint8_t *data)
+{
+ return (int16_t)((data[0] << 8) | data[1]) / 4;
+}
+
+/****************************************************************************
+ * Name: adxl367_fetch
+ ****************************************************************************/
+
+static int adxl367_fetch(FAR struct sensor_lowerhalf_s *lower,
+ FAR struct file *filep, FAR char *buffer,
+ size_t buflen)
+{
+ FAR struct adxl367_dev_s *priv = (FAR struct adxl367_dev_s *)lower;
+ struct sensor_accel sample;
+ uint8_t data[8];
+ uint8_t status;
+ int ret;
+
+ if (buflen < sizeof(sample))
+ {
+ return -EINVAL;
+ }
+
+ ret = nxmutex_lock(&priv->lock);
+ if (ret < 0)
+ {
+ return ret;
+ }
+
+ ret = adxl367_getregs(priv, ADXL367_STATUS, &status, 1);
+ if (ret < 0)
+ {
+ goto out;
+ }
+
+ if (!(status & ADXL367_STATUS_DATA_READY))
+ {
+ ret = -EAGAIN;
+ goto out;
+ }
+
+ ret = adxl367_getregs(priv, ADXL367_XDATA_H, data, sizeof(data));
+ if (ret < 0)
+ {
+ goto out;
+ }
+
+ sample.timestamp = sensor_get_timestamp();
+ sample.x = sensor_data_muli(sensor_data_ftof(9.80665f / 4000),
+ adxl367_data(&data[0]));
+ sample.y = sensor_data_muli(sensor_data_ftof(9.80665f / 4000),
+ adxl367_data(&data[2]));
+ sample.z = sensor_data_muli(sensor_data_ftof(9.80665f / 4000),
+ adxl367_data(&data[4]));
+
+ /* Typical uncalibrated temperature: 165 LSB at 25 C, 54 LSB/C. */
+
+ sample.temperature =
+ sensor_data_add(sensor_data_ftof(25.0f),
+ sensor_data_divi(
+ sensor_data_itof(adxl367_data(&data[6]) - 165),
+ 54));
+ memcpy(buffer, &sample, sizeof(sample));
+ ret = sizeof(sample);
+
+out:
+ nxmutex_unlock(&priv->lock);
+ return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: adxl367_register
+ ****************************************************************************/
+
+int adxl367_register(int devno, FAR struct i2c_master_s *i2c, uint8_t addr)
+{
+ FAR struct adxl367_dev_s *priv;
+ uint8_t id[3];
+ int ret;
+
+ if (i2c == NULL || (addr != 0x1d && addr != 0x53))
+ {
+ return -EINVAL;
+ }
+
+ priv = kmm_zalloc(sizeof(*priv));
+ if (priv == NULL)
+ {
+ return -ENOMEM;
+ }
+
+ priv->i2c = i2c;
+ priv->addr = addr;
+ priv->odr = ADXL367_DEFAULT_ODR;
+ priv->lower.ops = &g_adxl367_ops;
+ priv->lower.type = SENSOR_TYPE_ACCELEROMETER;
+ nxmutex_init(&priv->lock);
+
+ /* Allow power-up to standby before the first bus access. */
+
+ nxsig_usleep(10000);
+ ret = adxl367_getregs(priv, ADXL367_DEVID_AD, id, sizeof(id));
+ if (ret < 0)
+ {
+ goto errout;
+ }
+
+ if (id[0] != ADXL367_DEVID_AD_VALUE ||
+ id[1] != ADXL367_DEVID_MST_VALUE ||
+ id[2] != ADXL367_PARTID_VALUE)
+ {
+ ret = -ENODEV;
+ goto errout;
+ }
+
+ ret = adxl367_putreg(priv, ADXL367_SOFT_RESET, ADXL367_SOFT_RESET_VALUE);
+ if (ret < 0)
+ {
+ goto errout;
+ }
+
+ nxsig_usleep(10000);
+ ret = adxl367_putreg(priv, ADXL367_FILTER_CTL, priv->odr);
+ if (ret < 0)
+ {
+ goto errout;
+ }
+
+ ret = adxl367_putreg(priv, ADXL367_TEMP_CTL, ADXL367_TEMP_ENABLE);
+ if (ret < 0)
+ {
+ goto errout;
+ }
+
+ ret = sensor_register(&priv->lower, devno);
+ if (ret < 0)
+ {
+ goto errout;
+ }
+
+ return OK;
+
+errout:
+ nxmutex_destroy(&priv->lock);
+ kmm_free(priv);
+ return ret;
+}
diff --git a/include/nuttx/sensors/adxl367.h b/include/nuttx/sensors/adxl367.h
new file mode 100644
index 00000000000..2be8d7638a6
--- /dev/null
+++ b/include/nuttx/sensors/adxl367.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+ * include/nuttx/sensors/adxl367.h
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+#ifndef __INCLUDE_NUTTX_SENSORS_ADXL367_H
+#define __INCLUDE_NUTTX_SENSORS_ADXL367_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/i2c/i2c_master.h>
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Name: adxl367_register
+ *
+ * Description:
+ * Register the ADXL367 character device as uorb
+ *
+ * Input Parameters:
+ * devno - device instance
+ * i2c - An instance of the I2C interface to use to communicate with
+ * ADXL367
+ * addr - I2C address (0x1d or 0x53).
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+int adxl367_register(int devno, FAR struct i2c_master_s *i2c, uint8_t addr);
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INCLUDE_NUTTX_SENSORS_ADXL367_H */