Skip to content

Commit 7264c5b

Browse files
committed
sensors: lsm6dsv16x: add RTIO async and fifo stream
Add RTIO async and RTIO stream functionalities that enables, among all the other things, the sensor data streaming from FIFO. RTIO stream is using both SENSOR_TRIG_FIFO_WATERMARK and SENSOR_TRIG_FIFO_FULL triggers. The decoder currently only supports following FIFO tags: - LSM6DSV16X_XL_NC_TAG - LSM6DSV16X_GY_NC_TAG - LSM6DSV16X_TEMP_NC_TAG Following FIFO parameters has to be defined in device tree to correctly stream sensor data: - fifo-watermark (defaults to 32) - accel-fifo-batch-rate (defaults to LSM6DSV16X_DT_XL_NOT_BATCHED) - gyro-fifo-batch-rate (defaults to LSM6DSV16X_DT_GY_NOT_BATCHED) - temp-fifo-batch-rate (defaults to LSM6DSV16X_DT_TEMP_NOT_BATCHED) Signed-off-by: Armando Visconti <[email protected]>
1 parent ea8fe77 commit 7264c5b

File tree

13 files changed

+1379
-37
lines changed

13 files changed

+1379
-37
lines changed

drivers/sensor/st/lsm6dsv16x/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,7 @@ zephyr_library()
99
zephyr_library_sources(lsm6dsv16x.c)
1010
zephyr_library_sources_ifdef(CONFIG_LSM6DSV16X_SENSORHUB lsm6dsv16x_shub.c)
1111
zephyr_library_sources_ifdef(CONFIG_LSM6DSV16X_TRIGGER lsm6dsv16x_trigger.c)
12+
zephyr_library_sources_ifdef(CONFIG_SENSOR_ASYNC_API lsm6dsv16x_rtio.c lsm6dsv16x_decoder.c)
13+
zephyr_library_sources_ifdef(CONFIG_LSM6DSV16X_STREAM lsm6dsv16x_rtio_stream.c)
1214

1315
zephyr_library_include_directories(../stmemsc)

drivers/sensor/st/lsm6dsv16x/Kconfig

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,22 @@ menuconfig LSM6DSV16X
1212
select SPI if $(dt_compat_on_bus,$(DT_COMPAT_ST_LSM6DSV16X),spi)
1313
select HAS_STMEMSC
1414
select USE_STDC_LSM6DSV16X
15+
select RTIO_WORKQ if SENSOR_ASYNC_API
1516
help
1617
Enable driver for LSM6DSV16X accelerometer and gyroscope
1718
sensor.
1819

1920
if LSM6DSV16X
2021

22+
config LSM6DSV16X_STREAM
23+
bool "Use hardware FIFO to stream data"
24+
select LSM6DSV16X_TRIGGER
25+
default y
26+
depends on I2C_RTIO || SPI_RTIO
27+
depends on SENSOR_ASYNC_API
28+
help
29+
Use this config option to enable streaming sensor data via RTIO subsystem.
30+
2131
choice LSM6DSV16X_TRIGGER_MODE
2232
prompt "Trigger mode"
2333
help

drivers/sensor/st/lsm6dsv16x/lsm6dsv16x.c

Lines changed: 72 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
#include <zephyr/logging/log.h>
2020

2121
#include "lsm6dsv16x.h"
22+
#include "lsm6dsv16x_decoder.h"
23+
#include "lsm6dsv16x_rtio.h"
2224

2325
LOG_MODULE_REGISTER(LSM6DSV16X, CONFIG_SENSOR_LOG_LEVEL);
2426

@@ -86,6 +88,16 @@ static const uint16_t lsm6dsv16x_gyro_fs_map[] = {125, 250, 500, 1000, 2000, 0,
8688
0, 0, 0, 0, 0, 4000};
8789
static const uint16_t lsm6dsv16x_gyro_fs_sens[] = {1, 2, 4, 8, 16, 0, 0, 0, 0, 0, 0, 0, 32};
8890

91+
int lsm6dsv16x_calc_accel_gain(uint8_t fs)
92+
{
93+
return lsm6dsv16x_accel_fs_map[fs] * GAIN_UNIT_XL / 2;
94+
}
95+
96+
int lsm6dsv16x_calc_gyro_gain(uint8_t fs)
97+
{
98+
return lsm6dsv16x_gyro_fs_sens[fs] * GAIN_UNIT_G;
99+
}
100+
89101
static int lsm6dsv16x_gyro_range_to_fs_val(int32_t range)
90102
{
91103
size_t i;
@@ -205,7 +217,7 @@ static int lsm6dsv16x_accel_range_set(const struct device *dev, int32_t range)
205217
return -EIO;
206218
}
207219

208-
data->acc_gain = lsm6dsv16x_accel_fs_map[fs] * GAIN_UNIT_XL / 2;
220+
data->acc_gain = lsm6dsv16x_calc_accel_gain(fs);
209221
return 0;
210222
}
211223

@@ -295,7 +307,7 @@ static int lsm6dsv16x_gyro_range_set(const struct device *dev, int32_t range)
295307
return -EIO;
296308
}
297309

298-
data->gyro_gain = (lsm6dsv16x_gyro_fs_sens[fs] * GAIN_UNIT_G);
310+
data->gyro_gain = lsm6dsv16x_calc_gyro_gain(fs);
299311
return 0;
300312
}
301313

@@ -924,6 +936,10 @@ static const struct sensor_driver_api lsm6dsv16x_driver_api = {
924936
#endif
925937
.sample_fetch = lsm6dsv16x_sample_fetch,
926938
.channel_get = lsm6dsv16x_channel_get,
939+
#ifdef CONFIG_SENSOR_ASYNC_API
940+
.get_decoder = lsm6dsv16x_get_decoder,
941+
.submit = lsm6dsv16x_submit,
942+
#endif
927943
};
928944

929945
static int lsm6dsv16x_init_chip(const struct device *dev)
@@ -970,7 +986,7 @@ static int lsm6dsv16x_init_chip(const struct device *dev)
970986
LOG_ERR("failed to set accelerometer range %d", fs);
971987
return -EIO;
972988
}
973-
lsm6dsv16x->acc_gain = lsm6dsv16x_accel_fs_map[fs] * GAIN_UNIT_XL / 2;
989+
lsm6dsv16x->acc_gain = lsm6dsv16x_calc_accel_gain(fs);
974990

975991
odr = cfg->accel_odr;
976992
LOG_DBG("accel odr is %d", odr);
@@ -985,7 +1001,7 @@ static int lsm6dsv16x_init_chip(const struct device *dev)
9851001
LOG_ERR("failed to set gyroscope range %d", fs);
9861002
return -EIO;
9871003
}
988-
lsm6dsv16x->gyro_gain = (lsm6dsv16x_gyro_fs_sens[fs] * GAIN_UNIT_G);
1004+
lsm6dsv16x->gyro_gain = lsm6dsv16x_calc_gyro_gain(fs);
9891005

9901006
odr = cfg->gyro_odr;
9911007
LOG_DBG("gyro odr is %d", odr);
@@ -1057,10 +1073,6 @@ static int lsm6dsv16x_init(const struct device *dev)
10571073
CONFIG_SENSOR_INIT_PRIORITY, \
10581074
&lsm6dsv16x_driver_api);
10591075

1060-
/*
1061-
* Instantiation macros used when a device is on a SPI bus.
1062-
*/
1063-
10641076
#ifdef CONFIG_LSM6DSV16X_TRIGGER
10651077
#define LSM6DSV16X_CFG_IRQ(inst) \
10661078
.trig_enabled = true, \
@@ -1072,19 +1084,33 @@ static int lsm6dsv16x_init(const struct device *dev)
10721084
#define LSM6DSV16X_CFG_IRQ(inst)
10731085
#endif /* CONFIG_LSM6DSV16X_TRIGGER */
10741086

1087+
#define LSM6DSV16X_CONFIG_COMMON(inst) \
1088+
.accel_odr = DT_INST_PROP(inst, accel_odr), \
1089+
.accel_range = DT_INST_PROP(inst, accel_range), \
1090+
.gyro_odr = DT_INST_PROP(inst, gyro_odr), \
1091+
.gyro_range = DT_INST_PROP(inst, gyro_range), \
1092+
IF_ENABLED(CONFIG_LSM6DSV16X_STREAM, \
1093+
(.fifo_wtm = DT_INST_PROP(inst, fifo_watermark), \
1094+
.accel_batch = DT_INST_PROP(inst, accel_fifo_batch_rate), \
1095+
.gyro_batch = DT_INST_PROP(inst, gyro_fifo_batch_rate), \
1096+
.temp_batch = DT_INST_PROP(inst, temp_fifo_batch_rate),)) \
1097+
IF_ENABLED(UTIL_OR(DT_INST_NODE_HAS_PROP(inst, int1_gpios), \
1098+
DT_INST_NODE_HAS_PROP(inst, int2_gpios)), \
1099+
(LSM6DSV16X_CFG_IRQ(inst)))
1100+
1101+
/*
1102+
* Instantiation macros used when a device is on a SPI bus.
1103+
*/
1104+
10751105
#define LSM6DSV16X_SPI_OP (SPI_WORD_SET(8) | \
10761106
SPI_OP_MODE_MASTER | \
10771107
SPI_MODE_CPOL | \
10781108
SPI_MODE_CPHA) \
10791109

1080-
#define LSM6DSV16X_CONFIG_COMMON(inst) \
1081-
.accel_odr = DT_INST_PROP(inst, accel_odr), \
1082-
.accel_range = DT_INST_PROP(inst, accel_range), \
1083-
.gyro_odr = DT_INST_PROP(inst, gyro_odr), \
1084-
.gyro_range = DT_INST_PROP(inst, gyro_range), \
1085-
IF_ENABLED(UTIL_OR(DT_INST_NODE_HAS_PROP(inst, int1_gpios), \
1086-
DT_INST_NODE_HAS_PROP(inst, int2_gpios)), \
1087-
(LSM6DSV16X_CFG_IRQ(inst)))
1110+
#define LSM6DSV16X_SPI_RTIO_DEFINE(inst) \
1111+
SPI_DT_IODEV_DEFINE(lsm6dsv16x_iodev_##inst, \
1112+
DT_DRV_INST(inst), LSM6DSV16X_SPI_OP, 0U); \
1113+
RTIO_DEFINE(lsm6dsv16x_rtio_ctx_##inst, 4, 4);
10881114

10891115
#define LSM6DSV16X_CONFIG_SPI(inst) \
10901116
{ \
@@ -1097,10 +1123,25 @@ static int lsm6dsv16x_init(const struct device *dev)
10971123
LSM6DSV16X_CONFIG_COMMON(inst) \
10981124
}
10991125

1126+
#define LSM6DSV16X_DEFINE_SPI(inst) \
1127+
IF_ENABLED(CONFIG_LSM6DSV16X_STREAM, (LSM6DSV16X_SPI_RTIO_DEFINE(inst))); \
1128+
static struct lsm6dsv16x_data lsm6dsv16x_data_##inst = { \
1129+
IF_ENABLED(CONFIG_LSM6DSV16X_STREAM, \
1130+
(.rtio_ctx = &lsm6dsv16x_rtio_ctx_##inst, \
1131+
.iodev = &lsm6dsv16x_iodev_##inst, \
1132+
.bus_type = BUS_SPI,)) \
1133+
}; \
1134+
static const struct lsm6dsv16x_config lsm6dsv16x_config_##inst = \
1135+
LSM6DSV16X_CONFIG_SPI(inst); \
1136+
11001137
/*
11011138
* Instantiation macros used when a device is on an I2C bus.
11021139
*/
11031140

