drivers/sensors: Add iis2dh accelerometer sensor support
Add support to STM IIS2DH the ultra-low-power highperformance three-axis linear accelerometer. Signed-off-by: Armando Visconti <armando.visconti@st.com>
This commit is contained in:
parent
126a5678a6
commit
485f2d410c
16 changed files with 954 additions and 0 deletions
|
@ -27,6 +27,7 @@ add_subdirectory_ifdef(CONFIG_TI_HDC ti_hdc)
|
|||
add_subdirectory_ifdef(CONFIG_HMC5883L hmc5883l)
|
||||
add_subdirectory_ifdef(CONFIG_HP206C hp206c)
|
||||
add_subdirectory_ifdef(CONFIG_HTS221 hts221)
|
||||
add_subdirectory_ifdef(CONFIG_IIS2DH iis2dh)
|
||||
add_subdirectory_ifdef(CONFIG_IIS2DLPC iis2dlpc)
|
||||
add_subdirectory_ifdef(CONFIG_IIS2MDC iis2mdc)
|
||||
add_subdirectory_ifdef(CONFIG_IIS3DHHC iis3dhhc)
|
||||
|
|
|
@ -83,6 +83,8 @@ source "drivers/sensor/hp206c/Kconfig"
|
|||
|
||||
source "drivers/sensor/hts221/Kconfig"
|
||||
|
||||
source "drivers/sensor/iis2dh/Kconfig"
|
||||
|
||||
source "drivers/sensor/iis2dlpc/Kconfig"
|
||||
|
||||
source "drivers/sensor/iis2mdc/Kconfig"
|
||||
|
|
12
drivers/sensor/iis2dh/CMakeLists.txt
Normal file
12
drivers/sensor/iis2dh/CMakeLists.txt
Normal file
|
@ -0,0 +1,12 @@
|
|||
# ST Microelectronics IIS2DH 3-axis accelerometer driver
|
||||
#
|
||||
# Copyright (c) 2020 STMicroelectronics
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
zephyr_library()
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_IIS2DH iis2dh)
|
||||
zephyr_library_sources_ifdef(CONFIG_IIS2DH iis2dh_i2c.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_IIS2DH iis2dh_spi.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_IIS2DH_TRIGGER iis2dh_trigger.c)
|
97
drivers/sensor/iis2dh/Kconfig
Normal file
97
drivers/sensor/iis2dh/Kconfig
Normal file
|
@ -0,0 +1,97 @@
|
|||
# ST Microelectronics IIS2DH 3-axis accelerometer driver
|
||||
|
||||
# Copyright (c) 2020 STMicroelectronics
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
menuconfig IIS2DH
|
||||
bool "IIS2DH I2C/SPI accelerometer sensor driver"
|
||||
depends on (I2C && HAS_DTS_I2C) || SPI
|
||||
select HAS_STMEMSC
|
||||
select USE_STDC_IIS2DH
|
||||
help
|
||||
Enable driver for IIS2DH accelerometer sensor driver
|
||||
|
||||
if IIS2DH
|
||||
|
||||
choice IIS2DH_TRIGGER_MODE
|
||||
prompt "Trigger mode"
|
||||
help
|
||||
Specify the type of triggering to be used by the driver.
|
||||
|
||||
config IIS2DH_TRIGGER_NONE
|
||||
bool "No trigger"
|
||||
|
||||
config IIS2DH_TRIGGER_GLOBAL_THREAD
|
||||
bool "Use global thread"
|
||||
depends on GPIO
|
||||
select IIS2DH_TRIGGER
|
||||
|
||||
config IIS2DH_TRIGGER_OWN_THREAD
|
||||
bool "Use own thread"
|
||||
depends on GPIO
|
||||
select IIS2DH_TRIGGER
|
||||
|
||||
endchoice
|
||||
|
||||
config IIS2DH_TRIGGER
|
||||
bool
|
||||
|
||||
if IIS2DH_TRIGGER
|
||||
|
||||
config IIS2DH_THREAD_PRIORITY
|
||||
int "Thread priority"
|
||||
depends on IIS2DH_TRIGGER_OWN_THREAD
|
||||
default 10
|
||||
help
|
||||
Priority of thread used by the driver to handle interrupts.
|
||||
|
||||
config IIS2DH_THREAD_STACK_SIZE
|
||||
int "Thread stack size"
|
||||
depends on IIS2DH_TRIGGER_OWN_THREAD
|
||||
default 1024
|
||||
help
|
||||
Stack size of thread used by the driver to handle interrupts.
|
||||
|
||||
endif # IIS2DH_TRIGGER
|
||||
|
||||
config IIS2DH_RANGE
|
||||
int "Accelerometer Full-scale range setting"
|
||||
default 0
|
||||
help
|
||||
Specify the default accelerometer full-scale range.
|
||||
Valid values are:
|
||||
0: Full Scale selected at runtime
|
||||
2: +/- 2g
|
||||
4: +/- 4g
|
||||
8: +/- 8g
|
||||
16: +/- 16g
|
||||
|
||||
config IIS2DH_ODR
|
||||
int "Accelerometer sampling frequency (ODR)"
|
||||
range 0 9
|
||||
default 0
|
||||
help
|
||||
Specify the default accelerometer output data rate expressed in
|
||||
samples per second (Hz).
|
||||
0: ODR selected at runtime
|
||||
1: 1 Hz
|
||||
2: 10 Hz
|
||||
3: 25 Hz
|
||||
4: 50 Hz
|
||||
5: 100 Hz
|
||||
6: 200 Hz
|
||||
7: 400 Hz
|
||||
8: 1620 Hz (only LP)
|
||||
9: Depends by mode. LP: 5376 Hz - NORM or HR: 1344 Hz
|
||||
|
||||
config IIS2DH_POWER_MODE
|
||||
int "Sensor Power Modes"
|
||||
range 0 2
|
||||
default 0
|
||||
help
|
||||
Specify the sensor power mode
|
||||
0: High Resolution mode
|
||||
1: Normal mode
|
||||
2: Low Power mode
|
||||
|
||||
endif # IIS2DH
|
315
drivers/sensor/iis2dh/iis2dh.c
Normal file
315
drivers/sensor/iis2dh/iis2dh.c
Normal file
|
@ -0,0 +1,315 @@
|
|||
/* ST Microelectronics IIS2DH 3-axis accelerometer driver
|
||||
*
|
||||
* Copyright (c) 2020 STMicroelectronics
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Datasheet:
|
||||
* https://www.st.com/resource/en/datasheet/iis2dh.pdf
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT st_iis2dh
|
||||
|
||||
#include <init.h>
|
||||
#include <sys/__assert.h>
|
||||
#include <sys/byteorder.h>
|
||||
#include <logging/log.h>
|
||||
#include <drivers/sensor.h>
|
||||
|
||||
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi)
|
||||
#include <drivers/spi.h>
|
||||
#elif DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c)
|
||||
#include <drivers/i2c.h>
|
||||
#endif
|
||||
|
||||
#include "iis2dh.h"
|
||||
|
||||
LOG_MODULE_REGISTER(IIS2DH, CONFIG_SENSOR_LOG_LEVEL);
|
||||
|
||||
/* gains in uG/LSB */
|
||||
static const uint32_t iis2dh_gain[3][4] = {
|
||||
{
|
||||
/* HR mode */
|
||||
980/16, /* 2G */
|
||||
1950/16, /* 4G */
|
||||
3910/16, /* 8G */
|
||||
11720/16, /* 16G */
|
||||
},
|
||||
{
|
||||
/* NM mode */
|
||||
3910/64, /* 2G */
|
||||
7810/64, /* 4G */
|
||||
15630/64, /* 8G */
|
||||
46950/64, /* 16G */
|
||||
},
|
||||
{
|
||||
/* LP mode */
|
||||
15630/256, /* 2G */
|
||||
31250/256, /* 4G */
|
||||
62500/256, /* 8G */
|
||||
188680/256, /* 16G */
|
||||
},
|
||||
};
|
||||
|
||||
static int iis2dh_set_fs_raw(struct iis2dh_data *iis2dh, uint8_t fs)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = iis2dh_full_scale_set(iis2dh->ctx, fs);
|
||||
|
||||
if (!err) {
|
||||
/* save internally gain for optimization */
|
||||
iis2dh->gain = iis2dh_gain[IIS2DH_HR_12bit][fs];
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
#if (CONFIG_IIS2DH_RANGE == 0)
|
||||
/**
|
||||
* iis2dh_set_range - set full scale range for acc
|
||||
* @dev: Pointer to instance of struct device (I2C or SPI)
|
||||
* @range: Full scale range (2, 4, 8 and 16 G)
|
||||
*/
|
||||
static int iis2dh_set_range(struct device *dev, uint16_t range)
|
||||
{
|
||||
int err;
|
||||
struct iis2dh_data *iis2dh = dev->driver_data;
|
||||
uint8_t fs = IIS2DH_FS_TO_REG(range);
|
||||
|
||||
err = iis2dh_set_fs_raw(iis2dh, fs);
|
||||
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (CONFIG_IIS2DH_ODR == 0)
|
||||
/**
|
||||
* iis2dh_set_odr - set new sampling frequency
|
||||
* @dev: Pointer to instance of struct device (I2C or SPI)
|
||||
* @odr: Output data rate
|
||||
*/
|
||||
static int iis2dh_set_odr(struct device *dev, uint16_t odr)
|
||||
{
|
||||
struct iis2dh_data *iis2dh = dev->driver_data;
|
||||
const struct iis2dh_device_config *cfg = dev->config_info;
|
||||
iis2dh_odr_t val;
|
||||
|
||||
val = IIS2DH_ODR_TO_REG_HR(cfg->pm, odr);
|
||||
|
||||
return iis2dh_data_rate_set(iis2dh->ctx, val);
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void iis2dh_convert(struct sensor_value *val, int raw_val,
|
||||
uint32_t gain)
|
||||
{
|
||||
int64_t dval;
|
||||
|
||||
/* Gain is in ug/LSB */
|
||||
/* Convert to m/s^2 */
|
||||
dval = ((int64_t)raw_val * gain * SENSOR_G) / 1000000LL;
|
||||
val->val1 = dval / 1000000LL;
|
||||
val->val2 = dval % 1000000LL;
|
||||
}
|
||||
|
||||
static inline void iis2dh_channel_get_acc(struct device *dev,
|
||||
enum sensor_channel chan,
|
||||
struct sensor_value *val)
|
||||
{
|
||||
int i;
|
||||
uint8_t ofs_start, ofs_stop;
|
||||
struct iis2dh_data *iis2dh = dev->driver_data;
|
||||
struct sensor_value *pval = val;
|
||||
|
||||
switch (chan) {
|
||||
case SENSOR_CHAN_ACCEL_X:
|
||||
ofs_start = ofs_stop = 0U;
|
||||
break;
|
||||
case SENSOR_CHAN_ACCEL_Y:
|
||||
ofs_start = ofs_stop = 1U;
|
||||
break;
|
||||
case SENSOR_CHAN_ACCEL_Z:
|
||||
ofs_start = ofs_stop = 2U;
|
||||
break;
|
||||
default:
|
||||
ofs_start = 0U; ofs_stop = 2U;
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = ofs_start; i <= ofs_stop ; i++) {
|
||||
iis2dh_convert(pval++, iis2dh->acc[i], iis2dh->gain);
|
||||
}
|
||||
}
|
||||
|
||||
static int iis2dh_channel_get(struct device *dev,
|
||||
enum sensor_channel chan,
|
||||
struct sensor_value *val)
|
||||
{
|
||||
switch (chan) {
|
||||
case SENSOR_CHAN_ACCEL_X:
|
||||
case SENSOR_CHAN_ACCEL_Y:
|
||||
case SENSOR_CHAN_ACCEL_Z:
|
||||
case SENSOR_CHAN_ACCEL_XYZ:
|
||||
iis2dh_channel_get_acc(dev, chan, val);
|
||||
return 0;
|
||||
default:
|
||||
LOG_DBG("Channel not supported");
|
||||
break;
|
||||
}
|
||||
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
static int iis2dh_config(struct device *dev, enum sensor_channel chan,
|
||||
enum sensor_attribute attr,
|
||||
const struct sensor_value *val)
|
||||
{
|
||||
switch (attr) {
|
||||
#if (CONFIG_IIS2DH_RANGE == 0)
|
||||
case SENSOR_ATTR_FULL_SCALE:
|
||||
return iis2dh_set_range(dev, sensor_ms2_to_g(val));
|
||||
#endif
|
||||
#if (CONFIG_IIS2DH_ODR == 0)
|
||||
case SENSOR_ATTR_SAMPLING_FREQUENCY:
|
||||
return iis2dh_set_odr(dev, val->val1);
|
||||
#endif
|
||||
default:
|
||||
LOG_DBG("Acc attribute not supported");
|
||||
break;
|
||||
}
|
||||
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
static int iis2dh_attr_set(struct device *dev, enum sensor_channel chan,
|
||||
enum sensor_attribute attr,
|
||||
const struct sensor_value *val)
|
||||
{
|
||||
switch (chan) {
|
||||
case SENSOR_CHAN_ACCEL_X:
|
||||
case SENSOR_CHAN_ACCEL_Y:
|
||||
case SENSOR_CHAN_ACCEL_Z:
|
||||
case SENSOR_CHAN_ACCEL_XYZ:
|
||||
return iis2dh_config(dev, chan, attr, val);
|
||||
default:
|
||||
LOG_DBG("Attr not supported on %d channel", chan);
|
||||
break;
|
||||
}
|
||||
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
static int iis2dh_sample_fetch(struct device *dev, enum sensor_channel chan)
|
||||
{
|
||||
struct iis2dh_data *iis2dh = dev->driver_data;
|
||||
union axis3bit16_t buf;
|
||||
|
||||
/* fetch raw data sample */
|
||||
if (iis2dh_acceleration_raw_get(iis2dh->ctx, buf.u8bit) < 0) {
|
||||
LOG_DBG("Failed to fetch raw data sample");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
iis2dh->acc[0] = sys_le16_to_cpu(buf.i16bit[0]);
|
||||
iis2dh->acc[1] = sys_le16_to_cpu(buf.i16bit[1]);
|
||||
iis2dh->acc[2] = sys_le16_to_cpu(buf.i16bit[2]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct sensor_driver_api iis2dh_driver_api = {
|
||||
.attr_set = iis2dh_attr_set,
|
||||
#if CONFIG_IIS2DH_TRIGGER
|
||||
.trigger_set = iis2dh_trigger_set,
|
||||
#endif /* CONFIG_IIS2DH_TRIGGER */
|
||||
.sample_fetch = iis2dh_sample_fetch,
|
||||
.channel_get = iis2dh_channel_get,
|
||||
};
|
||||
|
||||
static int iis2dh_init_interface(struct device *dev)
|
||||
{
|
||||
struct iis2dh_data *iis2dh = dev->driver_data;
|
||||
const struct iis2dh_device_config *cfg = dev->config_info;
|
||||
|
||||
iis2dh->bus = device_get_binding(cfg->bus_name);
|
||||
if (!iis2dh->bus) {
|
||||
LOG_DBG("master bus not found: %s", cfg->bus_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi)
|
||||
iis2dh_spi_init(dev);
|
||||
#elif DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c)
|
||||
iis2dh_i2c_init(dev);
|
||||
#else
|
||||
#error "BUS MACRO NOT DEFINED IN DTS"
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iis2dh_init(struct device *dev)
|
||||
{
|
||||
struct iis2dh_data *iis2dh = dev->driver_data;
|
||||
const struct iis2dh_device_config *cfg = dev->config_info;
|
||||
uint8_t wai;
|
||||
|
||||
if (iis2dh_init_interface(dev)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* check chip ID */
|
||||
if (iis2dh_device_id_get(iis2dh->ctx, &wai) < 0) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (wai != IIS2DH_ID) {
|
||||
LOG_ERR("Invalid chip ID: %02x", wai);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (iis2dh_block_data_update_set(iis2dh->ctx, PROPERTY_ENABLE) < 0) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (iis2dh_operating_mode_set(iis2dh->ctx, cfg->pm)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
#if (CONFIG_IIS2DH_ODR != 0)
|
||||
/* set default odr and full scale for acc */
|
||||
if (iis2dh_data_rate_set(iis2dh->ctx, CONFIG_IIS2DH_ODR) < 0) {
|
||||
return -EIO;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (CONFIG_IIS2DH_RANGE != 0)
|
||||
iis2dh_set_fs_raw(iis2dh, CONFIG_IIS2DH_RANGE);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_IIS2DH_TRIGGER
|
||||
if (iis2dh_init_interrupt(dev) < 0) {
|
||||
LOG_ERR("Failed to initialize interrupts");
|
||||
return -EIO;
|
||||
}
|
||||
#endif /* CONFIG_IIS2DH_TRIGGER */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct iis2dh_device_config iis2dh_cfg = {
|
||||
.bus_name = DT_INST_BUS_LABEL(0),
|
||||
.pm = CONFIG_IIS2DH_POWER_MODE,
|
||||
#ifdef CONFIG_IIS2DH_TRIGGER
|
||||
.int_gpio_port = DT_INST_GPIO_LABEL(0, drdy_gpios),
|
||||
.int_gpio_pin = DT_INST_GPIO_PIN(0, drdy_gpios),
|
||||
.int_gpio_flags = DT_INST_GPIO_FLAGS(0, drdy_gpios),
|
||||
#endif /* CONFIG_IIS2DH_TRIGGER */
|
||||
};
|
||||
|
||||
struct iis2dh_data iis2dh_data;
|
||||
|
||||
DEVICE_AND_API_INIT(iis2dh, DT_INST_LABEL(0), iis2dh_init,
|
||||
&iis2dh_data, &iis2dh_cfg, POST_KERNEL,
|
||||
CONFIG_SENSOR_INIT_PRIORITY, &iis2dh_driver_api);
|
95
drivers/sensor/iis2dh/iis2dh.h
Normal file
95
drivers/sensor/iis2dh/iis2dh.h
Normal file
|
@ -0,0 +1,95 @@
|
|||
/* ST Microelectronics IIS2DH 3-axis accelerometer driver
|
||||
*
|
||||
* Copyright (c) 2020 STMicroelectronics
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Datasheet:
|
||||
* https://www.st.com/resource/en/datasheet/iis2dh.pdf
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_DRIVERS_SENSOR_IIS2DH_IIS2DH_H_
|
||||
#define ZEPHYR_DRIVERS_SENSOR_IIS2DH_IIS2DH_H_
|
||||
|
||||
#include <drivers/spi.h>
|
||||
#include <drivers/gpio.h>
|
||||
#include <sys/util.h>
|
||||
#include <drivers/sensor.h>
|
||||
#include "iis2dh_reg.h"
|
||||
|
||||
union axis3bit16_t {
|
||||
int16_t i16bit[3];
|
||||
uint8_t u8bit[6];
|
||||
};
|
||||
|
||||
/*
|
||||
* Return ODR reg value based on data rate set
|
||||
*/
|
||||
#define IIS2DH_ODR_TO_REG_HR(_lp, _odr) \
|
||||
((_odr == 0) ? IIS2DH_POWER_DOWN : \
|
||||
((_odr < 10) ? IIS2DH_ODR_1Hz : \
|
||||
((_odr < 25) ? IIS2DH_ODR_10Hz : \
|
||||
((_lp == IIS2DH_LP_8bit) && (_odr >= 5376) ? IIS2DH_ODR_5kHz376_LP_1kHz344_NM_HP : \
|
||||
((_lp != IIS2DH_LP_8bit) && (_odr >= 1344) ? IIS2DH_ODR_5kHz376_LP_1kHz344_NM_HP : \
|
||||
((_lp == IIS2DH_LP_8bit) && (_odr >= 1600) ? IIS2DH_ODR_1kHz620_LP : \
|
||||
((_lp != IIS2DH_LP_8bit) && (_odr >= 800) ? IIS2DH_ODR_400Hz : \
|
||||
((31 - __builtin_clz(_odr / 25))) + 3)))))))
|
||||
|
||||
/* FS reg value from Full Scale */
|
||||
#define IIS2DH_FS_TO_REG(_fs) (30 - __builtin_clz(_fs))
|
||||
|
||||
/**
|
||||
* struct iis2dh_device_config - iis2dh hw configuration
|
||||
* @bus_name: Pointer to bus master identifier.
|
||||
* @pm: Power mode (lis2dh_powermode).
|
||||
* @int_gpio_port: Pointer to GPIO PORT identifier.
|
||||
* @int_gpio_pin: GPIO pin number connecter to sensor int pin.
|
||||
*/
|
||||
struct iis2dh_device_config {
|
||||
const char *bus_name;
|
||||
uint8_t pm;
|
||||
#ifdef CONFIG_IIS2DH_TRIGGER
|
||||
const char *int_gpio_port;
|
||||
uint8_t int_gpio_pin;
|
||||
uint8_t int_gpio_flags;
|
||||
uint8_t int_pin;
|
||||
#endif /* CONFIG_IIS2DH_TRIGGER */
|
||||
};
|
||||
|
||||
/* sensor data */
|
||||
struct iis2dh_data {
|
||||
struct device *bus;
|
||||
int16_t acc[3];
|
||||
uint32_t gain;
|
||||
|
||||
stmdev_ctx_t *ctx;
|
||||
#ifdef CONFIG_IIS2DH_TRIGGER
|
||||
struct device *gpio;
|
||||
uint8_t gpio_pin;
|
||||
struct gpio_callback gpio_cb;
|
||||
sensor_trigger_handler_t drdy_handler;
|
||||
#if defined(CONFIG_IIS2DH_TRIGGER_OWN_THREAD)
|
||||
K_THREAD_STACK_MEMBER(thread_stack, CONFIG_IIS2DH_THREAD_STACK_SIZE);
|
||||
struct k_thread thread;
|
||||
struct k_sem gpio_sem;
|
||||
#elif defined(CONFIG_IIS2DH_TRIGGER_GLOBAL_THREAD)
|
||||
struct k_work work;
|
||||
struct device *dev;
|
||||
#endif /* CONFIG_IIS2DH_TRIGGER_GLOBAL_THREAD */
|
||||
#endif /* CONFIG_IIS2DH_TRIGGER */
|
||||
#if DT_INST_SPI_DEV_HAS_CS_GPIOS(0)
|
||||
struct spi_cs_control cs_ctrl;
|
||||
#endif
|
||||
};
|
||||
|
||||
int iis2dh_i2c_init(struct device *dev);
|
||||
int iis2dh_spi_init(struct device *dev);
|
||||
|
||||
#ifdef CONFIG_IIS2DH_TRIGGER
|
||||
int iis2dh_init_interrupt(struct device *dev);
|
||||
int iis2dh_trigger_set(struct device *dev,
|
||||
const struct sensor_trigger *trig,
|
||||
sensor_trigger_handler_t handler);
|
||||
#endif /* CONFIG_IIS2DH_TRIGGER */
|
||||
|
||||
#endif /* ZEPHYR_DRIVERS_SENSOR_IIS2DH_IIS2DH_H_ */
|
53
drivers/sensor/iis2dh/iis2dh_i2c.c
Normal file
53
drivers/sensor/iis2dh/iis2dh_i2c.c
Normal file
|
@ -0,0 +1,53 @@
|
|||
/* ST Microelectronics IIS2DH 3-axis accelerometer driver
|
||||
*
|
||||
* Copyright (c) 2020 STMicroelectronics
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Datasheet:
|
||||
* https://www.st.com/resource/en/datasheet/iis2dh.pdf
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT st_iis2dh
|
||||
|
||||
#include <string.h>
|
||||
#include <drivers/i2c.h>
|
||||
#include <logging/log.h>
|
||||
|
||||
#include "iis2dh.h"
|
||||
|
||||
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c)
|
||||
|
||||
static uint16_t iis2dh_i2c_slave_addr = DT_INST_REG_ADDR(0);
|
||||
|
||||
LOG_MODULE_DECLARE(IIS2DH, CONFIG_SENSOR_LOG_LEVEL);
|
||||
|
||||
static int iis2dh_i2c_read(struct iis2dh_data *data, uint8_t reg_addr,
|
||||
uint8_t *value, uint16_t len)
|
||||
{
|
||||
return i2c_burst_read(data->bus, iis2dh_i2c_slave_addr,
|
||||
reg_addr | 0x80, value, len);
|
||||
}
|
||||
|
||||
static int iis2dh_i2c_write(struct iis2dh_data *data, uint8_t reg_addr,
|
||||
uint8_t *value, uint16_t len)
|
||||
{
|
||||
return i2c_burst_write(data->bus, iis2dh_i2c_slave_addr,
|
||||
reg_addr | 0x80, value, len);
|
||||
}
|
||||
|
||||
stmdev_ctx_t iis2dh_i2c_ctx = {
|
||||
.read_reg = (stmdev_read_ptr) iis2dh_i2c_read,
|
||||
.write_reg = (stmdev_write_ptr) iis2dh_i2c_write,
|
||||
};
|
||||
|
||||
int iis2dh_i2c_init(struct device *dev)
|
||||
{
|
||||
struct iis2dh_data *data = dev->driver_data;
|
||||
|
||||
data->ctx = &iis2dh_i2c_ctx;
|
||||
data->ctx->handle = data;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c) */
|
128
drivers/sensor/iis2dh/iis2dh_spi.c
Normal file
128
drivers/sensor/iis2dh/iis2dh_spi.c
Normal file
|
@ -0,0 +1,128 @@
|
|||
/* ST Microelectronics IIS2DH 3-axis accelerometer driver
|
||||
*
|
||||
* Copyright (c) 2020 STMicroelectronics
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Datasheet:
|
||||
* https://www.st.com/resource/en/datasheet/iis2dh.pdf
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT st_iis2dh
|
||||
|
||||
#include <string.h>
|
||||
#include "iis2dh.h"
|
||||
#include <logging/log.h>
|
||||
|
||||
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi)
|
||||
|
||||
#define IIS2DH_SPI_READM (3 << 6) /* 0xC0 */
|
||||
#define IIS2DH_SPI_WRITEM (1 << 6) /* 0x40 */
|
||||
|
||||
LOG_MODULE_DECLARE(IIS2DH, CONFIG_SENSOR_LOG_LEVEL);
|
||||
|
||||
static struct spi_config iis2dh_spi_conf = {
|
||||
.frequency = DT_INST_PROP(0, spi_max_frequency),
|
||||
.operation = (SPI_OP_MODE_MASTER | SPI_MODE_CPOL |
|
||||
SPI_MODE_CPHA | SPI_WORD_SET(8) | SPI_LINES_SINGLE),
|
||||
.slave = DT_INST_REG_ADDR(0),
|
||||
.cs = NULL,
|
||||
};
|
||||
|
||||
static int iis2dh_spi_read(struct iis2dh_data *ctx, uint8_t reg,
|
||||
uint8_t *data, uint16_t len)
|
||||
{
|
||||
struct spi_config *spi_cfg = &iis2dh_spi_conf;
|
||||
uint8_t buffer_tx[2] = { reg | IIS2DH_SPI_READM, 0 };
|
||||
const struct spi_buf tx_buf = {
|
||||
.buf = buffer_tx,
|
||||
.len = 2,
|
||||
};
|
||||
const struct spi_buf_set tx = {
|
||||
.buffers = &tx_buf,
|
||||
.count = 1
|
||||
};
|
||||
const struct spi_buf rx_buf[2] = {
|
||||
{
|
||||
.buf = NULL,
|
||||
.len = 1,
|
||||
},
|
||||
{
|
||||
.buf = data,
|
||||
.len = len,
|
||||
}
|
||||
};
|
||||
const struct spi_buf_set rx = {
|
||||
.buffers = rx_buf,
|
||||
.count = 2
|
||||
};
|
||||
|
||||
if (spi_transceive(ctx->bus, spi_cfg, &tx, &rx)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iis2dh_spi_write(struct iis2dh_data *ctx, uint8_t reg,
|
||||
uint8_t *data, uint16_t len)
|
||||
{
|
||||
struct spi_config *spi_cfg = &iis2dh_spi_conf;
|
||||
uint8_t buffer_tx[1] = { reg | IIS2DH_SPI_WRITEM };
|
||||
const struct spi_buf tx_buf[2] = {
|
||||
{
|
||||
.buf = buffer_tx,
|
||||
.len = 1,
|
||||
},
|
||||
{
|
||||
.buf = data,
|
||||
.len = len,
|
||||
}
|
||||
};
|
||||
const struct spi_buf_set tx = {
|
||||
.buffers = tx_buf,
|
||||
.count = 2
|
||||
};
|
||||
|
||||
|
||||
if (spi_write(ctx->bus, spi_cfg, &tx)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
stmdev_ctx_t iis2dh_spi_ctx = {
|
||||
.read_reg = (stmdev_read_ptr) iis2dh_spi_read,
|
||||
.write_reg = (stmdev_write_ptr) iis2dh_spi_write,
|
||||
};
|
||||
|
||||
int iis2dh_spi_init(struct device *dev)
|
||||
{
|
||||
struct iis2dh_data *data = dev->driver_data;
|
||||
|
||||
data->ctx = &iis2dh_spi_ctx;
|
||||
data->ctx->handle = data;
|
||||
|
||||
#if DT_INST_SPI_DEV_HAS_CS_GPIOS(0)
|
||||
/* handle SPI CS thru GPIO if it is the case */
|
||||
data->cs_ctrl.gpio_dev = device_get_binding(
|
||||
DT_INST_SPI_DEV_CS_GPIOS_LABEL(0));
|
||||
if (!data->cs_ctrl.gpio_dev) {
|
||||
LOG_ERR("Unable to get GPIO SPI CS device");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
data->cs_ctrl.gpio_pin = DT_INST_SPI_DEV_CS_GPIOS_PIN(0);
|
||||
data->cs_ctrl.delay = 0U;
|
||||
|
||||
iis2dh_spi_conf.cs = &data->cs_ctrl;
|
||||
|
||||
LOG_DBG("SPI GPIO CS configured on %s:%u",
|
||||
DT_INST_SPI_DEV_CS_GPIOS_LABEL(0),
|
||||
DT_INST_SPI_DEV_CS_GPIOS_PIN(0));
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(spi) */
|
191
drivers/sensor/iis2dh/iis2dh_trigger.c
Normal file
191
drivers/sensor/iis2dh/iis2dh_trigger.c
Normal file
|
@ -0,0 +1,191 @@
|
|||
/* ST Microelectronics IIS2DH 3-axis accelerometer driver
|
||||
*
|
||||
* Copyright (c) 2020 STMicroelectronics
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Datasheet:
|
||||
* https://www.st.com/resource/en/datasheet/iis2dh.pdf
|
||||
*/
|
||||
|
||||
#include <kernel.h>
|
||||
#include <drivers/sensor.h>
|
||||
#include <drivers/gpio.h>
|
||||
#include <logging/log.h>
|
||||
|
||||
#include "iis2dh.h"
|
||||
|
||||
LOG_MODULE_DECLARE(IIS2DH, CONFIG_SENSOR_LOG_LEVEL);
|
||||
|
||||
/**
|
||||
* iis2dh_enable_int - enable selected int pin to generate interrupt
|
||||
*/
|
||||
static int iis2dh_enable_drdy(struct device *dev,
|
||||
enum sensor_trigger_type type, int enable)
|
||||
{
|
||||
struct iis2dh_data *iis2dh = dev->driver_data;
|
||||
iis2dh_ctrl_reg3_t reg3;
|
||||
|
||||
/* set interrupt for pin INT1 */
|
||||
iis2dh_pin_int1_config_get(iis2dh->ctx, ®3);
|
||||
|
||||
reg3.i1_drdy1 = enable;
|
||||
|
||||
return iis2dh_pin_int1_config_set(iis2dh->ctx, ®3);
|
||||
}
|
||||
|
||||
/**
|
||||
* iis2dh_trigger_set - link external trigger to event data ready
|
||||
*/
|
||||
int iis2dh_trigger_set(struct device *dev,
|
||||
const struct sensor_trigger *trig,
|
||||
sensor_trigger_handler_t handler)
|
||||
{
|
||||
struct iis2dh_data *iis2dh = dev->driver_data;
|
||||
union axis3bit16_t raw;
|
||||
int state = (handler != NULL) ? PROPERTY_ENABLE : PROPERTY_DISABLE;
|
||||
|
||||
switch (trig->type) {
|
||||
case SENSOR_TRIG_DATA_READY:
|
||||
iis2dh->drdy_handler = handler;
|
||||
if (state) {
|
||||
/* dummy read: re-trigger interrupt */
|
||||
iis2dh_acceleration_raw_get(iis2dh->ctx, raw.u8bit);
|
||||
}
|
||||
return iis2dh_enable_drdy(dev, SENSOR_TRIG_DATA_READY, state);
|
||||
default:
|
||||
LOG_ERR("Unsupported sensor trigger");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
}
|
||||
|
||||
static int iis2dh_handle_drdy_int(struct device *dev)
|
||||
{
|
||||
struct iis2dh_data *data = dev->driver_data;
|
||||
|
||||
struct sensor_trigger drdy_trig = {
|
||||
.type = SENSOR_TRIG_DATA_READY,
|
||||
.chan = SENSOR_CHAN_ALL,
|
||||
};
|
||||
|
||||
if (data->drdy_handler) {
|
||||
data->drdy_handler(dev, &drdy_trig);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* iis2dh_handle_interrupt - handle the drdy event
|
||||
* read data and call handler if registered any
|
||||
*/
|
||||
static void iis2dh_handle_interrupt(void *arg)
|
||||
{
|
||||
struct device *dev = (struct device *)arg;
|
||||
struct iis2dh_data *iis2dh = dev->driver_data;
|
||||
const struct iis2dh_device_config *cfg = dev->config_info;
|
||||
|
||||
iis2dh_handle_drdy_int(dev);
|
||||
|
||||
gpio_pin_interrupt_configure(iis2dh->gpio, cfg->int_gpio_pin,
|
||||
GPIO_INT_EDGE_TO_ACTIVE);
|
||||
}
|
||||
|
||||
static void iis2dh_gpio_callback(struct device *dev,
|
||||
struct gpio_callback *cb, uint32_t pins)
|
||||
{
|
||||
struct iis2dh_data *iis2dh =
|
||||
CONTAINER_OF(cb, struct iis2dh_data, gpio_cb);
|
||||
|
||||
if ((pins & BIT(iis2dh->gpio_pin)) == 0U) {
|
||||
return;
|
||||
}
|
||||
|
||||
gpio_pin_interrupt_configure(dev, iis2dh->gpio_pin,
|
||||
GPIO_INT_DISABLE);
|
||||
|
||||
#if defined(CONFIG_IIS2DH_TRIGGER_OWN_THREAD)
|
||||
k_sem_give(&iis2dh->gpio_sem);
|
||||
#elif defined(CONFIG_IIS2DH_TRIGGER_GLOBAL_THREAD)
|
||||
k_work_submit(&iis2dh->work);
|
||||
#endif /* CONFIG_IIS2DH_TRIGGER_OWN_THREAD */
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IIS2DH_TRIGGER_OWN_THREAD
|
||||
static void iis2dh_thread(int dev_ptr, int unused)
|
||||
{
|
||||
struct device *dev = INT_TO_POINTER(dev_ptr);
|
||||
struct iis2dh_data *iis2dh = dev->driver_data;
|
||||
|
||||
ARG_UNUSED(unused);
|
||||
|
||||
while (1) {
|
||||
k_sem_take(&iis2dh->gpio_sem, K_FOREVER);
|
||||
iis2dh_handle_interrupt(dev);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_IIS2DH_TRIGGER_OWN_THREAD */
|
||||
|
||||
#ifdef CONFIG_IIS2DH_TRIGGER_GLOBAL_THREAD
|
||||
static void iis2dh_work_cb(struct k_work *work)
|
||||
{
|
||||
struct iis2dh_data *iis2dh =
|
||||
CONTAINER_OF(work, struct iis2dh_data, work);
|
||||
|
||||
iis2dh_handle_interrupt(iis2dh->dev);
|
||||
}
|
||||
#endif /* CONFIG_IIS2DH_TRIGGER_GLOBAL_THREAD */
|
||||
|
||||
int iis2dh_init_interrupt(struct device *dev)
|
||||
{
|
||||
struct iis2dh_data *iis2dh = dev->driver_data;
|
||||
const struct iis2dh_device_config *cfg = dev->config_info;
|
||||
int ret;
|
||||
|
||||
/* setup data ready gpio interrupt */
|
||||
iis2dh->gpio = device_get_binding(cfg->int_gpio_port);
|
||||
if (iis2dh->gpio == NULL) {
|
||||
LOG_DBG("Cannot get pointer to %s device",
|
||||
cfg->int_gpio_port);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_IIS2DH_TRIGGER_OWN_THREAD)
|
||||
k_sem_init(&iis2dh->gpio_sem, 0, UINT_MAX);
|
||||
|
||||
k_thread_create(&iis2dh->thread, iis2dh->thread_stack,
|
||||
CONFIG_IIS2DH_THREAD_STACK_SIZE,
|
||||
(k_thread_entry_t)iis2dh_thread, dev,
|
||||
0, NULL, K_PRIO_COOP(CONFIG_IIS2DH_THREAD_PRIORITY),
|
||||
0, K_NO_WAIT);
|
||||
#elif defined(CONFIG_IIS2DH_TRIGGER_GLOBAL_THREAD)
|
||||
iis2dh->work.handler = iis2dh_work_cb;
|
||||
iis2dh->dev = dev;
|
||||
#endif /* CONFIG_IIS2DH_TRIGGER_OWN_THREAD */
|
||||
|
||||
iis2dh->gpio_pin = cfg->int_gpio_pin;
|
||||
|
||||
ret = gpio_pin_configure(iis2dh->gpio, cfg->int_gpio_pin,
|
||||
GPIO_INPUT | cfg->int_gpio_flags);
|
||||
if (ret < 0) {
|
||||
LOG_DBG("Could not configure gpio");
|
||||
return ret;
|
||||
}
|
||||
|
||||
gpio_init_callback(&iis2dh->gpio_cb,
|
||||
iis2dh_gpio_callback,
|
||||
BIT(cfg->int_gpio_pin));
|
||||
|
||||
if (gpio_add_callback(iis2dh->gpio, &iis2dh->gpio_cb) < 0) {
|
||||
LOG_DBG("Could not set gpio callback");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* enable drdy on int1 in pulse mode */
|
||||
if (iis2dh_int1_pin_notification_mode_set(iis2dh->ctx, IIS2DH_INT1_PULSED)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return gpio_pin_interrupt_configure(iis2dh->gpio, cfg->int_gpio_pin,
|
||||
GPIO_INT_EDGE_TO_ACTIVE);
|
||||
}
|
19
dts/bindings/sensor/st,iis2dh-i2c.yaml
Normal file
19
dts/bindings/sensor/st,iis2dh-i2c.yaml
Normal file
|
@ -0,0 +1,19 @@
|
|||
# Copyright (c) 2020 STMicroelectronics
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: |
|
||||
STMicroelectronics IIS2DH accelerometer accessed through I2C bus
|
||||
|
||||
compatible: "st,iis2dh"
|
||||
|
||||
include: i2c-device.yaml
|
||||
|
||||
properties:
|
||||
drdy-gpios:
|
||||
type: phandle-array
|
||||
required: false
|
||||
description: DRDY pin
|
||||
|
||||
This pin defaults to active high when produced by the sensor.
|
||||
The property value should ensure the flags properly describe
|
||||
the signal that is presented to the driver.
|
19
dts/bindings/sensor/st,iis2dh-spi.yaml
Normal file
19
dts/bindings/sensor/st,iis2dh-spi.yaml
Normal file
|
@ -0,0 +1,19 @@
|
|||
# Copyright (c) 2020 STMicroelectronics
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: |
|
||||
STMicroelectronics IIS2DH accelerometer accessed through SPI bus
|
||||
|
||||
compatible: "st,iis2dh"
|
||||
|
||||
include: spi-device.yaml
|
||||
|
||||
properties:
|
||||
drdy-gpios:
|
||||
type: phandle-array
|
||||
required: false
|
||||
description: DRDY pin
|
||||
|
||||
This pin defaults to active high when produced by the sensor.
|
||||
The property value should ensure the flags properly describe
|
||||
the signal that is presented to the driver.
|
|
@ -144,3 +144,8 @@
|
|||
&test_spi_iis3dhhc {
|
||||
irq-gpios = <&test_gpio 0 0>, <&test_gpio 0 0>;
|
||||
};
|
||||
|
||||
/* disable device to conflict with i2c version */
|
||||
&test_spi_iis2dh {
|
||||
status = "disabled";
|
||||
};
|
||||
|
|
|
@ -529,3 +529,10 @@ test_i2c_dps310: dps310@48 {
|
|||
label = "DPS310";
|
||||
reg = <0x48>;
|
||||
};
|
||||
|
||||
test_i2c_iis2dh: iis2dh@18 {
|
||||
compatible = "st,iis2dh";
|
||||
label = "IIS2DH";
|
||||
reg = <0x18>;
|
||||
drdy-gpios = <&test_gpio 0 0>;
|
||||
};
|
||||
|
|
|
@ -9,4 +9,5 @@ CONFIG_IIS2DLPC=y
|
|||
CONFIG_LIS2DW12=y
|
||||
CONFIG_STTS751=y
|
||||
CONFIG_ISM330DHCX=y
|
||||
CONFIG_IIS2DH=y
|
||||
CONFIG_IIS2MDC=y
|
||||
|
|
|
@ -13,5 +13,7 @@ CONFIG_STTS751=y
|
|||
CONFIG_STTS751_TRIGGER_OWN_THREAD=y
|
||||
CONFIG_ISM330DHCX=y
|
||||
CONFIG_ISM330DHCX_TRIGGER_OWN_THREAD=y
|
||||
CONFIG_IIS2DH=y
|
||||
CONFIG_IIS2DH_TRIGGER_OWN_THREAD=y
|
||||
CONFIG_IIS2MDC=y
|
||||
CONFIG_IIS2MDC_TRIGGER_OWN_THREAD=y
|
||||
|
|
|
@ -483,3 +483,10 @@ test_spi_mmc_spi_slot: mmc-spi-slot@2f {
|
|||
spi-max-frequency = <0>;
|
||||
};
|
||||
|
||||
test_spi_iis2dh: iis2dh@30 {
|
||||
compatible = "st,iis2dh";
|
||||
label = "IIS2DH";
|
||||
reg = <0x30>;
|
||||
spi-max-frequency = <0>;
|
||||
drdy-gpios = <&test_gpio 0 0>;
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue