Skip to content

Commit 4ada55f

Browse files
committed
bmi08x: Add support for Read-decode and Streaming Mode
One-shot reads through Read-Decode API matches functionality from Fetch-Get API, but asynchronously. Streaming mode supporting FIFO Watermark Interrupts. Works for both Gyro and Accel drivers. Signed-off-by: Luis Ubieda <[email protected]>
1 parent cb77257 commit 4ada55f

21 files changed

+1552
-14
lines changed

drivers/sensor/bosch/bmi08x/CMakeLists.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,12 @@ zephyr_library_sources(bmi08x_gyro.c)
77
zephyr_library_sources(bmi08x.c)
88
zephyr_library_sources_ifdef(CONFIG_BMI08X_ACCEL_TRIGGER bmi08x_accel_trigger.c)
99
zephyr_library_sources_ifdef(CONFIG_BMI08X_GYRO_TRIGGER bmi08x_gyro_trigger.c)
10+
zephyr_library_sources_ifdef(CONFIG_SENSOR_ASYNC_API
11+
bmi08x_bus.c
12+
bmi08x_gyro_async.c
13+
bmi08x_gyro_decoder.c
14+
bmi08x_accel_async.c
15+
bmi08x_accel_decoder.c
16+
)
17+
zephyr_library_sources_ifdef(CONFIG_BMI08X_GYRO_STREAM bmi08x_gyro_stream.c)
18+
zephyr_library_sources_ifdef(CONFIG_BMI08X_ACCEL_STREAM bmi08x_accel_stream.c)

drivers/sensor/bosch/bmi08x/Kconfig

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ menuconfig BMI08X
1111
|| $(dt_compat_on_bus,$(DT_COMPAT_BOSCH_BMI08X_GYRO),i2c)
1212
select SPI if $(dt_compat_on_bus,$(DT_COMPAT_BOSCH_BMI08X_ACCEL),spi) \
1313
|| $(dt_compat_on_bus,$(DT_COMPAT_BOSCH_BMI08X_GYRO),spi)
14+
select SPI_RTIO if SPI
15+
select I2C_RTIO if I2C
1416
help
1517
Enable Bosch BMI08X inertial measurement unit that provides acceleration
1618
and angular rate measurements.
@@ -19,6 +21,7 @@ if BMI08X
1921

2022
choice BMI08X_ACCEL_TRIGGER_MODE
2123
prompt "Accelerometer trigger mode"
24+
default BMI08X_ACCEL_TRIGGER_NONE
2225
default BMI08X_ACCEL_TRIGGER_GLOBAL_THREAD
2326
help
2427
Specify the type of triggering to be used by the driver.
@@ -39,6 +42,13 @@ config BMI08X_ACCEL_TRIGGER_OWN_THREAD
3942
select BMI08X_ACCEL_TRIGGER
4043
endchoice
4144

45+
config BMI08X_ACCEL_STREAM
46+
bool "Accelerometer Streaming Mode (FIFO)"
47+
depends on !BMI08X_ACCEL_TRIGGER
48+
depends on GPIO
49+
depends on $(dt_compat_any_has_prop,$(DT_COMPAT_BOSCH_BMI08X_ACCEL),int-gpios)
50+
51+
4252
config BMI08X_ACCEL_TRIGGER
4353
bool
4454

@@ -75,6 +85,12 @@ config BMI08X_GYRO_TRIGGER_OWN_THREAD
7585
select BMI08X_GYRO_TRIGGER
7686
endchoice
7787

88+
config BMI08X_GYRO_STREAM
89+
bool "Gyroscope Streaming Mode (FIFO)"
90+
depends on !BMI08X_GYRO_TRIGGER
91+
depends on GPIO
92+
depends on $(dt_compat_any_has_prop,$(DT_COMPAT_BOSCH_BMI08X_GYRO),int-gpios)
93+
7894
config BMI08X_GYRO_TRIGGER
7995
bool
8096

drivers/sensor/bosch/bmi08x/bmi08x.h

Lines changed: 118 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
#include <zephyr/drivers/spi.h>
1515
#include <zephyr/sys/util.h>
1616

17+
#include "bmi08x_bus.h"
18+
1719
/* Accel Chip Id register */
1820
#define BMI08X_REG_ACCEL_CHIP_ID 0x00
1921

@@ -65,6 +67,15 @@
6567
/* Sensor temperature LSB data register */
6668
#define BMI08X_REG_TEMP_LSB 0x23
6769

70+
/* Accel FIFO Length (low byte) */
71+
#define BMI08X_REG_ACCEL_FIFO_LEN_0 0x24
72+
73+
/* Accel FIFO Length (high byte) */
74+
#define BMI08X_REG_ACCEL_FIFO_LEN_1 0x25
75+
76+
/* Accel FIFO Data register */
77+
#define BMI08X_REG_ACCEL_FIFO_DATA 0x26
78+
6879
/* Accel general purpose register 4*/
6980
#define BMI08X_REG_ACCEL_GP_4 0x27
7081

@@ -77,6 +88,18 @@
7788
/* Accel range setting register */
7889
#define BMI08X_REG_ACCEL_RANGE 0x41
7990

91+
/* Accel FIFO Watermark (low byte) */
92+
#define BMI08X_REG_ACCEL_FIFO_WTM_0 0x46
93+
94+
/* Accel FIFO Watermark (high byte) */
95+
#define BMI08X_REG_ACCEL_FIFO_WTM_1 0x47
96+
97+
/* Accel FIFO Config (FIFO mode) */
98+
#define BMI08X_REG_ACCEL_FIFO_CONFIG_0 0x48
99+
100+
/* Accel FIFO Config (Interrupt enabling) */
101+
#define BMI08X_REG_ACCEL_FIFO_CONFIG_1 0x49
102+
80103
/* Accel Interrupt pin 1 configuration register */
81104
#define BMI08X_REG_ACCEL_INT1_IO_CONF 0x53
82105

@@ -262,6 +285,9 @@
262285
/* Gyro Interrupt status register */
263286
#define BMI08X_REG_GYRO_INT_STAT_1 0x0A
264287

288+
/* FIFO Status register (Overrun and Frame counter) */
289+
#define BMI08X_REG_FIFO_STATUS 0x0E
290+
265291
/* Gyro Range register */
266292
#define BMI08X_REG_GYRO_RANGE 0x0F
267293

@@ -283,9 +309,21 @@
283309
/* Gyro Interrupt Map register */
284310
#define BMI08X_REG_GYRO_INT3_INT4_IO_MAP 0x18
285311

312+
/* FIFO Watermark enable */
313+
#define BMI08X_REG_GYRO_FIFO_WM_EN 0x1E
314+
286315
/* Gyro Self test register */
287316
#define BMI08X_REG_GYRO_SELF_TEST 0x3C
288317

318+
/* FIFO Config register (FIFO Watermark) */
319+
#define BMI08X_REG_GYRO_FIFO_CONFIG_0 0x3D
320+
321+
/* FIFO Config register (FIFO Mode) */
322+
#define BMI08X_REG_GYRO_FIFO_CONFIG_1 0x3E
323+
324+
/* FIFO Data register */
325+
#define BMI08X_REG_GYRO_FIFO_DATA 0x3F
326+
289327
/* Gyro unique chip identifier */
290328
#define BMI08X_GYRO_CHIP_ID 0x0F
291329

@@ -469,8 +507,9 @@ struct bmi08x_gyro_bus_io {
469507
struct bmi08x_accel_config {
470508
union bmi08x_bus bus;
471509
const struct bmi08x_accel_bus_io *api;
472-
#if defined(CONFIG_BMI08X_ACCEL_TRIGGER)
473510
struct gpio_dt_spec int_gpio;
511+
#if defined(CONFIG_SENSOR_ASYNC_API)
512+
struct bmi08x_rtio_bus rtio_bus;
474513
#endif
475514
#if defined(CONFIG_BMI08X_ACCEL_TRIGGER) || BMI08X_ACCEL_ANY_INST_HAS_DATA_SYNC
476515
uint8_t int1_map;
@@ -488,8 +527,9 @@ struct bmi08x_accel_config {
488527
struct bmi08x_gyro_config {
489528
union bmi08x_bus bus;
490529
const struct bmi08x_gyro_bus_io *api;
491-
#if defined(CONFIG_BMI08X_GYRO_TRIGGER)
492530
struct gpio_dt_spec int_gpio;
531+
#if defined(CONFIG_SENSOR_ASYNC_API)
532+
struct bmi08x_rtio_bus rtio_bus;
493533
#endif
494534
#if defined(CONFIG_BMI08X_GYRO_TRIGGER) || BMI08X_GYRO_ANY_INST_HAS_DATA_SYNC
495535
uint8_t int3_4_map;
@@ -500,19 +540,27 @@ struct bmi08x_gyro_config {
500540
};
501541

502542
struct bmi08x_accel_data {
503-
#if defined(CONFIG_BMI08X_ACCEL_TRIGGER)
543+
const struct device *dev;
544+
#if defined(CONFIG_BMI08X_ACCEL_TRIGGER) || defined(CONFIG_SENSOR_ASYNC_API)
504545
struct gpio_callback gpio_cb;
505546
#endif
506547
uint16_t acc_sample[3];
507548
uint16_t scale; /* micro m/s^2/lsb */
549+
uint16_t range;
550+
#if defined(CONFIG_SENSOR_ASYNC_API)
551+
struct {
552+
struct rtio_iodev_sqe *iodev_sqe;
553+
atomic_t state;
554+
uint8_t fifo_wm;
555+
} stream;
556+
#endif
508557

509558
#if defined(CONFIG_BMI08X_ACCEL_TRIGGER_OWN_THREAD)
510559
K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_BMI08X_ACCEL_THREAD_STACK_SIZE);
511560
struct k_thread thread;
512561
struct k_sem sem;
513562
#elif defined(CONFIG_BMI08X_ACCEL_TRIGGER_GLOBAL_THREAD)
514563
struct k_work work;
515-
const struct device *dev;
516564
#endif
517565

518566
#ifdef CONFIG_BMI08X_ACCEL_TRIGGER
@@ -523,19 +571,27 @@ struct bmi08x_accel_data {
523571
};
524572

525573
struct bmi08x_gyro_data {
526-
#if defined(CONFIG_BMI08X_GYRO_TRIGGER)
574+
const struct device *dev;
575+
#if defined(CONFIG_BMI08X_GYRO_TRIGGER) || defined(CONFIG_SENSOR_ASYNC_API)
527576
struct gpio_callback gpio_cb;
528577
#endif
529578
uint16_t gyr_sample[3];
530579
uint16_t scale; /* micro radians/s/lsb */
580+
uint16_t range;
581+
#if defined(CONFIG_SENSOR_ASYNC_API)
582+
struct {
583+
struct rtio_iodev_sqe *iodev_sqe;
584+
atomic_t state;
585+
uint8_t fifo_wm;
586+
} stream;
587+
#endif
531588

532589
#if defined(CONFIG_BMI08X_GYRO_TRIGGER_OWN_THREAD)
533590
K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_BMI08X_GYRO_THREAD_STACK_SIZE);
534591
struct k_thread thread;
535592
struct k_sem sem;
536593
#elif defined(CONFIG_BMI08X_GYRO_TRIGGER_GLOBAL_THREAD)
537594
struct k_work work;
538-
const struct device *dev;
539595
#endif
540596

541597
#ifdef CONFIG_BMI08X_GYRO_TRIGGER
@@ -544,6 +600,62 @@ struct bmi08x_gyro_data {
544600
#endif /* CONFIG_BMI08X_GYRO_TRIGGER */
545601
};
546602

603+
struct bmi08x_accel_frame {
604+
uint8_t header;
605+
union {
606+
struct {
607+
uint16_t payload[3];
608+
} accel;
609+
struct {
610+
uint8_t skipped_frames;
611+
} skip;
612+
struct {
613+
uint8_t time[3];
614+
} sensortime;
615+
struct {
616+
uint8_t change;
617+
} fifo_config;
618+
};
619+
} __packed;
620+
621+
struct bmi08x_gyro_frame {
622+
uint16_t payload[3];
623+
} __packed;
624+
625+
struct bmi08x_accel_encoded_data {
626+
struct {
627+
uint64_t timestamp;
628+
uint16_t range;
629+
uint8_t chip_id;
630+
bool has_accel;
631+
bool is_streaming;
632+
uint16_t fifo_len;
633+
uint8_t sample_count;
634+
uint16_t buf_len;
635+
} header;
636+
union {
637+
uint16_t payload[3];
638+
uint8_t fifo[0]; /* Left as bytes since it can contain multiple frames */
639+
};
640+
};
641+
642+
struct bmi08x_gyro_encoded_data {
643+
struct {
644+
uint64_t timestamp;
645+
uint16_t range;
646+
bool has_gyro;
647+
bool is_streaming;
648+
uint8_t int_status;
649+
uint8_t fifo_status;
650+
uint8_t sample_count;
651+
} header;
652+
union {
653+
struct bmi08x_gyro_frame frame;
654+
struct bmi08x_gyro_frame fifo[0];
655+
} __packed;
656+
};
657+
658+
547659
/* common functions for accel and gyro */
548660
int bmi08x_freq_to_odr_val(uint16_t freq_int, uint16_t freq_milli);
549661
int32_t bmi08x_range_to_reg_val(uint16_t range, const struct bmi08x_range *range_map,

drivers/sensor/bosch/bmi08x/bmi08x_accel.c

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,21 @@
66
*/
77

88
#include <zephyr/drivers/sensor.h>
9+
#include <zephyr/drivers/sensor_clock.h>
910
#include <zephyr/pm/device.h>
1011
#include <zephyr/init.h>
1112
#include <zephyr/kernel.h>
1213
#include <zephyr/logging/log.h>
1314
#include <zephyr/sys/__assert.h>
1415
#include <zephyr/sys/byteorder.h>
16+
#include <zephyr/sys/check.h>
1517

1618
#define DT_DRV_COMPAT bosch_bmi08x_accel
1719
#include "bmi08x.h"
1820
#include "bmi08x_config_file.h"
21+
#include "bmi08x_accel_async.h"
22+
#include "bmi08x_accel_stream.h"
23+
#include "bmi08x_accel_decoder.h"
1924

2025
LOG_MODULE_REGISTER(BMI08X_ACCEL, CONFIG_SENSOR_LOG_LEVEL);
2126

@@ -320,6 +325,7 @@ static int bmi08x_acc_range_set(const struct device *dev, int32_t range)
320325
}
321326

322327
data->scale = BMI08X_ACC_SCALE(range);
328+
data->range = reg_val;
323329

324330
return ret;
325331
}
@@ -538,6 +544,10 @@ static DEVICE_API(sensor, bmi08x_api) = {
538544
.attr_set = bmi08x_attr_set,
539545
#ifdef CONFIG_BMI08X_ACCEL_TRIGGER
540546
.trigger_set = bmi08x_trigger_set_acc,
547+
#endif
548+
#ifdef CONFIG_SENSOR_ASYNC_API
549+
.submit = bmi08x_accel_async_submit,
550+
.get_decoder = bmi08x_accel_decoder_get,
541551
#endif
542552
.sample_fetch = bmi08x_sample_fetch,
543553
.channel_get = bmi08x_channel_get,
@@ -719,6 +729,14 @@ int bmi08x_accel_init(const struct device *dev)
719729
}
720730
#endif
721731

732+
#if defined(CONFIG_BMI08X_ACCEL_STREAM)
733+
ret = bmi08x_accel_stream_init(dev);
734+
if (ret < 0) {
735+
LOG_ERR("Failed to init stream: %d", ret);
736+
return ret;
737+
}
738+
#endif
739+
722740
return ret;
723741
}
724742

@@ -784,22 +802,44 @@ int bmi08x_accel_init(const struct device *dev)
784802

785803
#define BMI08X_CREATE_INST(inst) \
786804
\
805+
RTIO_DEFINE(bmi08x_accel_rtio_ctx_##inst, 16, 16); \
806+
\
807+
COND_CODE_1(DT_INST_ON_BUS(inst, i2c), \
808+
(I2C_DT_IODEV_DEFINE(bmi08x_accel_rtio_bus_##inst, \
809+
DT_DRV_INST(inst))), \
810+
(COND_CODE_1(DT_INST_ON_BUS(inst, spi), \
811+
(SPI_DT_IODEV_DEFINE(bmi08x_accel_rtio_bus_##inst, \
812+
DT_DRV_INST(inst), \
813+
SPI_OP_MODE_MASTER | SPI_WORD_SET(8) | SPI_TRANSFER_MSB)),\
814+
()))); \
815+
\
787816
IF_ENABLED(BMI08X_ACCEL_DATA_SYNC_EN(inst), (BMI08X_VERIFY_DATA_SYNC(inst);)) \
788817
IF_ENABLED(BMI08X_ACCEL_DATA_SYNC_EN(inst), (BMI08X_VERIFY_DATA_SYNC_ODR(inst);)) \
789818
IF_ENABLED(BMI08X_ACCEL_DATA_SYNC_EN(inst), (BMI08X_VERIFY_GYRO_DATA_SYNC_EN(inst);)) \
790819
\
791-
static struct bmi08x_accel_data bmi08x_drv_##inst; \
820+
static struct bmi08x_accel_data bmi08x_drv_##inst = { \
821+
IF_ENABLED(CONFIG_BMI08X_ACCEL_STREAM, \
822+
(.stream.fifo_wm = DT_INST_PROP_OR(inst, fifo_watermark, 0),)) \
823+
}; \
824+
\
792825
\
793826
static const struct bmi08x_accel_config bmi08x_config_##inst = { \
794827
COND_CODE_1(DT_INST_ON_BUS(inst, spi), (BMI08X_CONFIG_SPI(inst)), \
795828
(BMI08X_CONFIG_I2C(inst))) \
796829
.api = COND_CODE_1(DT_INST_ON_BUS(inst, spi), (&bmi08x_spi_api), \
797830
(&bmi08x_i2c_api)), \
798-
IF_ENABLED(CONFIG_BMI08X_ACCEL_TRIGGER, \
799-
(.int_gpio = GPIO_DT_SPEC_INST_GET(inst, int_gpios),)) \
831+
.int_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, int_gpios, {0}), \
800832
BMI08X_ACCEL_TRIGGER_PINS(inst) \
801833
.accel_hz = DT_INST_ENUM_IDX(inst, accel_hz) + 5, \
802-
.accel_fs = DT_INST_PROP(inst, accel_fs), BMI08X_DATA_SYNC_REG(inst)}; \
834+
.rtio_bus = { \
835+
.ctx = &bmi08x_accel_rtio_ctx_##inst, \
836+
.iodev = &bmi08x_accel_rtio_bus_##inst, \
837+
.type = COND_CODE_1(DT_INST_ON_BUS(inst, i2c), \
838+
(BMI08X_RTIO_BUS_TYPE_I2C), \
839+
(BMI08X_RTIO_BUS_TYPE_SPI)), \
840+
}, \
841+
.accel_fs = DT_INST_PROP(inst, accel_fs), BMI08X_DATA_SYNC_REG(inst) \
842+
}; \
803843
\
804844
PM_DEVICE_DT_INST_DEFINE(inst, bmi08x_accel_pm_action); \
805845
SENSOR_DEVICE_DT_INST_DEFINE(inst, bmi08x_accel_init, PM_DEVICE_DT_INST_GET(inst), \

0 commit comments

Comments
 (0)