1141+
#define LSM6DSV16X_I2C_RTIO_DEFINE(inst) \
1142+
I2C_DT_IODEV_DEFINE(lsm6dsv16x_iodev_##inst, DT_DRV_INST(inst));\
1143+
RTIO_DEFINE(lsm6dsv16x_rtio_ctx_##inst, 4, 4);
1144+
11041145
#define LSM6DSV16X_CONFIG_I2C(inst) \
11051146
{ \
11061147
STMEMSC_CTX_I2C(&lsm6dsv16x_config_##inst.stmemsc_cfg), \
@@ -1110,17 +1151,27 @@ static int lsm6dsv16x_init(const struct device *dev)
11101151
LSM6DSV16X_CONFIG_COMMON(inst) \
11111152
}
11121153

1154+
1155+
#define LSM6DSV16X_DEFINE_I2C(inst) \
1156+
IF_ENABLED(CONFIG_LSM6DSV16X_STREAM, (LSM6DSV16X_I2C_RTIO_DEFINE(inst))); \
1157+
static struct lsm6dsv16x_data lsm6dsv16x_data_##inst = { \
1158+
IF_ENABLED(CONFIG_LSM6DSV16X_STREAM, \
1159+
(.rtio_ctx = &lsm6dsv16x_rtio_ctx_##inst, \
1160+
.iodev = &lsm6dsv16x_iodev_##inst, \
1161+
.bus_type = BUS_I2C,)) \
1162+
}; \
1163+
static const struct lsm6dsv16x_config lsm6dsv16x_config_##inst = \
1164+
LSM6DSV16X_CONFIG_I2C(inst); \
1165+
11131166
/*
11141167
* Main instantiation macro. Use of COND_CODE_1() selects the right
11151168
* bus-specific macro at preprocessor time.
11161169
*/
11171170

11181171
#define LSM6DSV16X_DEFINE(inst) \
1119-
static struct lsm6dsv16x_data lsm6dsv16x_data_##inst; \
1120-
static const struct lsm6dsv16x_config lsm6dsv16x_config_##inst = \
11211172
COND_CODE_1(DT_INST_ON_BUS(inst, spi), \
1122-
(LSM6DSV16X_CONFIG_SPI(inst)), \
1123-
(LSM6DSV16X_CONFIG_I2C(inst))); \
1124-
LSM6DSV16X_DEVICE_INIT(inst)
1173+
(LSM6DSV16X_DEFINE_SPI(inst)), \
1174+
(LSM6DSV16X_DEFINE_I2C(inst))); \
1175+
LSM6DSV16X_DEVICE_INIT(inst)
11251176

11261177
DT_INST_FOREACH_STATUS_OKAY(LSM6DSV16X_DEFINE)

drivers/sensor/st/lsm6dsv16x/lsm6dsv16x.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@
3535
/* Gyro sensor sensitivity grain is 4.375 udps/LSB */
3636
#define GAIN_UNIT_G (4375LL)
3737

38+
int lsm6dsv16x_calc_accel_gain(uint8_t fs);
39+
int lsm6dsv16x_calc_gyro_gain(uint8_t fs);
40+
3841
struct lsm6dsv16x_config {
3942
stmdev_ctx_t ctx;
4043
union {
@@ -52,6 +55,12 @@ struct lsm6dsv16x_config {
5255
uint8_t gyro_odr;
5356
uint8_t gyro_range;
5457
uint8_t drdy_pulsed;
58+
#ifdef CONFIG_LSM6DSV16X_STREAM
59+
uint8_t fifo_wtm;
60+
uint8_t accel_batch : 4;
61+
uint8_t gyro_batch : 4;
62+
uint8_t temp_batch : 2;
63+
#endif
5564
#ifdef CONFIG_LSM6DSV16X_TRIGGER
5665
const struct gpio_dt_spec int1_gpio;
5766
const struct gpio_dt_spec int2_gpio;
@@ -98,6 +107,21 @@ struct lsm6dsv16x_data {
98107
uint8_t gyro_freq;
99108
uint8_t gyro_fs;
100109

110+
#ifdef CONFIG_LSM6DSV16X_STREAM
111+
struct rtio_iodev_sqe *streaming_sqe;
112+
struct rtio *rtio_ctx;
113+
struct rtio_iodev *iodev;
114+
uint64_t fifo_timestamp;
115+
uint8_t fifo_status[2];
116+
uint16_t fifo_count;
117+
uint8_t fifo_irq;
118+
uint8_t accel_batch_odr : 4;
119+
uint8_t gyro_batch_odr : 4;
120+
uint8_t temp_batch_odr : 2;
121+
uint8_t bus_type : 1; /* I2C is 0, SPI is 1 */
122+
uint8_t reserved : 5;
123+
#endif
124+
101125
#ifdef CONFIG_LSM6DSV16X_TRIGGER
102126
struct gpio_dt_spec *drdy_gpio;
103127

@@ -119,6 +143,19 @@ struct lsm6dsv16x_data {
119143
#endif /* CONFIG_LSM6DSV16X_TRIGGER */
120144
};
121145

146+
#ifdef CONFIG_LSM6DSV16X_STREAM
147+
#define BUS_I2C 0
148+
#define BUS_SPI 1
149+
150+
static inline uint8_t lsm6dsv16x_bus_reg(struct lsm6dsv16x_data *data, uint8_t x)
151+
{
152+
return (data->bus_type == BUS_SPI) ? x | 0x80 : x;
153+
}
154+
155+
#define LSM6DSV16X_FIFO_ITEM_LEN 7
156+
#define LSM6DSV16X_FIFO_SIZE(x) (x * LSM6DSV16X_FIFO_ITEM_LEN)
157+
#endif
158+
122159
#if defined(CONFIG_LSM6DSV16X_SENSORHUB)
123160
int lsm6dsv16x_shub_init(const struct device *dev);
124161
int lsm6dsv16x_shub_fetch_external_devs(const struct device *dev);

0 commit comments

Comments
 (0)